// // Conveniently, Encrypt() and Decrypt() are identical save for the actual P/Invoke call to CNG. Thus, both // APIs invoke this common helper with the "transform" parameter determining whether encryption or decryption is done. // private byte[] EncryptOrDecrypt(byte[] data, RSAEncryptionPadding padding, EncryptOrDecryptAction encryptOrDecrypt) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } unsafe { using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { switch (padding.Mode) { case RSAEncryptionPaddingMode.Pkcs1: return(EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, null, encryptOrDecrypt)); case RSAEncryptionPaddingMode.Oaep: { using (SafeUnicodeStringHandle safeHashAlgorithmName = new SafeUnicodeStringHandle(padding.OaepHashAlgorithm.Name)) { BCRYPT_OAEP_PADDING_INFO paddingInfo = new BCRYPT_OAEP_PADDING_INFO() { pszAlgId = safeHashAlgorithmName.DangerousGetHandle(), // It would nice to put randomized data here but RSAEncryptionPadding does not at this point provide support for this. pbLabel = IntPtr.Zero, cbLabel = 0, }; return(EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_OAEP_FLAG, &paddingInfo, encryptOrDecrypt)); } } default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } } } }
// // Conveniently, Encrypt() and Decrypt() are identical save for the actual P/Invoke call to CNG. Thus, both // APIs invoke this common helper with the "transform" parameter determining whether encryption or decryption is done. // private byte[] EncryptOrDecrypt(byte[] data, RSAEncryptionPadding padding, EncryptOrDecryptAction encryptOrDecrypt) { if (data == null) throw new ArgumentNullException(nameof(data)); if (padding == null) throw new ArgumentNullException(nameof(padding)); unsafe { using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { switch (padding.Mode) { case RSAEncryptionPaddingMode.Pkcs1: return EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, null, encryptOrDecrypt); case RSAEncryptionPaddingMode.Oaep: { using (SafeUnicodeStringHandle safeHashAlgorithmName = new SafeUnicodeStringHandle(padding.OaepHashAlgorithm.Name)) { BCRYPT_OAEP_PADDING_INFO paddingInfo = new BCRYPT_OAEP_PADDING_INFO() { pszAlgId = safeHashAlgorithmName.DangerousGetHandle(), // It would nice to put randomized data here but RSAEncryptionPadding does not at this point provide support for this. pbLabel = IntPtr.Zero, cbLabel = 0, }; return EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_OAEP_FLAG, &paddingInfo, encryptOrDecrypt); } } default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } } } }
// // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption. // private unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, byte[] input, AsymmetricPaddingMode paddingMode, void *paddingInfo, EncryptOrDecryptAction encryptOrDecrypt) { int estimatedSize = KeySize / 8; #if DEBUG estimatedSize = 2; // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised. #endif byte[] output = new byte[estimatedSize]; int numBytesNeeded; ErrorCode errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode); if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL) { output = new byte[numBytesNeeded]; errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode); } if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } Array.Resize(ref output, numBytesNeeded); return(output); }
// // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption. // private unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, byte[] input, AsymmetricPaddingMode paddingMode, void* paddingInfo, EncryptOrDecryptAction encryptOrDecrypt) { int estimatedSize = KeySize / 8; #if DEBUG estimatedSize = 2; // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised. #endif byte[] output = new byte[estimatedSize]; int numBytesNeeded; ErrorCode errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode); if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL) { output = new byte[numBytesNeeded]; errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode); } if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); Array.Resize(ref output, numBytesNeeded); return output; }
// // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption. // private static unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, byte[] input, AsymmetricPaddingMode paddingMode, void* paddingInfo, EncryptOrDecryptAction encryptOrDecrypt) { int numBytesNeeded; ErrorCode errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, null, 0, out numBytesNeeded, paddingMode); if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); byte[] output = new byte[numBytesNeeded]; errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, output, numBytesNeeded, out numBytesNeeded, paddingMode); if (errorCode != ErrorCode.ERROR_SUCCESS) throw errorCode.ToCryptographicException(); return output; }
// // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption. // private static unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, byte[] input, AsymmetricPaddingMode paddingMode, void *paddingInfo, EncryptOrDecryptAction encryptOrDecrypt) { int numBytesNeeded; ErrorCode errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, null, 0, out numBytesNeeded, paddingMode); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } byte[] output = new byte[numBytesNeeded]; errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, output, numBytesNeeded, out numBytesNeeded, paddingMode); if (errorCode != ErrorCode.ERROR_SUCCESS) { throw errorCode.ToCryptographicException(); } return(output); }