public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } ThrowIfDisposed(); int rsaSize = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize); if (destination.Length < rsaSize) { bytesWritten = 0; return(false); } if (padding == RSAEncryptionPadding.Pkcs1 && data.Length > 0) { const int Pkcs1PaddingOverhead = 11; int maxAllowed = rsaSize - Pkcs1PaddingOverhead; if (data.Length > maxAllowed) { throw new CryptographicException( SR.Format(SR.Cryptography_Encryption_MessageTooLong, maxAllowed)); } return(Interop.AppleCrypto.TryRsaEncrypt( GetKeys().PublicKey, data, destination, padding, out bytesWritten)); } RsaPaddingProcessor processor; switch (padding.Mode) { case RSAEncryptionPaddingMode.Pkcs1: processor = null; break; case RSAEncryptionPaddingMode.Oaep: processor = RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm); break; default: throw new CryptographicException(SR.Cryptography_InvalidPaddingMode); } byte[] rented = CryptoPool.Rent(rsaSize); Span <byte> tmp = new Span <byte>(rented, 0, rsaSize); try { if (processor != null) { processor.PadOaep(data, tmp); } else { Debug.Assert(padding.Mode == RSAEncryptionPaddingMode.Pkcs1); RsaPaddingProcessor.PadPkcs1Encryption(data, tmp); } return(Interop.AppleCrypto.TryRsaEncryptionPrimitive( GetKeys().PublicKey, tmp, destination, out bytesWritten)); } finally { CryptographicOperations.ZeroMemory(tmp); CryptoPool.Return(rented, clearSize: 0); } }
public override bool TryDecrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } SecKeyPair keys = GetKeys(); if (keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } return(TryDecrypt(keys.PrivateKey, data, destination, padding, out bytesWritten)); }
// Conveniently, Encrypt() and Decrypt() are identical save for the actual P/Invoke call to CNG. Thus, both // array-based APIs invoke this common helper with the "encrypt" parameter determining whether encryption or decryption is done. private unsafe byte[] EncryptOrDecrypt(byte[] data, RSAEncryptionPadding padding, bool encrypt) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } int modulusSizeInBytes = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize); if (!encrypt && data.Length != modulusSizeInBytes) { throw new CryptographicException(SR.Cryptography_RSA_DecryptWrongSize); } if (encrypt && padding.Mode == RSAEncryptionPaddingMode.Pkcs1 && data.Length > modulusSizeInBytes - Pkcs1PaddingOverhead) { throw new CryptographicException( SR.Format(SR.Cryptography_Encryption_MessageTooLong, modulusSizeInBytes - Pkcs1PaddingOverhead)); } using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { if (encrypt && data.Length == 0) { byte[] rented = CryptoPool.Rent(modulusSizeInBytes); Span <byte> paddedMessage = new Span <byte>(rented, 0, modulusSizeInBytes); try { if (padding == RSAEncryptionPadding.Pkcs1) { RsaPaddingProcessor.PadPkcs1Encryption(data, paddedMessage); } else if (padding.Mode == RSAEncryptionPaddingMode.Oaep) { RsaPaddingProcessor processor = RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm); processor.PadOaep(data, paddedMessage); } else { throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } return(EncryptOrDecrypt(keyHandle, paddedMessage, AsymmetricPaddingMode.NCRYPT_NO_PADDING_FLAG, null, encrypt)); } finally { CryptographicOperations.ZeroMemory(paddedMessage); CryptoPool.Return(rented, clearSize: 0); } } switch (padding.Mode) { case RSAEncryptionPaddingMode.Pkcs1: return(EncryptOrDecrypt(keyHandle, data, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, null, encrypt)); case RSAEncryptionPaddingMode.Oaep: IntPtr namePtr = Marshal.StringToHGlobalUni(padding.OaepHashAlgorithm.Name); try { var paddingInfo = new BCRYPT_OAEP_PADDING_INFO() { pszAlgId = namePtr, // 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, encrypt)); } finally { Marshal.FreeHGlobal(namePtr); } default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } } }
public virtual byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) { throw RSA.DerivedClassMustOverride(); }
/// <summary> /// /// </summary> /// <param name="input"></param> /// <param name="privateKey_xml">密钥</param> /// <param name="encryptionPadding">OaepSHA1|OaepSHA256|OaepSHA384|OaepSHA512|Pkcs1</param> /// <returns></returns> public static byte[] RSADecrypt(this byte[] input, Stream privateKey_xml, RSAEncryptionPadding encryptionPadding) => RSADecrypt_(input, privateKey_xml, encryptionPadding);
/// <summary>Decrypts data using the private key.</summary> public override bool TryDecrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) => TryEncryptOrDecrypt(data, destination, padding, encrypt: false, bytesWritten: out bytesWritten);
public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } ValidatePadding(padding); SafeEvpPKeyHandle?key = GetKey(); return(TryEncrypt(key, data, destination, padding, out bytesWritten)); }
public virtual byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) => throw DerivedClassMustOverride();
public abstract byte[] Decrypt(byte[] data, RSAEncryptionPadding padding);
public override bool TryDecrypt( ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } ValidatePadding(padding); SafeEvpPKeyHandle key = GetKey(); int keySizeBytes = Interop.Crypto.EvpPKeySize(key); // OpenSSL requires that the decryption buffer be at least as large as EVP_PKEY_size. // So if the destination is too small, use a temporary buffer so we can match // Windows behavior of succeeding so long as the buffer can hold the final output. if (destination.Length < keySizeBytes) { // RSA up through 4096 bits use a stackalloc Span <byte> tmp = stackalloc byte[512]; byte[]? rent = null; if (keySizeBytes > tmp.Length) { rent = CryptoPool.Rent(keySizeBytes); tmp = rent; } int written = Decrypt(key, data, tmp, padding); bool ret; if (destination.Length < written) { bytesWritten = 0; ret = false; } else { tmp.Slice(0, written).CopyTo(destination); bytesWritten = written; ret = true; } // Whether a stackalloc or a rented array, clear our copy of // the decrypted content. CryptographicOperations.ZeroMemory(tmp.Slice(0, written)); if (rent != null) { // Already cleared. CryptoPool.Return(rent, clearSize: 0); } return(ret); } bytesWritten = Decrypt(key, data, destination, padding); return(true); }
public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } int rsaSize = RsaPaddingProcessor.BytesRequiredForBitCount(KeySize); if (destination.Length < rsaSize) { bytesWritten = 0; return(false); } if (padding == RSAEncryptionPadding.Pkcs1 && data.Length > 0) { return(Interop.AppleCrypto.TryRsaEncrypt( GetKeys().PublicKey, data, destination, padding, out bytesWritten)); } RsaPaddingProcessor processor; switch (padding.Mode) { case RSAEncryptionPaddingMode.Pkcs1: processor = null; break; case RSAEncryptionPaddingMode.Oaep: processor = RsaPaddingProcessor.OpenProcessor(padding.OaepHashAlgorithm); break; default: throw new CryptographicException(SR.Cryptography_InvalidPaddingMode); } byte[] rented = ArrayPool <byte> .Shared.Rent(rsaSize); Span <byte> tmp = new Span <byte>(rented, 0, rsaSize); try { if (processor != null) { processor.PadOaep(data, tmp); } else { Debug.Assert(padding.Mode == RSAEncryptionPaddingMode.Pkcs1); RsaPaddingProcessor.PadPkcs1Encryption(data, tmp); } return(Interop.AppleCrypto.TryRsaEncryptionPrimitive( GetKeys().PublicKey, tmp, destination, out bytesWritten)); } finally { tmp.Clear(); ArrayPool <byte> .Shared.Return(rented); } }
public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { ArgumentNullException.ThrowIfNull(padding); Interop.AndroidCrypto.RsaPadding rsaPadding = GetInteropPadding(padding); SafeRsaHandle key = GetKey(); return(TryEncrypt(key, data, destination, rsaPadding, out bytesWritten)); }
// Conveniently, Encrypt() and Decrypt() are identical save for the actual P/Invoke call to CNG. Thus, both // span-based APIs invoke this common helper with the "encrypt" parameter determining whether encryption or decryption is done. private unsafe bool TryEncryptOrDecrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, bool encrypt, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { switch (padding.Mode) { case RSAEncryptionPaddingMode.Pkcs1: return(TryEncryptOrDecrypt(keyHandle, data, destination, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, null, encrypt, out bytesWritten)); case RSAEncryptionPaddingMode.Oaep: IntPtr namePtr = Marshal.StringToHGlobalUni(padding.OaepHashAlgorithm.Name); try { var paddingInfo = new BCRYPT_OAEP_PADDING_INFO() { pszAlgId = namePtr, pbLabel = IntPtr.Zero, // It would nice to put randomized data here but RSAEncryptionPadding does not at this point provide support for this. cbLabel = 0, }; return(TryEncryptOrDecrypt(keyHandle, data, destination, AsymmetricPaddingMode.NCRYPT_PAD_OAEP_FLAG, &paddingInfo, encrypt, out bytesWritten)); } finally { Marshal.FreeHGlobal(namePtr); } default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } } }
public override bool TryDecrypt( ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } Interop.Crypto.RsaPadding rsaPadding = GetInteropPadding(padding, out RsaPaddingProcessor oaepProcessor); SafeRsaHandle key = GetKey(); int keySizeBytes = Interop.Crypto.RsaSize(key); // OpenSSL does not take a length value for the destination, so it can write out of bounds. // To prevent the OOB write, decrypt into a temporary buffer. if (destination.Length < keySizeBytes) { Span <byte> tmp = stackalloc byte[0]; byte[] rent = null; // RSA up through 4096 stackalloc if (keySizeBytes <= 512) { tmp = stackalloc byte[keySizeBytes]; } else { rent = ArrayPool <byte> .Shared.Rent(keySizeBytes); tmp = rent; } bool ret = TryDecrypt(key, data, tmp, rsaPadding, oaepProcessor, out bytesWritten); if (ret) { tmp = tmp.Slice(0, bytesWritten); if (bytesWritten > destination.Length) { ret = false; bytesWritten = 0; } else { tmp.CopyTo(destination); } CryptographicOperations.ZeroMemory(tmp); } if (rent != null) { // Already cleared ArrayPool <byte> .Shared.Return(rent); } return(ret); } return(TryDecrypt(key, data, destination, rsaPadding, oaepProcessor, out bytesWritten)); }
/// <summary>Encrypts data using the public key.</summary> public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) => EncryptOrDecrypt(data, padding, encrypt: true);
public override bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { if (padding == null) { throw new ArgumentNullException(nameof(padding)); } Interop.Crypto.RsaPadding rsaPadding = GetInteropPadding(padding, out RsaPaddingProcessor oaepProcessor); SafeRsaHandle key = GetKey(); return(TryEncrypt(key, data, destination, rsaPadding, oaepProcessor, out bytesWritten)); }
/// <summary>Decrypts data using the private key.</summary> public override unsafe byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) => EncryptOrDecrypt(data, padding, encrypt: false);
public virtual bool TryEncrypt(ReadOnlySpan <byte> data, Span <byte> destination, RSAEncryptionPadding padding, out int bytesWritten) { byte[] result = Encrypt(data.ToArray(), padding); if (destination.Length >= result.Length) { new ReadOnlySpan <byte>(result).CopyTo(destination); bytesWritten = result.Length; return(true); } bytesWritten = 0; return(false); }
public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) { return(Interop.AppleCrypto.RsaEncrypt(GetKeys().PublicKey, data, padding)); }