// // 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); } }
/// <summary> /// Performs a signing or verification operation. /// </summary> /// <param name="action">The delegate that will actually perform the cryptographic operation.</param> /// <remarks> /// This method should not throw an error when verifying a signature and /// the signature is invalid. Rather, the delegate should retain the result of /// verification and the caller of this method should share that closure and /// return the result. /// </remarks> protected unsafe void SignOrVerify(SignOrVerifyAction action) { Requires.NotNull(action, nameof(action)); if (this.SignaturePadding.Value == AsymmetricSignaturePadding.None) { action(null, NCryptSignHashFlags.None); } else { char[] hashAlgorithmName = HashAlgorithmProviderFactory.GetHashAlgorithmName(this.SignatureHash.Value).ToCharArrayWithNullTerminator(); fixed(char *hashAlgorithmNamePointer = &hashAlgorithmName[0]) { switch (this.SignaturePadding.Value) { case AsymmetricSignaturePadding.Pkcs1: var pkcs1PaddingInfo = new BCrypt.BCRYPT_PKCS1_PADDING_INFO { pszAlgId = hashAlgorithmNamePointer, }; action(&pkcs1PaddingInfo, NCryptSignHashFlags.BCRYPT_PAD_PKCS1); break; case AsymmetricSignaturePadding.Pss: var pssPaddingInfo = new BCrypt.BCRYPT_PSS_PADDING_INFO { pszAlgId = hashAlgorithmNamePointer, cbSalt = hashAlgorithmName.Length, }; action(&pssPaddingInfo, NCryptSignHashFlags.BCRYPT_PAD_PSS); break; default: throw new NotImplementedException(); } } } }
// // 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); } }