[pgsqlclient-checkins] pgsqlclient_10/Mono.Security/Mono.Security/Mono.Security.Cryptography ARC4Man
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-serv901 Added Files: ARC4Managed.cs HMAC.cs MD5SHA1.cs PKCS1.cs RC4.cs RSAManaged.cs Log Message: Reorganization to match mono:: cvs structure --- NEW FILE: ARC4Managed.cs --- // // ARC4Managed.cs: Alleged RC4(tm) compatible symmetric stream cipher // RC4 is a trademark of RSA Security // using System; using System.Security.Cryptography; namespace Mono.Security.Cryptography { // References: // a. Usenet 1994 - RC4 Algorithm revealed // http://www.qrst.de/html/dsds/rc4.htm internal class ARC4Managed : RC4, ICryptoTransform { private byte[] key; private byte[] state; private byte x; private byte y; private bool m_disposed; public ARC4Managed () : base () { state = new byte [256]; m_disposed = false; } ~ARC4Managed () { Dispose (true); } protected override void Dispose (bool disposing) { if (!m_disposed) { x = 0; y = 0; if (key != null) { Array.Clear (key, 0, key.Length); key = null; } Array.Clear (state, 0, state.Length); state = null; GC.SuppressFinalize (this); m_disposed = true; } } public override byte[] Key { get { return (byte[]) key.Clone (); } set { key = (byte[]) value.Clone (); KeySetup (key); } } public bool CanReuseTransform { get { return false; } } public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgvIV) { Key = rgbKey; return (ICryptoTransform) this; } public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgvIV) { Key = rgbKey; return CreateEncryptor (); } public override void GenerateIV () { // not used for a stream cipher IV = new byte [0]; } public override void GenerateKey () { byte[] key = new byte [KeySizeValue >> 3]; RandomNumberGenerator rng = RandomNumberGenerator.Create (); rng.GetBytes (key); Key = key; } public bool CanTransformMultipleBlocks { get { return true; } } public int InputBlockSize { get { return 1; } } public int OutputBlockSize { get { return 1; } } private void KeySetup (byte[] key) { byte index1 = 0; byte index2 = 0; for (int counter = 0; counter < 256; counter++) state [counter] = (byte) counter; x = 0; y = 0; for (int counter = 0; counter < 256; counter++) { index2 = (byte) ((key [index1] + state [counter] + index2) % 256); // swap byte byte tmp = state [counter]; state [counter] = state [index2]; state [index2] = tmp; index1 = (byte) ((index1 + 1) % key.Length); } } public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { 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]; state [x] = state [y]; state [y] = tmp; xorIndex = (byte) (state [x] + (state [y]) % 256); outputBuffer [outputOffset + counter] = (byte) (inputBuffer [inputOffset + counter] ^ state [xorIndex]); } return inputCount; } public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) { byte[] output = new byte [inputCount]; TransformBlock (inputBuffer, inputOffset, inputCount, output, 0); return output; } } } --- NEW FILE: HMAC.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ using System; using System.Security.Cryptography; namespace Mono.Security.Cryptography { /* * References: * RFC 2104 (http://www.ietf.org/rfc/rfc2104.txt) * RFC 2202 (http://www.ietf.org/rfc/rfc2202.txt) * MSDN: * * Extending the KeyedHashAlgorithm Class (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconextendingkeyedhashalgorithmclass.asp) */ internal class HMAC : System.Security.Cryptography.KeyedHashAlgorithm { #region Fields private HashAlgorithm hash; private bool hashing; private byte[] innerPad; private byte[] outerPad; #endregion #region Properties public override byte[] Key { get { return (byte[])KeyValue.Clone(); } set { if (hashing) { throw new Exception("Cannot change key during hash operation."); } /* if key is longer than 64 bytes reset it to rgbKey = Hash(rgbKey) */ if (value.Length > 64) { KeyValue = hash.ComputeHash(value); } else { KeyValue = (byte[])value.Clone(); } initializePad(); } } #endregion #region Constructors public HMAC() { // Create the hash hash = MD5.Create(); // Set HashSizeValue HashSizeValue = hash.HashSize; // Generate a radom key byte[] rgbKey = new byte[64]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetNonZeroBytes(rgbKey); KeyValue = (byte[])rgbKey.Clone(); this.Initialize(); } public HMAC(string hashName, byte[] rgbKey) { // Create the hash if (hashName == null || hashName.Length == 0) { hashName = "MD5"; } hash = HashAlgorithm.Create(hashName); // Set HashSizeValue HashSizeValue = hash.HashSize; /* if key is longer than 64 bytes reset it to rgbKey = Hash(rgbKey) */ if (rgbKey.Length > 64) { KeyValue = hash.ComputeHash(rgbKey); } else { KeyValue = (byte[])rgbKey.Clone(); } this.Initialize(); } #endregion #region Methods public override void Initialize() { hash.Initialize(); initializePad(); hashing = false; } protected override byte[] HashFinal() { if (!hashing) { hash.TransformBlock(innerPad, 0, innerPad.Length, innerPad, 0); hashing = true; } // Finalize the original hash hash.TransformFinalBlock(new byte[0], 0, 0); byte[] firstResult = hash.Hash; hash.Initialize(); hash.TransformBlock(outerPad, 0, outerPad.Length, outerPad, 0); hash.TransformFinalBlock(firstResult, 0, firstResult.Length); Initialize(); return hash.Hash; } protected override void HashCore( byte[] array, int ibStart, int cbSize) { if (!hashing) { hash.TransformBlock(innerPad, 0, innerPad.Length, innerPad, 0); hashing = true; } hash.TransformBlock(array, ibStart, cbSize, array, ibStart); } #endregion #region Private Methods private void initializePad() { // Fill pad arrays innerPad = new byte[64]; outerPad = new byte[64]; /* Pad the key for inner and outer digest */ for (int i = 0 ; i < KeyValue.Length; ++i) { innerPad[i] = (byte)(KeyValue[i] ^ 0x36); outerPad[i] = (byte)(KeyValue[i] ^ 0x5C); } for (int i = KeyValue.Length; i < 64; ++i) { innerPad[i] = 0x36; outerPad[i] = 0x5C; } } #endregion } } --- NEW FILE: MD5SHA1.cs --- /* Transport Security Layer (TLS) * Copyright (c) 2003-2004 Carlos Guzman Alvarez * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ using System; using System.Security.Cryptography; using Mono.Security.Protocol.Tls; namespace Mono.Security.Cryptography { internal class MD5SHA1 : HashAlgorithm { #region Fields private HashAlgorithm md5; private HashAlgorithm sha; private bool hashing; #endregion #region Constructors public MD5SHA1() : base() { this.md5 = MD5.Create(); this.sha = SHA1.Create(); // Set HashSizeValue this.HashSizeValue = this.md5.HashSize + this.sha.HashSize; } #endregion #region Methods public override void Initialize() { this.md5.Initialize(); this.sha.Initialize(); this.hashing = false; } protected override byte[] HashFinal() { if (!hashing) { this.hashing = true; } // Finalize the original hash this.md5.TransformFinalBlock(new byte[0], 0, 0); this.sha.TransformFinalBlock(new byte[0], 0, 0); byte[] hash = new byte[36]; System.Array.Copy(this.md5.Hash, 0, hash, 0, 16); System.Array.Copy(this.sha.Hash, 0, hash, 16, 20); return hash; } protected override void HashCore( byte[] array, int ibStart, int cbSize) { if (!hashing) { hashing = true; } this.md5.TransformBlock(array, ibStart, cbSize, array, ibStart); this.sha.TransformBlock(array, ibStart, cbSize, array, ibStart); } public byte[] CreateSignature(RSA rsa) { if (rsa == null) { throw new CryptographicUnexpectedOperationException ("missing key"); } RSASslSignatureFormatter f = new RSASslSignatureFormatter(rsa); f.SetHashAlgorithm("MD5SHA1"); return f.CreateSignature(this.Hash); } public bool VerifySignature(RSA rsa, byte[] rgbSignature) { if (rsa == null) { throw new CryptographicUnexpectedOperationException ("missing key"); } if (rgbSignature == null) { throw new ArgumentNullException ("rgbSignature"); } RSASslSignatureDeformatter d = new RSASslSignatureDeformatter(rsa); d.SetHashAlgorithm("MD5SHA1"); return d.VerifySignature(this.Hash, rgbSignature); } #endregion } } --- NEW FILE: PKCS1.cs --- // // PKCS1.cs - Implements PKCS#1 primitives. // // Author: // Sebastien Pouliot (spo...@mo...) // // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com) // using System; using System.Security.Cryptography; namespace Mono.Security.Cryptography { // References: // a. PKCS#1: RSA Cryptography Standard // http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/index.html internal class PKCS1 { private static bool Compare (byte[] array1, byte[] array2) { bool result = (array1.Length == array2.Length); if (result) { for (int i=0; i < array1.Length; i++) if (array1[i] != array2[i]) return false; } return result; } private static byte[] xor (byte[] array1, byte[] array2) { byte[] result = new byte [array1.Length]; for (int i=0; i < result.Length; i++) result[i] = (byte) (array1[i] ^ array2[i]); return result; } private static byte[] emptySHA1 = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 }; private static byte[] emptySHA256 = { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }; private static byte[] emptySHA384 = { 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b }; private static byte[] emptySHA512 = { 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e }; private static byte[] GetEmptyHash (HashAlgorithm hash) { if (hash is SHA1) return emptySHA1; else if (hash is SHA256) return emptySHA256; else if (hash is SHA384) return emptySHA384; else if (hash is SHA512) return emptySHA512; else return hash.ComputeHash ((byte[])null); } // PKCS #1 v.2.1, Section 4.1 // I2OSP converts a non-negative integer to an octet string of a specified length. public static byte[] I2OSP (int x, int size) { byte[] array = BitConverter.GetBytes (x); Array.Reverse (array, 0, array.Length); return I2OSP (array, size); } public static byte[] I2OSP (byte[] x, int size) { byte[] result = new byte [size]; Array.Copy (x, 0, result, (result.Length - x.Length), x.Length); return result; } // PKCS #1 v.2.1, Section 4.2 // OS2IP converts an octet string to a nonnegative integer. public static byte[] OS2IP (byte[] x) { int i = 0; while ((x [i++] == 0x00) && (i < x.Length)); i--; if (i > 0) { byte[] result = new byte [x.Length - i]; Array.Copy (x, i, result, 0, result.Length); return result; } else return x; } // PKCS #1 v.2.1, Section 5.1.1 public static byte[] RSAEP (RSA rsa, byte[] m) { // c = m^e mod n return rsa.EncryptValue (m); } // PKCS #1 v.2.1, Section 5.1.2 public static byte[] RSADP (RSA rsa, byte[] c) { // m = c^d mod n // Decrypt value may apply CRT optimizations return rsa.DecryptValue (c); } // PKCS #1 v.2.1, Section 5.2.1 public static byte[] RSASP1 (RSA rsa, byte[] m) { // first form: s = m^d mod n // Decrypt value may apply CRT optimizations return rsa.DecryptValue (m); } // PKCS #1 v.2.1, Section 5.2.2 public static byte[] RSAVP1 (RSA rsa, byte[] s) { // m = s^e mod n return rsa.EncryptValue (s); } // PKCS #1 v.2.1, Section 7.1.1 // RSAES-OAEP-ENCRYPT ((n, e), M, L) public static byte[] Encrypt_OAEP (RSA rsa, HashAlgorithm hash, RandomNumberGenerator rng, byte[] M) { int size = rsa.KeySize / 8; int hLen = hash.HashSize / 8; if (M.Length > size - 2 * hLen - 2) throw new CryptographicException ("message too long"); // empty label L SHA1 hash byte[] lHash = GetEmptyHash (hash); int PSLength = (size - M.Length - 2 * hLen - 2); // DB = lHash || PS || 0x01 || M byte[] DB = new byte [lHash.Length + PSLength + 1 + M.Length]; Array.Copy (lHash, 0, DB, 0, lHash.Length); DB [(lHash.Length + PSLength)] = 0x01; Array.Copy (M, 0, DB, (DB.Length - M.Length), M.Length); byte[] seed = new byte [hLen]; rng.GetBytes (seed); byte[] dbMask = MGF1 (hash, seed, size - hLen - 1); byte[] maskedDB = xor (DB, dbMask); byte[] seedMask = MGF1 (hash, maskedDB, hLen); byte[] maskedSeed = xor (seed, seedMask); // EM = 0x00 || maskedSeed || maskedDB byte[] EM = new byte [maskedSeed.Length + maskedDB.Length + 1]; Array.Copy (maskedSeed, 0, EM, 1, maskedSeed.Length); Array.Copy (maskedDB, 0, EM, maskedSeed.Length + 1, maskedDB.Length); byte[] m = OS2IP (EM); byte[] c = RSAEP (rsa, m); return I2OSP (c, size); } // PKCS #1 v.2.1, Section 7.1.2 // RSAES-OAEP-DECRYPT (K, C, L) public static byte[] Decrypt_OAEP (RSA rsa, HashAlgorithm hash, byte[] C) { int size = rsa.KeySize / 8; int hLen = hash.HashSize / 8; if ((size < (2 * hLen + 2)) || (C.Length != size)) throw new CryptographicException ("decryption error"); byte[] c = OS2IP (C); byte[] m = RSADP (rsa, c); byte[] EM = I2OSP (m, size); // split EM = Y || maskedSeed || maskedDB byte[] maskedSeed = new byte [hLen]; Array.Copy (EM, 1, maskedSeed, 0, maskedSeed.Length); byte[] maskedDB = new byte [size - hLen - 1]; Array.Copy (EM, (EM.Length - maskedDB.Length), maskedDB, 0, maskedDB.Length); byte[] seedMask = MGF1 (hash, maskedDB, hLen); byte[] seed = xor (maskedSeed, seedMask); byte[] dbMask = MGF1 (hash, seed, size - hLen - 1); byte[] DB = xor (maskedDB, dbMask); byte[] lHash = GetEmptyHash (hash); // split DB = lHash' || PS || 0x01 || M byte[] dbHash = new byte [lHash.Length]; Array.Copy (DB, 0, dbHash, 0, dbHash.Length); bool h = Compare (lHash, dbHash); // find separator 0x01 int nPos = lHash.Length; while (DB[nPos] == 0) nPos++; int Msize = DB.Length - nPos - 1; byte[] M = new byte [Msize]; Array.Copy (DB, (nPos + 1), M, 0, Msize); // we could have returned EM[0] sooner but would be helping a timing attack if ((EM[0] != 0) || (!h) || (DB[nPos] != 0x01)) return null; return M; } // PKCS #1 v.2.1, Section 7.2.1 // RSAES-PKCS1-V1_5-ENCRYPT ((n, e), M) public static byte[] Encrypt_v15 (RSA rsa, RandomNumberGenerator rng, byte[] M) { int size = rsa.KeySize / 8; if (M.Length > size - 11) throw new CryptographicException ("message too long"); int PSLength = System.Math.Max (8, (size - M.Length - 3)); byte[] PS = new byte [PSLength]; rng.GetNonZeroBytes (PS); byte[] EM = new byte [size]; EM [1] = 0x02; Array.Copy (PS, 0, EM, 2, PSLength); Array.Copy (M, 0, EM, (size - M.Length), M.Length); byte[] m = OS2IP (EM); byte[] c = RSAEP (rsa, m); byte[] C = I2OSP (c, size); return C; } // PKCS #1 v.2.1, Section 7.2.2 // RSAES-PKCS1-V1_5-DECRYPT (K, C) public static byte[] Decrypt_v15 (RSA rsa, byte[] C) { int size = rsa.KeySize / 8; if ((size < 11) || (C.Length != size)) throw new CryptographicException ("decryption error"); byte[] c = OS2IP (C); byte[] m = RSADP (rsa, c); byte[] EM = I2OSP (m, size); if ((EM [0] != 0x00) || (EM [1] != 0x02)) return null; int mPos = 10; // PS is a minimum of 8 bytes + 2 bytes for header while ((EM [mPos] != 0x00) && (mPos < EM.Length)) mPos++; if (EM [mPos] != 0x00) return null; mPos++; byte[] M = new byte [EM.Length - mPos]; Array.Copy (EM, mPos, M, 0, M.Length); return M; } // PKCS #1 v.2.1, Section 8.2.1 // RSASSA-PKCS1-V1_5-SIGN (K, M) public static byte[] Sign_v15 (RSA rsa, HashAlgorithm hash, byte[] hashValue) { int size = (rsa.KeySize >> 3); // div 8 byte[] EM = Encode_v15 (hash, hashValue, size); byte[] m = OS2IP (EM); byte[] s = RSASP1 (rsa, m); byte[] S = I2OSP (s, size); return S; } // PKCS #1 v.2.1, Section 8.2.2 // RSASSA-PKCS1-V1_5-VERIFY ((n, e), M, S) public static bool Verify_v15 (RSA rsa, HashAlgorithm hash, byte[] hashValue, byte[] signature) { int size = (rsa.KeySize >> 3); // div 8 byte[] s = OS2IP (signature); byte[] m = RSAVP1 (rsa, s); byte[] EM2 = I2OSP (m, size); byte[] EM = Encode_v15 (hash, hashValue, size); bool result = Compare (EM, EM2); if (!result) { // NOTE: some signatures don't include the hash OID (pretty lame but real) // and compatible with MS implementation if ((EM2 [0] != 0x00) || (EM2 [1] != 0x01)) return false; // TODO: add more validation byte[] decryptedHash = new byte [hashValue.Length]; Array.Copy (EM2, EM2.Length - hashValue.Length, decryptedHash, 0, decryptedHash.Length); result = Compare (decryptedHash, hashValue); } return result; } // PKCS #1 v.2.1, Section 9.2 // EMSA-PKCS1-v1_5-Encode public static byte[] Encode_v15 (HashAlgorithm hash, byte[] hashValue, int emLength) { if (hashValue.Length != (hash.HashSize >> 3)) throw new CryptographicException ("bad hash length for " + hash.ToString ()); // DigestInfo ::= SEQUENCE { // digestAlgorithm AlgorithmIdentifier, // digest OCTET STRING // } byte[] t = null; string oid = CryptoConfig.MapNameToOID (hash.ToString ()); if (oid != null) { ASN1 digestAlgorithm = new ASN1 (0x30); digestAlgorithm.Add (new ASN1 (CryptoConfig.EncodeOID (oid))); digestAlgorithm.Add (new ASN1 (0x05)); // NULL ASN1 digest = new ASN1 (0x04, hashValue); ASN1 digestInfo = new ASN1 (0x30); digestInfo.Add (digestAlgorithm); digestInfo.Add (digest); t = digestInfo.GetBytes (); } else { // There are no valid OID, in this case t = hashValue // This is the case of the MD5SHA hash algorithm t = hashValue; } Array.Copy (hashValue, 0, t, t.Length - hashValue.Length, hashValue.Length); int PSLength = System.Math.Max (8, emLength - t.Length - 3); // PS = PSLength of 0xff // EM = 0x00 | 0x01 | PS | 0x00 | T byte[] EM = new byte [PSLength + t.Length + 3]; EM [1] = 0x01; for (int i=2; i < PSLength + 2; i++) EM[i] = 0xff; Array.Copy (t, 0, EM, PSLength + 3, t.Length); return EM; } // PKCS #1 v.2.1, Section B.2.1 public static byte[] MGF1 (HashAlgorithm hash, byte[] mgfSeed, int maskLen) { // 1. If maskLen > 2^32 hLen, output "mask too long" and stop. // easy - this is impossible by using a int (31bits) as parameter ;-) // BUT with a signed int we do have to check for negative values! if (maskLen < 0) throw new OverflowException(); int mgfSeedLength = mgfSeed.Length; int hLen = (hash.HashSize >> 3); // from bits to bytes int iterations = (maskLen / hLen); if (maskLen % hLen != 0) iterations++; // 2. Let T be the empty octet string. byte[] T = new byte [iterations * hLen]; byte[] toBeHashed = new byte [mgfSeedLength + 4]; int pos = 0; // 3. For counter from 0 to \ceil (maskLen / hLen) - 1, do the following: for (int counter = 0; counter < iterations; counter++) { // a. Convert counter to an octet string C of length 4 octets byte[] C = I2OSP (counter, 4); // b. Concatenate the hash of the seed mgfSeed and C to the octet string T: // T = T || Hash (mgfSeed || C) Array.Copy (mgfSeed, 0, toBeHashed, 0, mgfSeedLength); Array.Copy (C, 0, toBeHashed, mgfSeedLength, 4); byte[] output = hash.ComputeHash (toBeHashed); Array.Copy (output, 0, T, pos, hLen); pos += mgfSeedLength; } // 4. Output the leading maskLen octets of T as the octet string mask. byte[] mask = new byte [maskLen]; Array.Copy (T, 0, mask, 0, maskLen); return mask; } } } --- NEW FILE: RC4.cs --- // // RC4.cs: RC4(tm) symmetric stream cipher // RC4 is a trademark of RSA Security // // Author: // Sebastien Pouliot (spo...@mo...) // // (C) 2003 Motus Technologies Inc. (http://www.motus.com) // using System; using System.Security.Cryptography; namespace Mono.Security.Cryptography { internal abstract class RC4 : SymmetricAlgorithm { private static KeySizes[] s_legalBlockSizes = { new KeySizes (64, 64, 0) }; private static KeySizes[] s_legalKeySizes = { new KeySizes (40, 2048, 8) }; public RC4() { KeySizeValue = 128; BlockSizeValue = 64; FeedbackSizeValue = BlockSizeValue; LegalBlockSizesValue = s_legalBlockSizes; LegalKeySizesValue = s_legalKeySizes; } new static public RC4 Create() { return Create ("RC4"); } new static public RC4 Create (string algName) { object o = CryptoConfig.CreateFromName (algName); // in case machine.config isn't configured to use // any RC4 implementation if (o == null) { o = new ARC4Managed (); } return (RC4) o; } } } --- NEW FILE: RSAManaged.cs --- // // RSAManaged.cs - Implements the RSA algorithm. // // Authors: // Sebastien Pouliot (spo...@mo...) // Ben Maurer (bm...@us...) // // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com) // Portions (C) 2003 Ben Maurer // // Key generation translated from Bouncy Castle JCE (http://www.bouncycastle.org/) // See bouncycastle.txt for license. // using System; using System.Security.Cryptography; using Mono.Math; // Big chunks of code are coming from the original RSACryptoServiceProvider class. // The class was refactored to : // a. ease integration of new hash algorithm (like MD2, RIPEMD160, ...); // b. provide better support for the coming SSL implementation (requires // EncryptValue/DecryptValue) with, or without, Mono runtime/corlib; // c. provide an alternative RSA implementation for all Windows (like using // OAEP without Windows XP). namespace Mono.Security.Cryptography { internal class RSAManaged : RSA { private const int defaultKeySize = 1024; private bool isCRTpossible = false; private bool keypairGenerated = false; private bool m_disposed = false; private BigInteger d; private BigInteger p; private BigInteger q; private BigInteger dp; private BigInteger dq; private BigInteger qInv; private BigInteger n; // modulus private BigInteger e; public RSAManaged () : this (defaultKeySize) {} public RSAManaged (int dwKeySize) { KeySizeValue = dwKeySize; LegalKeySizesValue = new KeySizes [1]; LegalKeySizesValue [0] = new KeySizes (384, 16384, 8); } ~RSAManaged () { // Zeroize private key Dispose (false); } private void GenerateKeyPair () { // p and q values should have a length of half the strength in bits int pbitlength = ((KeySize + 1) >> 1); int qbitlength = (KeySize - pbitlength); const uint uint_e = 17; e = uint_e; // fixed // generate p, prime and (p-1) relatively prime to e for (;;) { p = BigInteger.genPseudoPrime (pbitlength); if (p % uint_e != 1) break; } // generate a modulus of the required length for (;;) { // generate q, prime and (q-1) relatively prime to e, // and not equal to p for (;;) { q = BigInteger.genPseudoPrime (qbitlength); if ((q % uint_e != 1) && (p != q)) break; } // calculate the modulus n = p * q; if (n.bitCount () == KeySize) break; // if we get here our primes aren't big enough, make the largest // of the two p and try again if (p < q) p = q; } BigInteger pSub1 = (p - 1); BigInteger qSub1 = (q - 1); BigInteger phi = pSub1 * qSub1; // calculate the private exponent d = e.modInverse (phi); // calculate the CRT factors dp = d % pSub1; dq = d % qSub1; qInv = q.modInverse (p); keypairGenerated = true; isCRTpossible = true; } // overrides from RSA class public override int KeySize { get { // in case keypair hasn't been (yet) generated if (keypairGenerated) return n.bitCount (); else return base.KeySize; } } public override string KeyExchangeAlgorithm { get { return "RSA-PKCS1-KeyEx"; } } public override string SignatureAlgorithm { get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; } } public override byte[] DecryptValue (byte[] rgb) { if (m_disposed) throw new ObjectDisposedException ("private key"); // decrypt operation is used for signature if (!keypairGenerated) GenerateKeyPair (); BigInteger input = new BigInteger (rgb); BigInteger output; // decrypt (which uses the private key) can be // optimized by using CRT (Chinese Remainder Theorem) if (isCRTpossible) { // m1 = c^dp mod p BigInteger m1 = input.modPow (dp, p); // m2 = c^dq mod q BigInteger m2 = input.modPow (dq, q); BigInteger h; if (m2 > m1) { // thanks to benm! h = p - ((m2 - m1) * qInv % p); output = m2 + q * h; } else { // h = (m1 - m2) * qInv mod p h = (m1 - m2) * qInv % p; // m = m2 + q * h; output = m2 + q * h; } } else { // m = c^d mod n output = input.modPow (d, n); } byte[] result = output.getBytes (); // zeroize value input.Clear (); output.Clear (); return result; } public override byte[] EncryptValue (byte[] rgb) { if (m_disposed) throw new ObjectDisposedException ("public key"); if (!keypairGenerated) GenerateKeyPair (); BigInteger input = new BigInteger (rgb); BigInteger output = input.modPow (e, n); byte[] result = output.getBytes (); // zeroize value input.Clear (); output.Clear (); return result; } public override RSAParameters ExportParameters (bool includePrivateParameters) { if (m_disposed) throw new ObjectDisposedException (""); if (!keypairGenerated) GenerateKeyPair (); RSAParameters param = new RSAParameters (); param.Exponent = e.getBytes (); param.Modulus = n.getBytes (); if (includePrivateParameters) { param.D = d.getBytes (); param.DP = dp.getBytes (); param.DQ = dq.getBytes (); param.InverseQ = qInv.getBytes (); param.P = p.getBytes (); param.Q = q.getBytes (); } return param; } public override void ImportParameters (RSAParameters parameters) { if (m_disposed) throw new ObjectDisposedException (""); // if missing "mandatory" parameters if (parameters.Exponent == null) throw new CryptographicException ("Missing Exponent"); if (parameters.Modulus == null) throw new CryptographicException ("Missing Modulus"); e = new BigInteger (parameters.Exponent); n = new BigInteger (parameters.Modulus); // only if the private key is present if (parameters.D != null) d = new BigInteger (parameters.D); if (parameters.DP != null) dp = new BigInteger (parameters.DP); if (parameters.DQ != null) dq = new BigInteger (parameters.DQ); if (parameters.InverseQ != null) qInv = new BigInteger (parameters.InverseQ); if (parameters.P != null) p = new BigInteger (parameters.P); if (parameters.Q != null) q = new BigInteger (parameters.Q); // we now have a keypair keypairGenerated = true; isCRTpossible = ((p != null) && (q != null) && (dp != null) && (dq != null) && (qInv != null)); } protected override void Dispose (bool disposing) { if (!m_disposed) { // Always zeroize private key if (d != null) { d.Clear (); d = null; } if (p != null) { p.Clear (); p = null; } if (q != null) { q.Clear (); q = null; } if (dp != null) { dp.Clear (); dp = null; } if (dq != null) { dq.Clear (); dq = null; } if (qInv != null) { qInv.Clear (); qInv = null; } if (disposing) { // clear public key if (e != null) { e.Clear (); e = null; } if (n != null) { n.Clear (); n = null; } } } // call base class // no need as they all are abstract before us m_disposed = true; } } } |