Thread: [pgsqlclient-checkins] pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Cryptography CryptoT
Status: Inactive
Brought to you by:
carlosga_fb
Update of /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Cryptography In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24444 Modified Files: ARC4Managed.cs RC4.cs RSAManaged.cs Added Files: CryptoTools.cs PKCS8.cs Log Message: Sync security stuff with mono CVS classes. --- NEW FILE: CryptoTools.cs --- // // Mono.Security.Cryptography.CryptoTools // Shared class for common cryptographic functionalities // // Authors: // Sebastien Pouliot (spo...@mo...) // // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com) // using System; using System.Security.Cryptography; namespace Mono.Security.Cryptography { internal class KeyBuilder { static private RandomNumberGenerator rng; static KeyBuilder () { rng = RandomNumberGenerator.Create (); } static public byte[] Key (int size) { byte[] key = new byte [size]; rng.GetBytes (key); return key; } static public byte[] IV (int size) { byte[] iv = new byte [size]; rng.GetBytes (iv); return iv; } } // Process an array as a sequence of blocks internal class BlockProcessor { private ICryptoTransform transform; private byte[] block; private int blockSize; // in bytes (not in bits) private int blockCount; public BlockProcessor (ICryptoTransform transform) : this (transform, transform.InputBlockSize) {} // some Transforms (like HashAlgorithm descendant) return 1 for // block size (which isn't their real internal block size) public BlockProcessor (ICryptoTransform transform, int blockSize) { this.transform = transform; this.blockSize = blockSize; block = new byte [blockSize]; } ~BlockProcessor () { // zeroize our block (so we don't retain any information) Array.Clear (block, 0, blockSize); } public void Initialize () { Array.Clear (block, 0, blockSize); blockCount = 0; } public void Core (byte[] rgb) { Core (rgb, 0, rgb.Length); } public void Core (byte[] rgb, int ib, int cb) { // 1. fill the rest of the "block" int n = System.Math.Min (blockSize - blockCount, cb); Array.Copy (rgb, ib, block, blockCount, n); blockCount += n; // 2. if block is full then transform it if (blockCount == blockSize) { transform.TransformBlock (block, 0, blockSize, block, 0); // 3. transform any other full block in specified buffer int b = (int) ((cb - n) / blockSize); for (int i=0; i < b; i++) { transform.TransformBlock (rgb, n, blockSize, block, 0); n += blockSize; } // 4. if data is still present fill the "block" with the remainder blockCount = cb - n; if (blockCount > 0) Array.Copy (rgb, n, block, 0, blockCount); } } public byte[] Final () { return transform.TransformFinalBlock (block, 0, blockCount); } } } --- NEW FILE: PKCS8.cs --- // // PKCS8.cs: PKCS #8 - Private-Key Information Syntax Standard // ftp://ftp.rsasecurity.com/pub/pkcs/doc/pkcs-8.doc // // Author: // Sebastien Pouliot (spo...@mo...) // // (C) 2003 Motus Technologies Inc. (http://www.motus.com) // using System; using System.Collections; using System.Security.Cryptography; using System.Text; using Mono.Security.Cryptography; using Mono.Security.X509; namespace Mono.Security.Cryptography { internal class PKCS8 { public enum KeyInfo { PrivateKey, EncryptedPrivateKey, Unknown } static public KeyInfo GetType (byte[] data) { if (data == null) throw new ArgumentNullException ("data"); KeyInfo ki = KeyInfo.Unknown; try { ASN1 top = new ASN1 (data); if ((top.Tag == 0x30) && (top.Count > 0)) { ASN1 firstLevel = top [0]; switch (firstLevel.Tag) { case 0x02: ki = KeyInfo.PrivateKey; break; case 0x30: ki = KeyInfo.EncryptedPrivateKey; break; } } } catch { throw new CryptographicException ("invalid ASN.1 data"); } return ki; } /* * PrivateKeyInfo ::= SEQUENCE { * version Version, * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, * privateKey PrivateKey, * attributes [0] IMPLICIT Attributes OPTIONAL * } * * Version ::= INTEGER * * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier * * PrivateKey ::= OCTET STRING * * Attributes ::= SET OF Attribute */ public class PrivateKeyInfo { private int _version; private string _algorithm; private byte[] _key; private ArrayList _list; public PrivateKeyInfo () { _version = 0; _list = new ArrayList (); } public PrivateKeyInfo (byte[] data) : this () { Decode (data); } // properties public string Algorithm { get { return _algorithm; } set { _algorithm = value; } } public ArrayList Attributes { get { return _list; } } public byte[] PrivateKey { get { return _key; } set { _key = value; } } public int Version { get { return _version; } set { if (_version < 0) throw new ArgumentOutOfRangeException ("negative version"); _version = value; } } // methods private void Decode (byte[] data) { ASN1 privateKeyInfo = new ASN1 (data); if (privateKeyInfo.Tag != 0x30) throw new CryptographicException ("invalid PrivateKeyInfo"); ASN1 version = privateKeyInfo [0]; if (version.Tag != 0x02) throw new CryptographicException ("invalid version"); _version = version.Value [0]; ASN1 privateKeyAlgorithm = privateKeyInfo [1]; if (privateKeyAlgorithm.Tag != 0x30) throw new CryptographicException ("invalid algorithm"); ASN1 algorithm = privateKeyAlgorithm [0]; if (algorithm.Tag != 0x06) throw new CryptographicException ("missing algorithm OID"); _algorithm = ASN1Convert.ToOID (algorithm); ASN1 privateKey = privateKeyInfo [2]; _key = privateKey.Value; // attributes [0] IMPLICIT Attributes OPTIONAL if (privateKeyInfo.Count > 3) { ASN1 attributes = privateKeyInfo [3]; for (int i=0; i < attributes.Count; i++) { _list.Add (attributes [i]); } } } // TODO public byte[] GetBytes () { return null; } // static methods static private byte[] RemoveLeadingZero (byte[] bigInt) { int start = 0; int length = bigInt.Length; if (bigInt [0] == 0x00) { start = 1; length--; } byte[] bi = new byte [length]; Buffer.BlockCopy (bigInt, start, bi, 0, length); return bi; } static private byte[] Normalize (byte[] bigInt, int length) { if (bigInt.Length == length) return bigInt; else if (bigInt.Length > length) return RemoveLeadingZero (bigInt); else { // pad with 0 byte[] bi = new byte [length]; Buffer.BlockCopy (bigInt, 0, bi, (length - bigInt.Length), bigInt.Length); return bi; } } /* * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER, -- (inverse of q) mod p * otherPrimeInfos OtherPrimeInfos OPTIONAL * } */ static public RSA DecodeRSA (byte[] encryptedKeypair) { ASN1 privateKey = new ASN1 (encryptedKeypair); if (privateKey.Tag != 0x30) throw new CryptographicException ("invalid private key format"); ASN1 version = privateKey [0]; if (version.Tag != 0x02) throw new CryptographicException ("missing version"); if (privateKey.Count < 9) throw new CryptographicException ("not enough key parameters"); RSAParameters param = new RSAParameters (); // note: MUST remove leading 0 - else MS wont import the key param.Modulus = RemoveLeadingZero (privateKey [1].Value); int keysize = param.Modulus.Length; int keysize2 = (keysize >> 1); // half-size // size must be normalized - else MS wont import the key param.D = Normalize (privateKey [3].Value, keysize); param.DP = Normalize (privateKey [6].Value, keysize2); param.DQ = Normalize (privateKey [7].Value, keysize2); param.Exponent = RemoveLeadingZero (privateKey [2].Value); param.InverseQ = Normalize (privateKey [8].Value, keysize2); param.P = Normalize (privateKey [4].Value, keysize2); param.Q = Normalize (privateKey [5].Value, keysize2); RSA rsa = RSA.Create (); rsa.ImportParameters (param); return rsa; } // DSA only encode it's X private key inside an ASN.1 INTEGER (Hint: Tag == 0x02) // which isn't enough for rebuilding the keypair. The other parameters // can be found (98% of the time) in the X.509 certificate associated // with the private key or (2% of the time) the parameters are in it's // issuer X.509 certificate (not supported in the .NET framework). static public DSA DecodeDSA (byte[] encryptedPrivateKey, DSAParameters dsaParameters) { ASN1 privateKey = new ASN1 (encryptedPrivateKey); if (privateKey.Tag != 0x02) throw new CryptographicException ("invalid private key format"); // X is ALWAYS 20 bytes (no matter if the key length is 512 or 1024 bits) dsaParameters.X = Normalize (encryptedPrivateKey, 20); DSA dsa = DSA.Create (); dsa.ImportParameters (dsaParameters); return dsa; } } /* * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptedData EncryptedData * } * * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier * * EncryptedData ::= OCTET STRING * * -- * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } * * -- from PKCS#5 * PBEParameter ::= SEQUENCE { * salt OCTET STRING SIZE(8), * iterationCount INTEGER * } */ public class EncryptedPrivateKeyInfo { private string _algorithm; private byte[] _salt; private int _iterations; private byte[] _data; public EncryptedPrivateKeyInfo () {} public EncryptedPrivateKeyInfo (byte[] data) : this () { Decode (data); } // properties public string Algorithm { get { return _algorithm; } } public byte[] EncryptedData { get { return (byte[]) _data.Clone (); } } public byte[] Salt { get { return (byte[]) _salt.Clone (); } } public int IterationCount { get { return _iterations; } } // methods private void Decode (byte[] data) { ASN1 encryptedPrivateKeyInfo = new ASN1 (data); if (encryptedPrivateKeyInfo.Tag != 0x30) throw new CryptographicException ("invalid EncryptedPrivateKeyInfo"); ASN1 encryptionAlgorithm = encryptedPrivateKeyInfo [0]; if (encryptionAlgorithm.Tag != 0x30) throw new CryptographicException ("invalid encryptionAlgorithm"); ASN1 algorithm = encryptionAlgorithm [0]; if (algorithm.Tag != 0x06) throw new CryptographicException ("invalid algorithm"); _algorithm = ASN1Convert.ToOID (algorithm); // parameters ANY DEFINED BY algorithm OPTIONAL if (encryptionAlgorithm.Count > 1) { ASN1 parameters = encryptionAlgorithm [1]; if (parameters.Tag != 0x30) throw new CryptographicException ("invalid parameters"); ASN1 salt = parameters [0]; if (salt.Tag != 0x04) throw new CryptographicException ("invalid salt"); _salt = salt.Value; ASN1 iterationCount = parameters [1]; if (iterationCount.Tag != 0x02) throw new CryptographicException ("invalid iterationCount"); _iterations = ASN1Convert.ToInt32 (iterationCount); } ASN1 encryptedData = encryptedPrivateKeyInfo [1]; if (encryptedData.Tag != 0x04) throw new CryptographicException ("invalid EncryptedData"); _data = encryptedData.Value; } // Note: PKCS#8 doesn't define how to generate the key required for encryption // so you're on your own. Just don't try to copy the big guys too much ;) // Netscape: http://www.cs.auckland.ac.nz/~pgut001/pubs/netscape.txt // Microsoft: http://www.cs.auckland.ac.nz/~pgut001/pubs/breakms.txt public byte[] GetBytes (byte[] encryptedPrivateKey) { // TODO return null; } } } } Index: ARC4Managed.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Cryptography/ARC4Managed.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ARC4Managed.cs 10 Feb 2004 09:43:04 -0000 1.1 --- ARC4Managed.cs 5 Mar 2004 23:15:21 -0000 1.2 *************** *** 13,17 **** // http://www.qrst.de/html/dsds/rc4.htm ! internal class ARC4Managed : RC4, ICryptoTransform { private byte[] key; --- 13,17 ---- // http://www.qrst.de/html/dsds/rc4.htm ! public class ARC4Managed : RC4, ICryptoTransform { private byte[] key; *************** *** 80,87 **** public override void GenerateKey () { ! byte[] key = new byte [KeySizeValue >> 3]; ! RandomNumberGenerator rng = RandomNumberGenerator.Create (); ! rng.GetBytes (key); ! Key = key; } --- 80,84 ---- public override void GenerateKey () { ! Key = KeyBuilder.Key (KeySizeValue >> 3); } *************** *** 108,112 **** y = 0; for (int counter = 0; counter < 256; counter++) { ! index2 = (byte) ((key [index1] + state [counter] + index2) % 256); // swap byte byte tmp = state [counter]; --- 105,109 ---- y = 0; for (int counter = 0; counter < 256; counter++) { ! index2 = (byte) (key [index1] + state [counter] + index2); // swap byte byte tmp = state [counter]; *************** *** 121,126 **** byte xorIndex; for (int counter = 0; counter < inputCount; counter ++) { ! x = (byte) ((x + 1) % 256); ! y = (byte) ((state [x] + y) % 256); // swap byte byte tmp = state [x]; --- 118,123 ---- byte xorIndex; for (int counter = 0; counter < inputCount; counter ++) { ! x = (byte) (x + 1); ! y = (byte) (state [x] + y); // swap byte byte tmp = state [x]; *************** *** 128,132 **** state [y] = tmp; ! xorIndex = (byte) (state [x] + (state [y]) % 256); outputBuffer [outputOffset + counter] = (byte) (inputBuffer [inputOffset + counter] ^ state [xorIndex]); } --- 125,129 ---- state [y] = tmp; ! xorIndex = (byte) (state [x] + state [y]); outputBuffer [outputOffset + counter] = (byte) (inputBuffer [inputOffset + counter] ^ state [xorIndex]); } Index: RC4.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Cryptography/RC4.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RC4.cs 10 Feb 2004 09:43:04 -0000 1.1 --- RC4.cs 5 Mar 2004 23:15:21 -0000 1.2 *************** *** 14,18 **** namespace Mono.Security.Cryptography { ! internal abstract class RC4 : SymmetricAlgorithm { private static KeySizes[] s_legalBlockSizes = { --- 14,18 ---- namespace Mono.Security.Cryptography { ! public abstract class RC4 : SymmetricAlgorithm { private static KeySizes[] s_legalBlockSizes = { Index: RSAManaged.cs =================================================================== RCS file: /cvsroot/pgsqlclient/pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Cryptography/RSAManaged.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RSAManaged.cs 10 Feb 2004 09:43:04 -0000 1.1 --- RSAManaged.cs 5 Mar 2004 23:15:21 -0000 1.2 *************** *** 28,32 **** namespace Mono.Security.Cryptography { ! internal class RSAManaged : RSA { private const int defaultKeySize = 1024; --- 28,37 ---- namespace Mono.Security.Cryptography { ! #if INSIDE_CORLIB ! internal ! #else ! public ! #endif ! class RSAManaged : RSA { private const int defaultKeySize = 1024; *************** *** 109,112 **** --- 114,120 ---- keypairGenerated = true; isCRTpossible = true; + + if (KeyGenerated != null) + KeyGenerated (this); } *************** *** 126,129 **** --- 134,143 ---- } + // note: this property will exist in RSACryptoServiceProvider in + // version 1.2 of the framework + public bool PublicOnly { + get { return ((d == null) || (n == null)); } + } + public override string SignatureAlgorithm { get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; } *************** *** 288,291 **** --- 302,309 ---- m_disposed = true; } + + public delegate void KeyGeneratedEventHandler (object sender); + + public event KeyGeneratedEventHandler KeyGenerated; } } |