[System.Security.SecurityCritical] // auto-generated internal static byte[] RsaOaepDecrypt (RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, byte[] encryptedData) { int cb = rsa.KeySize / 8; // 1. Decode the input data // It is important that the Integer to Octet String conversion errors be indistinguishable from the other decoding // errors to protect against chosen cipher text attacks // A lecture given by James Manger during Crypto 2001 explains the issue in details byte[] data = null; try { data = rsa.DecryptValue(encryptedData); } catch (CryptographicException) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } // 2. Create the hash object so we can get its size info. int cbHash = hash.HashSize / 8; // 3. Let maskedSeed be the first hLen octects and maskedDB // be the remaining bytes. int zeros = cb - data.Length; if (zeros < 0 || zeros >= cbHash) throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); byte[] seed = new byte[cbHash]; Buffer.InternalBlockCopy(data, 0, seed, zeros, seed.Length - zeros); byte[] DB = new byte[data.Length - seed.Length + zeros]; Buffer.InternalBlockCopy(data, seed.Length - zeros, DB, 0, DB.Length); // 4. seedMask = MGF(maskedDB, hLen); byte[] mask = mgf.GenerateMask(DB, seed.Length); // 5. seed = seedMask XOR maskedSeed int i = 0; for (i=0; i < seed.Length; i++) { seed[i] ^= mask[i]; } // 6. dbMask = MGF(seed, |EM| - hLen); mask = mgf.GenerateMask(seed, DB.Length); // 7. DB = maskedDB xor dbMask for (i=0; i < DB.Length; i++) { DB[i] = (byte) (DB[i] ^ mask[i]); } // 8. pHash = HASH(P) hash.ComputeHash(EmptyArray<Byte>.Value); // 9. DB = pHash' || PS || 01 || M // 10. Check that pHash = pHash' byte[] hashValue = hash.Hash; for (i=0; i < cbHash; i++) { if (DB[i] != hashValue[i]) throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } // Check that PS is all zeros for (; i<DB.Length; i++) { if (DB[i] == 1) break; else if (DB[i] != 0) throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } if (i == DB.Length) throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); i++; // skip over the one // 11. Output M. byte[] output = new byte[DB.Length - i]; Buffer.InternalBlockCopy(DB, i, output, 0, output.Length); return output; }
internal static byte[] RsaOaepEncrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, RandomNumberGenerator rng, byte[] data) { int length1 = rsa.KeySize / 8; int length2 = hash.HashSize / 8; if (data.Length + 2 + 2 * length2 > length1) { throw new CryptographicException(string.Format((IFormatProvider)null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), (object)(length1 - 2 - 2 * length2))); } hash.ComputeHash(EmptyArray <byte> .Value); byte[] rgbSeed = new byte[length1 - length2]; Buffer.InternalBlockCopy((Array)hash.Hash, 0, (Array)rgbSeed, 0, length2); byte[] numArray1 = rgbSeed; int index1 = numArray1.Length - data.Length - 1; int num = 1; numArray1[index1] = (byte)num; Buffer.InternalBlockCopy((Array)data, 0, (Array)rgbSeed, rgbSeed.Length - data.Length, data.Length); byte[] numArray2 = new byte[length2]; rng.GetBytes(numArray2); byte[] mask1 = mgf.GenerateMask(numArray2, rgbSeed.Length); for (int index2 = 0; index2 < rgbSeed.Length; ++index2) { rgbSeed[index2] = (byte)((uint)rgbSeed[index2] ^ (uint)mask1[index2]); } byte[] mask2 = mgf.GenerateMask(rgbSeed, length2); for (int index2 = 0; index2 < numArray2.Length; ++index2) { numArray2[index2] ^= mask2[index2]; } byte[] rgb = new byte[length1]; Buffer.InternalBlockCopy((Array)numArray2, 0, (Array)rgb, 0, numArray2.Length); Buffer.InternalBlockCopy((Array)rgbSeed, 0, (Array)rgb, numArray2.Length, rgbSeed.Length); return(rsa.EncryptValue(rgb)); }
internal static byte[] RsaOaepEncrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, RandomNumberGenerator rng, byte[] data) { int num = rsa.KeySize / 8; int num2 = hash.HashSize / 8; if (data.Length + 2 + 2 * num2 > num) { throw new CryptographicException(string.Format(null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), num - 2 - 2 * num2)); } hash.ComputeHash(EmptyArray <byte> .Value); byte[] array = new byte[num - num2]; Buffer.InternalBlockCopy(hash.Hash, 0, array, 0, num2); array[array.Length - data.Length - 1] = 1; Buffer.InternalBlockCopy(data, 0, array, array.Length - data.Length, data.Length); byte[] array2 = new byte[num2]; rng.GetBytes(array2); byte[] array3 = mgf.GenerateMask(array2, array.Length); for (int i = 0; i < array.Length; i++) { array[i] ^= array3[i]; } array3 = mgf.GenerateMask(array, num2); for (int j = 0; j < array2.Length; j++) { byte[] array4 = array2; int num3 = j; array4[num3] ^= array3[j]; } byte[] array5 = new byte[num]; Buffer.InternalBlockCopy(array2, 0, array5, 0, array2.Length); Buffer.InternalBlockCopy(array, 0, array5, array2.Length, array.Length); return(rsa.EncryptValue(array5)); }
internal static byte[] RsaOaepEncrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, RandomNumberGenerator rng, byte[] data) { int num = rsa.KeySize / 8; int byteCount = hash.HashSize / 8; if (((data.Length + 2) + (2 * byteCount)) > num) { throw new CryptographicException(string.Format(null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), new object[] { (num - 2) - (2 * byteCount) })); } hash.ComputeHash(new byte[0]); byte[] dst = new byte[num - byteCount]; Buffer.InternalBlockCopy(hash.Hash, 0, dst, 0, byteCount); dst[(dst.Length - data.Length) - 1] = 1; Buffer.InternalBlockCopy(data, 0, dst, dst.Length - data.Length, data.Length); byte[] buffer2 = new byte[byteCount]; rng.GetBytes(buffer2); byte[] buffer3 = mgf.GenerateMask(buffer2, dst.Length); for (int i = 0; i < dst.Length; i++) { dst[i] = (byte)(dst[i] ^ buffer3[i]); } buffer3 = mgf.GenerateMask(dst, byteCount); for (int j = 0; j < buffer2.Length; j++) { buffer2[j] = (byte)(buffer2[j] ^ buffer3[j]); } byte[] buffer4 = new byte[num]; Buffer.InternalBlockCopy(buffer2, 0, buffer4, 0, buffer2.Length); Buffer.InternalBlockCopy(dst, 0, buffer4, buffer2.Length, dst.Length); return(rsa.EncryptValue(buffer4)); }
public static void EmptyMaskTest() { PKCS1MaskGenerationMethod pkcs1 = new PKCS1MaskGenerationMethod(); byte[] random = { 0x01 }; byte[] mask = pkcs1.GenerateMask(random, 0); Assert.Equal(0, mask.Length); }
public static void GenerateMaskTest() { PKCS1MaskGenerationMethod pkcs1 = new PKCS1MaskGenerationMethod(); byte[] seed = { 0xaa, 0xfd, 0x12, 0xf6, 0x59, 0xca, 0xe6, 0x34, 0x89, 0xb4, 0x79, 0xe5, 0x07, 0x6d, 0xde, 0xc2, 0xf0, 0x6c, 0xb5, 0x8f }; int LengthDB = 107; byte[] expectedDBMask = { 0x06, 0xe1, 0xde, 0xb2, 0x36, 0x9a, 0xa5, 0xa5, 0xc7, 0x07, 0xd8, 0x2c, 0x8e, 0x4e, 0x93, 0x24, 0x8a, 0xc7, 0x83, 0xde, 0xe0, 0xb2, 0xc0, 0x46, 0x26, 0xf5, 0xaf, 0xf9, 0x3e, 0xdc, 0xfb, 0x25, 0xc9, 0xc2, 0xb3, 0xff, 0x8a, 0xe1, 0x0e, 0x83, 0x9a, 0x2d, 0xdb, 0x4c, 0xdc, 0xfe, 0x4f, 0xf4, 0x77, 0x28, 0xb4, 0xa1, 0xb7, 0xc1, 0x36, 0x2b, 0xaa, 0xd2, 0x9a, 0xb4, 0x8d, 0x28, 0x69, 0xd5, 0x02, 0x41, 0x21, 0x43, 0x58, 0x11, 0x59, 0x1b, 0xe3, 0x92, 0xf9, 0x82, 0xfb, 0x3e, 0x87, 0xd0, 0x95, 0xae, 0xb4, 0x04, 0x48, 0xdb, 0x97, 0x2f, 0x3a, 0xc1, 0x4e, 0xaf, 0xf4, 0x9c, 0x8c, 0x3b, 0x7c, 0xfc, 0x95, 0x1a, 0x51, 0xec, 0xd1, 0xdd, 0xe6, 0x12, 0x64 }; byte[] dbMask = pkcs1.GenerateMask(seed, LengthDB); Assert.Equal(expectedDBMask, dbMask); byte[] DB = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd4, 0x36, 0xe9, 0x95, 0x69, 0xfd, 0x32, 0xa7, 0xc8, 0xa0, 0x5b, 0xbc, 0x90, 0xd3, 0x2c, 0x49 }; byte[] maskedDB = new byte[dbMask.Length]; for (int i = 0; i < dbMask.Length; i++) { maskedDB[i] = (byte)(DB[i]^dbMask[i]); } byte[] seedMask = pkcs1.GenerateMask(maskedDB, seed.Length); byte[] expectedSeedMask = { 0x41, 0x87, 0x0b, 0x5a, 0xb0, 0x29, 0xe6, 0x57, 0xd9, 0x57, 0x50, 0xb5, 0x4c, 0x28, 0x3c, 0x08, 0x72, 0x5d, 0xbe, 0xa9 }; Assert.Equal(expectedSeedMask, seedMask); }
public override byte[] GenerateMask ( byte[] rgbSalt, int cbReturn ) { // member implemented for compatibility only .... // throw new System.NotImplementedException("GenerateMask needs more parameters"); // Computes masks according to PKCS #1 for use by key exchange algorithms. // Generates and returns a mask from the specified random salt of the specified length. PKCS1MaskGenerationMethod pkcs1 = new PKCS1MaskGenerationMethod(); return(pkcs1.GenerateMask(rgbSalt, cbReturn)); }
/************************* PUBLIC METHODS *************************/ /// <include file='doc\RSAOAEPKeyExchangeDeformatter.uex' path='docs/doc[@for="RSAOAEPKeyExchangeDeformatter.DecryptKeyExchange"]/*' /> public override byte[] DecryptKeyExchange(byte[] rgbData) { byte[] rgbOut = null; if (_rsaKey is RSACryptoServiceProvider) { rgbOut = ((RSACryptoServiceProvider)_rsaKey).Decrypt(rgbData, true); } else { int cb = _rsaKey.KeySize / 8; int cbHash; HashAlgorithm hash; int i; MaskGenerationMethod mgf; byte[] rgbDB; byte[] rgbMask; byte[] rgbSeed; byte[] rgbIn; bool bError = false; // 1. Decode the input data // It is important that the Integer to Octet String conversion errors be indistinguishable from the other decoding // errors to protect against chosen cipher text attacks // A lecture given by James Manger during Crypto 2001 explains the issue in details try { rgbIn = _rsaKey.DecryptValue(rgbData); } catch { bError = true; goto error; } // 2. Create the hash object so we can get its size info. hash = (HashAlgorithm)CryptoConfig.CreateFromName(HashNameValue); cbHash = hash.HashSize / 8; if (rgbIn.Length != cb || cb < 2 * cbHash + 2) { bError = true; goto error; } // 3. Let maskedSeed be the first hLen octects and maskedDB // be the remaining bytes. rgbSeed = new byte[cbHash]; Buffer.InternalBlockCopy(rgbIn, 1, rgbSeed, 0, rgbSeed.Length); rgbDB = new byte[rgbIn.Length - rgbSeed.Length - 1]; Buffer.InternalBlockCopy(rgbIn, rgbSeed.Length + 1, rgbDB, 0, rgbDB.Length); // 4. seedMask = MGF(maskedDB, hLen); mgf = new PKCS1MaskGenerationMethod(); rgbMask = mgf.GenerateMask(rgbDB, rgbSeed.Length); // 5. seed = seedMask XOR maskedSeed for (i = 0; i < rgbSeed.Length; i++) { rgbSeed[i] ^= rgbMask[i]; } // 6. dbMask = MGF(seed, |EM| - hLen); rgbMask = mgf.GenerateMask(rgbSeed, rgbDB.Length); // 7. DB = maskedDB xor dbMask for (i = 0; i < rgbDB.Length; i++) { rgbDB[i] ^= rgbMask[i]; } // 8. pHash = HASH(P) hash.ComputeHash(ParameterValue); // 9. DB = pHash' || PS || 01 || M // // 10. Check that pHash = pHash' for (i = 0; i < cbHash; i++) { if (rgbDB[i] != hash.Hash[i]) { bError = true; goto error; } } // Check that PS is all zeros for (; i < rgbDB.Length; i++) { if (rgbDB[i] == 01) { break; } else if (rgbDB[i] != 0) { bError = true; goto error; } } if (i == rgbDB.Length) { bError = true; goto error; } i++; // Skip over the one rgbOut = new byte[rgbDB.Length - i]; // 11. Output M. Buffer.InternalBlockCopy(rgbDB, i, rgbOut, 0, rgbOut.Length); error : if (bError) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } } return(rgbOut); }
internal static byte[] RsaOaepDecrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, byte[] encryptedData) { int num = rsa.KeySize / 8; byte[] src = null; try { src = rsa.DecryptValue(encryptedData); } catch (CryptographicException) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } int num2 = hash.HashSize / 8; int dstOffsetBytes = num - src.Length; if ((dstOffsetBytes < 0) || (dstOffsetBytes >= num2)) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } byte[] dst = new byte[num2]; Buffer.InternalBlockCopy(src, 0, dst, dstOffsetBytes, dst.Length - dstOffsetBytes); byte[] buffer3 = new byte[(src.Length - dst.Length) + dstOffsetBytes]; Buffer.InternalBlockCopy(src, dst.Length - dstOffsetBytes, buffer3, 0, buffer3.Length); byte[] buffer4 = mgf.GenerateMask(buffer3, dst.Length); int index = 0; for (index = 0; index < dst.Length; index++) { dst[index] = (byte)(dst[index] ^ buffer4[index]); } buffer4 = mgf.GenerateMask(dst, buffer3.Length); for (index = 0; index < buffer3.Length; index++) { buffer3[index] = (byte)(buffer3[index] ^ buffer4[index]); } hash.ComputeHash(new byte[0]); byte[] buffer5 = hash.Hash; index = 0; while (index < num2) { if (buffer3[index] != buffer5[index]) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } index++; } while (index < buffer3.Length) { if (buffer3[index] == 1) { break; } if (buffer3[index] != 0) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } index++; } if (index == buffer3.Length) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } index++; byte[] buffer6 = new byte[buffer3.Length - index]; Buffer.InternalBlockCopy(buffer3, index, buffer6, 0, buffer6.Length); return(buffer6); }
// Encrypt a value using a specified OAEP padding array. // The array may be null to pad with zeroes. internal byte[] EncryptOAEP(byte[] rgb, byte[] padding, RandomNumberGenerator rng) { // Check the data against null. if (rgb == null) { throw new ArgumentNullException("rgb"); } // Make sure that we have sufficient RSA parameters. if (rsaParams.Modulus == null) { throw new CryptographicException (_("Crypto_RSAParamsNotSet")); } // Format the label, padding string, and rgb into a message. int k = rsaParams.Modulus.Length; if (rgb.Length > (k - 2 * 20 - 2)) { throw new CryptographicException (_("Crypto_RSAMessageTooLong")); } byte[] msg = new byte [k - 20 - 1]; int posn = 0; Array.Copy(label, 0, msg, posn, 20); posn += 20; int padlen = k - rgb.Length - 2 * 20 - 2; if (padlen > 0 && padding != null) { if (padding.Length <= padlen) { Array.Copy(padding, 0, msg, posn, padding.Length); } else { Array.Copy(padding, 0, msg, posn, padlen); } } posn += padlen; msg[posn++] = (byte)0x01; Array.Copy(rgb, 0, msg, posn, rgb.Length); // Acquire a mask generation method, based on SHA-1. MaskGenerationMethod maskGen = new PKCS1MaskGenerationMethod(); // Generate a random seed to use to generate masks. byte[] seed = new byte [20]; rng.GetBytes(seed); // Generate a mask and encrypt the above message. byte[] mask = maskGen.GenerateMask(seed, msg.Length); int index; for (index = 0; index < msg.Length; ++index) { msg[index] ^= mask[index]; } // Generate another mask and encrypt the seed. byte[] seedMask = maskGen.GenerateMask(msg, 20); for (index = 0; index < 20; ++index) { seed[index] ^= seedMask[index]; } // Build the value to be encrypted using RSA. byte[] value = new byte [k]; Array.Copy(seed, 0, value, 1, 20); Array.Copy(msg, 0, value, 21, msg.Length); // Encrypt the value. byte[] encrypted = ApplyPublic(value); // Destroy sensitive data. Array.Clear(msg, 0, msg.Length); Array.Clear(seed, 0, seed.Length); Array.Clear(mask, 0, mask.Length); Array.Clear(seedMask, 0, seedMask.Length); Array.Clear(value, 0, value.Length); // Done. return(encrypted); }
[System.Security.SecurityCritical] // auto-generated internal static byte[] RsaOaepEncrypt (RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, RandomNumberGenerator rng, byte[] data) { int cb = rsa.KeySize / 8; // 1. Hash the parameters to get PHash int cbHash = hash.HashSize / 8; if ((data.Length + 2 + 2*cbHash) > cb) throw new CryptographicException(String.Format(null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), cb-2-2*cbHash)); hash.ComputeHash(EmptyArray<Byte>.Value); // Use an empty octet string // 2. Create DB object byte[] DB = new byte[cb - cbHash]; // Structure is as follows: // pHash || PS || 01 || M // PS consists of all zeros Buffer.InternalBlockCopy(hash.Hash, 0, DB, 0, cbHash); DB[DB.Length - data.Length - 1] = 1; Buffer.InternalBlockCopy(data, 0, DB, DB.Length-data.Length, data.Length); // 3. Create a random value of size hLen byte[] seed = new byte[cbHash]; rng.GetBytes(seed); // 4. Compute the mask value byte[] mask = mgf.GenerateMask(seed, DB.Length); // 5. Xor maskDB into DB for (int i=0; i < DB.Length; i++) { DB[i] = (byte) (DB[i] ^ mask[i]); } // 6. Compute seed mask value mask = mgf.GenerateMask(DB, cbHash); // 7. Xor mask into seed for (int i=0; i < seed.Length; i++) { seed[i] ^= mask[i]; } // 8. Concatenate seed and DB to form value to encrypt byte[] pad = new byte[cb]; Buffer.InternalBlockCopy(seed, 0, pad, 0, seed.Length); Buffer.InternalBlockCopy(DB, 0, pad, seed.Length, DB.Length); return rsa.EncryptValue(pad); }
// Decrypt a value using the RSA private key and OAEP padding. internal byte[] DecryptOAEP(byte[] rgb) { // Check the data against null. if(rgb == null) { throw new ArgumentNullException("rgb"); } // Make sure that we have sufficient RSA parameters. if(rsaParams.Modulus == null) { throw new CryptographicException (_("Crypto_RSAParamsNotSet")); } // Check the length of the incoming value. int k = rsaParams.Modulus.Length; if(k < (2 * 20 + 2)) { throw new CryptographicException (_("Crypto_RSAKeyTooShort")); } // Decrypt the incoming value, and expand to k octets, // as the big number routines in the engine may have // stripped leading zeroes from the value. byte[] decrypted = ApplyPrivate(rgb); if(decrypted.Length > k) { Array.Clear(decrypted, 0, decrypted.Length); throw new CryptographicException (_("Crypto_RSAInvalidCiphertext")); } byte[] msg = new byte [k]; Array.Copy(decrypted, 0, msg, k - decrypted.Length, decrypted.Length); // Acquire a mask generation method, based on SHA-1. MaskGenerationMethod maskGen = new PKCS1MaskGenerationMethod(); // Extract the non-seed part of the decrypted message. byte[] maskedMsg = new byte [k - 20 - 1]; Array.Copy(msg, 0, maskedMsg, 0, k - 20 - 1); // Decrypt the seed value. byte[] seedMask = maskGen.GenerateMask(maskedMsg, 20); byte[] seed = new byte [20]; int index; for(index = 0; index < 20; ++index) { seed[index] = (byte)(msg[index + 1] ^ seedMask[index]); } // Decrypt the non-seed part of the decrypted message. byte[] msgMask = maskGen.GenerateMask(seed, maskedMsg.Length); for(index = 0; index < maskedMsg.Length; ++index) { maskedMsg[index] ^= msgMask[index]; } // Validate the format of the unmasked message. We do this // carefully, to prevent attackers from performing timing // attacks on the algorithm. See PKCS #1 for details. int error = msg[0]; for(index = 0; index < 20; ++index) { error |= (maskedMsg[index] ^ label[index]); } for(index = 20; index < (k - 20 - 2); ++index) { // Question: is this careful enough to prevent // timing attacks? May need revisiting later. if(maskedMsg[index] != 0) { break; } } error |= (maskedMsg[index] ^ 0x01); if(error != 0) { // Something is wrong with the decrypted padding data. Array.Clear(decrypted, 0, decrypted.Length); Array.Clear(msg, 0, msg.Length); Array.Clear(maskedMsg, 0, maskedMsg.Length); Array.Clear(seedMask, 0, seedMask.Length); Array.Clear(seed, 0, seed.Length); Array.Clear(msgMask, 0, msgMask.Length); throw new CryptographicException (_("Crypto_RSAInvalidCiphertext")); } ++index; // Extract the final decrypted message. byte[] finalMsg = new byte [maskedMsg.Length - index]; Array.Copy(maskedMsg, index, finalMsg, 0, maskedMsg.Length - index); // Destroy sensitive values. Array.Clear(decrypted, 0, decrypted.Length); Array.Clear(msg, 0, msg.Length); Array.Clear(maskedMsg, 0, maskedMsg.Length); Array.Clear(seedMask, 0, seedMask.Length); Array.Clear(seed, 0, seed.Length); Array.Clear(msgMask, 0, msgMask.Length); // Done. return finalMsg; }
// Encrypt a value using a specified OAEP padding array. // The array may be null to pad with zeroes. internal byte[] EncryptOAEP(byte[] rgb, byte[] padding, RandomNumberGenerator rng) { // Check the data against null. if(rgb == null) { throw new ArgumentNullException("rgb"); } // Make sure that we have sufficient RSA parameters. if(rsaParams.Modulus == null) { throw new CryptographicException (_("Crypto_RSAParamsNotSet")); } // Format the label, padding string, and rgb into a message. int k = rsaParams.Modulus.Length; if(rgb.Length > (k - 2 * 20 - 2)) { throw new CryptographicException (_("Crypto_RSAMessageTooLong")); } byte[] msg = new byte [k - 20 - 1]; int posn = 0; Array.Copy(label, 0, msg, posn, 20); posn += 20; int padlen = k - rgb.Length - 2 * 20 - 2; if(padlen > 0 && padding != null) { if(padding.Length <= padlen) { Array.Copy(padding, 0, msg, posn, padding.Length); } else { Array.Copy(padding, 0, msg, posn, padlen); } } posn += padlen; msg[posn++] = (byte)0x01; Array.Copy(rgb, 0, msg, posn, rgb.Length); // Acquire a mask generation method, based on SHA-1. MaskGenerationMethod maskGen = new PKCS1MaskGenerationMethod(); // Generate a random seed to use to generate masks. byte[] seed = new byte [20]; rng.GetBytes(seed); // Generate a mask and encrypt the above message. byte[] mask = maskGen.GenerateMask(seed, msg.Length); int index; for(index = 0; index < msg.Length; ++index) { msg[index] ^= mask[index]; } // Generate another mask and encrypt the seed. byte[] seedMask = maskGen.GenerateMask(msg, 20); for(index = 0; index < 20; ++index) { seed[index] ^= seedMask[index]; } // Build the value to be encrypted using RSA. byte[] value = new byte [k]; Array.Copy(seed, 0, value, 1, 20); Array.Copy(msg, 0, value, 21, msg.Length); // Encrypt the value. byte[] encrypted = ApplyPublic(value); // Destroy sensitive data. Array.Clear(msg, 0, msg.Length); Array.Clear(seed, 0, seed.Length); Array.Clear(mask, 0, mask.Length); Array.Clear(seedMask, 0, seedMask.Length); Array.Clear(value, 0, value.Length); // Done. return encrypted; }
internal static byte[] RsaOaepDecrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, byte[] encryptedData) { int num = rsa.KeySize / 8; byte[] array = null; try { array = rsa.DecryptValue(encryptedData); } catch (CryptographicException) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } int num2 = hash.HashSize / 8; int num3 = num - array.Length; if (num3 < 0 || num3 >= num2) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } byte[] array2 = new byte[num2]; Buffer.InternalBlockCopy(array, 0, array2, num3, array2.Length - num3); byte[] array3 = new byte[array.Length - array2.Length + num3]; Buffer.InternalBlockCopy(array, array2.Length - num3, array3, 0, array3.Length); byte[] array4 = mgf.GenerateMask(array3, array2.Length); int i; for (i = 0; i < array2.Length; i++) { byte[] array5 = array2; int num4 = i; array5[num4] ^= array4[i]; } array4 = mgf.GenerateMask(array2, array3.Length); for (i = 0; i < array3.Length; i++) { array3[i] ^= array4[i]; } hash.ComputeHash(EmptyArray <byte> .Value); byte[] hash2 = hash.Hash; for (i = 0; i < num2; i++) { if (array3[i] != hash2[i]) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } } while (i < array3.Length && array3[i] != 1) { if (array3[i] != 0) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } i++; } if (i == array3.Length) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } i++; byte[] array6 = new byte[array3.Length - i]; Buffer.InternalBlockCopy(array3, i, array6, 0, array6.Length); return(array6); }
public static void NullSeedTest() { PKCS1MaskGenerationMethod pkcs1 = new PKCS1MaskGenerationMethod(); Assert.Throws<NullReferenceException>(() => pkcs1.GenerateMask(null, 10)); }
// Decrypt a value using the RSA private key and OAEP padding. internal byte[] DecryptOAEP(byte[] rgb) { // Check the data against null. if (rgb == null) { throw new ArgumentNullException("rgb"); } // Make sure that we have sufficient RSA parameters. if (rsaParams.Modulus == null) { throw new CryptographicException (_("Crypto_RSAParamsNotSet")); } // Check the length of the incoming value. int k = rsaParams.Modulus.Length; if (k < (2 * 20 + 2)) { throw new CryptographicException (_("Crypto_RSAKeyTooShort")); } // Decrypt the incoming value, and expand to k octets, // as the big number routines in the engine may have // stripped leading zeroes from the value. byte[] decrypted = ApplyPrivate(rgb); if (decrypted.Length > k) { Array.Clear(decrypted, 0, decrypted.Length); throw new CryptographicException (_("Crypto_RSAInvalidCiphertext")); } byte[] msg = new byte [k]; Array.Copy(decrypted, 0, msg, k - decrypted.Length, decrypted.Length); // Acquire a mask generation method, based on SHA-1. MaskGenerationMethod maskGen = new PKCS1MaskGenerationMethod(); // Extract the non-seed part of the decrypted message. byte[] maskedMsg = new byte [k - 20 - 1]; Array.Copy(msg, 0, maskedMsg, 0, k - 20 - 1); // Decrypt the seed value. byte[] seedMask = maskGen.GenerateMask(maskedMsg, 20); byte[] seed = new byte [20]; int index; for (index = 0; index < 20; ++index) { seed[index] = (byte)(msg[index + 1] ^ seedMask[index]); } // Decrypt the non-seed part of the decrypted message. byte[] msgMask = maskGen.GenerateMask(seed, maskedMsg.Length); for (index = 0; index < maskedMsg.Length; ++index) { maskedMsg[index] ^= msgMask[index]; } // Validate the format of the unmasked message. We do this // carefully, to prevent attackers from performing timing // attacks on the algorithm. See PKCS #1 for details. int error = msg[0]; for (index = 0; index < 20; ++index) { error |= (maskedMsg[index] ^ label[index]); } for (index = 20; index < (k - 20 - 2); ++index) { // Question: is this careful enough to prevent // timing attacks? May need revisiting later. if (maskedMsg[index] != 0) { break; } } error |= (maskedMsg[index] ^ 0x01); if (error != 0) { // Something is wrong with the decrypted padding data. Array.Clear(decrypted, 0, decrypted.Length); Array.Clear(msg, 0, msg.Length); Array.Clear(maskedMsg, 0, maskedMsg.Length); Array.Clear(seedMask, 0, seedMask.Length); Array.Clear(seed, 0, seed.Length); Array.Clear(msgMask, 0, msgMask.Length); throw new CryptographicException (_("Crypto_RSAInvalidCiphertext")); } ++index; // Extract the final decrypted message. byte[] finalMsg = new byte [maskedMsg.Length - index]; Array.Copy(maskedMsg, index, finalMsg, 0, maskedMsg.Length - index); // Destroy sensitive values. Array.Clear(decrypted, 0, decrypted.Length); Array.Clear(msg, 0, msg.Length); Array.Clear(maskedMsg, 0, maskedMsg.Length); Array.Clear(seedMask, 0, seedMask.Length); Array.Clear(seed, 0, seed.Length); Array.Clear(msgMask, 0, msgMask.Length); // Done. return(finalMsg); }
internal static byte[] RsaOaepDecrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, byte[] encryptedData) { int num = rsa.KeySize / 8; byte[] src = null; try { src = rsa.DecryptValue(encryptedData); } catch (CryptographicException) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } int num2 = hash.HashSize / 8; int dstOffsetBytes = num - src.Length; if ((dstOffsetBytes < 0) || (dstOffsetBytes >= num2)) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } byte[] dst = new byte[num2]; Buffer.InternalBlockCopy(src, 0, dst, dstOffsetBytes, dst.Length - dstOffsetBytes); byte[] buffer3 = new byte[(src.Length - dst.Length) + dstOffsetBytes]; Buffer.InternalBlockCopy(src, dst.Length - dstOffsetBytes, buffer3, 0, buffer3.Length); byte[] buffer4 = mgf.GenerateMask(buffer3, dst.Length); int index = 0; for (index = 0; index < dst.Length; index++) { dst[index] = (byte) (dst[index] ^ buffer4[index]); } buffer4 = mgf.GenerateMask(dst, buffer3.Length); for (index = 0; index < buffer3.Length; index++) { buffer3[index] = (byte) (buffer3[index] ^ buffer4[index]); } hash.ComputeHash(new byte[0]); byte[] buffer5 = hash.Hash; index = 0; while (index < num2) { if (buffer3[index] != buffer5[index]) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } index++; } while (index < buffer3.Length) { if (buffer3[index] == 1) { break; } if (buffer3[index] != 0) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } index++; } if (index == buffer3.Length) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } index++; byte[] buffer6 = new byte[buffer3.Length - index]; Buffer.InternalBlockCopy(buffer3, index, buffer6, 0, buffer6.Length); return buffer6; }
internal static byte[] RsaOaepEncrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, RandomNumberGenerator rng, byte[] data) { int num = rsa.KeySize / 8; int byteCount = hash.HashSize / 8; if (((data.Length + 2) + (2 * byteCount)) > num) { throw new CryptographicException(string.Format(null, Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), new object[] { (num - 2) - (2 * byteCount) })); } hash.ComputeHash(new byte[0]); byte[] dst = new byte[num - byteCount]; Buffer.InternalBlockCopy(hash.Hash, 0, dst, 0, byteCount); dst[(dst.Length - data.Length) - 1] = 1; Buffer.InternalBlockCopy(data, 0, dst, dst.Length - data.Length, data.Length); byte[] buffer2 = new byte[byteCount]; rng.GetBytes(buffer2); byte[] buffer3 = mgf.GenerateMask(buffer2, dst.Length); for (int i = 0; i < dst.Length; i++) { dst[i] = (byte) (dst[i] ^ buffer3[i]); } buffer3 = mgf.GenerateMask(dst, byteCount); for (int j = 0; j < buffer2.Length; j++) { buffer2[j] = (byte) (buffer2[j] ^ buffer3[j]); } byte[] buffer4 = new byte[num]; Buffer.InternalBlockCopy(buffer2, 0, buffer4, 0, buffer2.Length); Buffer.InternalBlockCopy(dst, 0, buffer4, buffer2.Length, dst.Length); return rsa.EncryptValue(buffer4); }
/// <include file='doc\RSAOAEPKeyExchangeFormatter.uex' path='docs/doc[@for="RSAOAEPKeyExchangeFormatter.CreateKeyExchange"]/*' /> public override byte[] CreateKeyExchange(byte[] rgbData) { byte[] rgbKeyEx; if (_rsaKey is RSACryptoServiceProvider) { rgbKeyEx = ((RSACryptoServiceProvider)_rsaKey).Encrypt(rgbData, true); } else { int cb = _rsaKey.KeySize / 8; int cbHash; HashAlgorithm hash; int i; MaskGenerationMethod mgf; byte[] rgbDB; byte[] rgbIn; byte[] rgbMask; byte[] rgbSeed; // Create the OAEP padding object. // 1. Hash the parameters to get rgbPHash hash = (HashAlgorithm)CryptoConfig.CreateFromName("SHA1"); // Create the default SHA1 object cbHash = hash.HashSize / 8; if ((rgbData.Length + 2 + 2 * cbHash) > cb) { throw new CryptographicException(String.Format(Environment.GetResourceString("Cryptography_Padding_EncDataTooBig"), cb - 2 - 2 * cbHash)); } hash.ComputeHash(new byte[0]); // Use an empty octet string // 2. Create DB object rgbDB = new byte[cb - cbHash - 1]; // Structure is as follows: // pHash || PS || 01 || M // PS consists of all zeros Buffer.InternalBlockCopy(hash.Hash, 0, rgbDB, 0, cbHash); rgbDB[rgbDB.Length - rgbData.Length - 1] = 1; Buffer.InternalBlockCopy(rgbData, 0, rgbDB, rgbDB.Length - rgbData.Length, rgbData.Length); // 3. Create a random value of size hLen if (RngValue == null) { RngValue = RandomNumberGenerator.Create(); } rgbSeed = new byte[cbHash]; RngValue.GetBytes(rgbSeed); // 4. Compute the mask value mgf = new PKCS1MaskGenerationMethod(); rgbMask = mgf.GenerateMask(rgbSeed, rgbDB.Length); // 5. Xor rgbMaskDB into rgbDB for (i = 0; i < rgbDB.Length; i++) { rgbDB[i] = (byte)(rgbDB[i] ^ rgbMask[i]); } // 6. Compute seed mask value rgbMask = mgf.GenerateMask(rgbDB, cbHash); // 7. Xor rgbMask into rgbSeed for (i = 0; i < rgbSeed.Length; i++) { rgbSeed[i] ^= rgbMask[i]; } // 8. Concatenate rgbSeed and rgbDB to form value to encrypt rgbIn = new byte[cb]; Buffer.InternalBlockCopy(rgbSeed, 0, rgbIn, 1, rgbSeed.Length); Buffer.InternalBlockCopy(rgbDB, 0, rgbIn, rgbSeed.Length + 1, rgbDB.Length); // 9. Now Encrypt it rgbKeyEx = _rsaKey.EncryptValue(rgbIn); } return(rgbKeyEx); }
internal static byte[] RsaOaepDecrypt(RSA rsa, HashAlgorithm hash, PKCS1MaskGenerationMethod mgf, byte[] encryptedData) { int num = rsa.KeySize / 8; byte[] numArray1; try { numArray1 = rsa.DecryptValue(encryptedData); } catch (CryptographicException ex) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } int length = hash.HashSize / 8; int dstOffsetBytes = num - numArray1.Length; if (dstOffsetBytes < 0 || dstOffsetBytes >= length) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } byte[] rgbSeed1 = new byte[length]; Buffer.InternalBlockCopy((Array)numArray1, 0, (Array)rgbSeed1, dstOffsetBytes, rgbSeed1.Length - dstOffsetBytes); byte[] rgbSeed2 = new byte[numArray1.Length - rgbSeed1.Length + dstOffsetBytes]; Buffer.InternalBlockCopy((Array)numArray1, rgbSeed1.Length - dstOffsetBytes, (Array)rgbSeed2, 0, rgbSeed2.Length); byte[] mask1 = mgf.GenerateMask(rgbSeed2, rgbSeed1.Length); for (int index = 0; index < rgbSeed1.Length; ++index) { rgbSeed1[index] ^= mask1[index]; } byte[] mask2 = mgf.GenerateMask(rgbSeed1, rgbSeed2.Length); for (int index = 0; index < rgbSeed2.Length; ++index) { rgbSeed2[index] = (byte)((uint)rgbSeed2[index] ^ (uint)mask2[index]); } hash.ComputeHash(EmptyArray <byte> .Value); byte[] hash1 = hash.Hash; int index1; for (index1 = 0; index1 < length; ++index1) { if ((int)rgbSeed2[index1] != (int)hash1[index1]) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } } for (; index1 < rgbSeed2.Length && (int)rgbSeed2[index1] != 1; ++index1) { if ((int)rgbSeed2[index1] != 0) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } } if (index1 == rgbSeed2.Length) { throw new CryptographicException(Environment.GetResourceString("Cryptography_OAEPDecoding")); } int srcOffsetBytes = index1 + 1; byte[] numArray2 = new byte[rgbSeed2.Length - srcOffsetBytes]; Buffer.InternalBlockCopy((Array)rgbSeed2, srcOffsetBytes, (Array)numArray2, 0, numArray2.Length); return(numArray2); }
public static void NegativeReturnParameterTest() { PKCS1MaskGenerationMethod pkcs1 = new PKCS1MaskGenerationMethod(); byte[] random = { 0x01 }; Assert.Throws<OverflowException>(() => pkcs1.GenerateMask(random, -1)); }