/// <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);
                }
            }
        }
Example #3
0
        //
        // 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);
            }
        }
Example #4
0
        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);
                }
            }
        }
Example #5
0
        //
        // 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);
            }
        }