/// <summary> /// Computes the signature of a hash that was produced by the hash algorithm specified by "hashAlgorithm." /// </summary> public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { if (hash == null) { throw new ArgumentNullException(nameof(hash)); } string?hashAlgorithmName = hashAlgorithm.Name; if (string.IsNullOrEmpty(hashAlgorithmName)) { throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } if (hash.Length != GetHashSizeInBytes(hashAlgorithm)) { throw new CryptographicException(SR.Cryptography_SignHash_WrongSize); } using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { IntPtr namePtr = Marshal.StringToHGlobalUni(hashAlgorithmName); try { unsafe { int estimatedSize = KeySize / 8; switch (padding.Mode) { case RSASignaturePaddingMode.Pkcs1: var pkcsPaddingInfo = new BCRYPT_PKCS1_PADDING_INFO() { pszAlgId = namePtr }; return(keyHandle.SignHash(hash, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, &pkcsPaddingInfo, estimatedSize)); case RSASignaturePaddingMode.Pss: var pssPaddingInfo = new BCRYPT_PSS_PADDING_INFO() { pszAlgId = namePtr, cbSalt = hash.Length }; return(keyHandle.SignHash(hash, AsymmetricPaddingMode.NCRYPT_PAD_PSS_FLAG, &pssPaddingInfo, estimatedSize)); default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } } } finally { Marshal.FreeHGlobal(namePtr); } } }
public override unsafe bool VerifyHash(ReadOnlySpan <byte> hash, ReadOnlySpan <byte> signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { string?hashAlgorithmName = hashAlgorithm.Name; if (string.IsNullOrEmpty(hashAlgorithmName)) { throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { if (hash.Length != GetHashSizeInBytes(hashAlgorithm)) { return(false); } IntPtr namePtr = Marshal.StringToHGlobalUni(hashAlgorithmName); try { switch (padding.Mode) { case RSASignaturePaddingMode.Pkcs1: var pkcs1PaddingInfo = new BCRYPT_PKCS1_PADDING_INFO() { pszAlgId = namePtr }; return(keyHandle.VerifyHash(hash, signature, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, &pkcs1PaddingInfo)); case RSASignaturePaddingMode.Pss: var pssPaddingInfo = new BCRYPT_PSS_PADDING_INFO() { pszAlgId = namePtr, cbSalt = hash.Length }; return(keyHandle.VerifyHash(hash, signature, AsymmetricPaddingMode.NCRYPT_PAD_PSS_FLAG, &pssPaddingInfo)); default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } } finally { Marshal.FreeHGlobal(namePtr); } } }
// // Common helper for SignHash() and VerifyHash(). Creates the necessary PADDING_INFO structure based on the chosen padding mode and then passes it // to "signOrVerify" which performs the actual signing or verification. // private static unsafe void SignOrVerify(RSASignaturePadding padding, HashAlgorithmName hashAlgorithm, byte[] hash, SignOrVerifyAction signOrVerify) { string hashAlgorithmName = hashAlgorithm.Name; if (string.IsNullOrEmpty(hashAlgorithmName)) { throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } switch (padding.Mode) { case RSASignaturePaddingMode.Pkcs1: { using (SafeUnicodeStringHandle safeHashAlgorithmName = new SafeUnicodeStringHandle(hashAlgorithmName)) { BCRYPT_PKCS1_PADDING_INFO paddingInfo = new BCRYPT_PKCS1_PADDING_INFO() { pszAlgId = safeHashAlgorithmName.DangerousGetHandle(), }; signOrVerify(AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, &paddingInfo); } break; } case RSASignaturePaddingMode.Pss: { using (SafeUnicodeStringHandle safeHashAlgorithmName = new SafeUnicodeStringHandle(hashAlgorithmName)) { BCRYPT_PSS_PADDING_INFO paddingInfo = new BCRYPT_PSS_PADDING_INFO() { pszAlgId = safeHashAlgorithmName.DangerousGetHandle(), cbSalt = hash.Length, }; signOrVerify(AsymmetricPaddingMode.NCRYPT_PAD_PSS_FLAG, &paddingInfo); } break; } default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } }
public override unsafe bool TrySignHash(ReadOnlySpan <byte> hash, Span <byte> destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { string?hashAlgorithmName = hashAlgorithm.Name; ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); ArgumentNullException.ThrowIfNull(padding); using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { if (hash.Length != GetHashSizeInBytes(hashAlgorithm)) { throw new CryptographicException(SR.Cryptography_SignHash_WrongSize); } IntPtr namePtr = Marshal.StringToHGlobalUni(hashAlgorithmName); try { switch (padding.Mode) { case RSASignaturePaddingMode.Pkcs1: var pkcs1PaddingInfo = new BCRYPT_PKCS1_PADDING_INFO() { pszAlgId = namePtr }; return(keyHandle.TrySignHash(hash, destination, AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, &pkcs1PaddingInfo, out bytesWritten)); case RSASignaturePaddingMode.Pss: var pssPaddingInfo = new BCRYPT_PSS_PADDING_INFO() { pszAlgId = namePtr, cbSalt = hash.Length }; return(keyHandle.TrySignHash(hash, destination, AsymmetricPaddingMode.NCRYPT_PAD_PSS_FLAG, &pssPaddingInfo, out bytesWritten)); default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } } finally { Marshal.FreeHGlobal(namePtr); } } }
// // Common helper for SignHash() and VerifyHash(). Creates the necessary PADDING_INFO structure based on the chosen padding mode and then passes it // to "signOrVerify" which performs the actual signing or verification. // private static unsafe void SignOrVerify(RSASignaturePadding padding, HashAlgorithmName hashAlgorithm, byte[] hash, SignOrVerifyAction signOrVerify) { string hashAlgorithmName = hashAlgorithm.Name; if (string.IsNullOrEmpty(hashAlgorithmName)) throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); if (padding == null) throw new ArgumentNullException("padding"); switch (padding.Mode) { case RSASignaturePaddingMode.Pkcs1: { using (SafeUnicodeStringHandle safeHashAlgorithmName = new SafeUnicodeStringHandle(hashAlgorithmName)) { BCRYPT_PKCS1_PADDING_INFO paddingInfo = new BCRYPT_PKCS1_PADDING_INFO() { pszAlgId = safeHashAlgorithmName.DangerousGetHandle(), }; signOrVerify(AsymmetricPaddingMode.NCRYPT_PAD_PKCS1_FLAG, &paddingInfo); } break; } case RSASignaturePaddingMode.Pss: { using (SafeUnicodeStringHandle safeHashAlgorithmName = new SafeUnicodeStringHandle(hashAlgorithmName)) { BCRYPT_PSS_PADDING_INFO paddingInfo = new BCRYPT_PSS_PADDING_INFO() { pszAlgId = safeHashAlgorithmName.DangerousGetHandle(), cbSalt = hash.Length, }; signOrVerify(AsymmetricPaddingMode.NCRYPT_PAD_PSS_FLAG, &paddingInfo); } break; } default: throw new CryptographicException(SR.Cryptography_UnsupportedPaddingMode); } }