Пример #1
0
        public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));

            return VerifyData(data, 0, data.Length, signature, hashAlgorithm, padding);
        }
Пример #2
0
        /// <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("hash");

            unsafe
            {
                byte[] signature = null;
                SignOrVerify(padding, hashAlgorithm, hash,
                    delegate (AsymmetricPaddingMode paddingMode, void* pPaddingInfo)
                    {
                        SafeNCryptKeyHandle keyHandle = Key.Handle;
                        int numBytesNeeded;
                        ErrorCode errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, null, 0, out numBytesNeeded, paddingMode);
                        if (errorCode != ErrorCode.ERROR_SUCCESS)
                            throw errorCode.ToCryptographicException();

                        signature = new byte[numBytesNeeded];
                        errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
                        if (errorCode != ErrorCode.ERROR_SUCCESS)
                            throw errorCode.ToCryptographicException();
                    }
                );
                return signature;
            }
        }
        private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithmName)
        {
            HashAlgorithm hasher;

            if (hashAlgorithmName == HashAlgorithmName.MD5)
            {
                hasher = MD5.Create();
            }
            else if (hashAlgorithmName == HashAlgorithmName.SHA1)
            {
                hasher = SHA1.Create();
            }
            else if (hashAlgorithmName == HashAlgorithmName.SHA256)
            {
                hasher = SHA256.Create();
            }
            else if (hashAlgorithmName == HashAlgorithmName.SHA384)
            {
                hasher = SHA384.Create();
            }
            else if (hashAlgorithmName == HashAlgorithmName.SHA512)
            {
                hasher = SHA512.Create();
            }
            else
            {
                throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName.Name);
            }

            return hasher;
        }
Пример #4
0
        /// <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("hash");

            unsafe
            {
                byte[] signature = null;
                SignOrVerify(padding, hashAlgorithm, hash,
                    delegate (AsymmetricPaddingMode paddingMode, void* pPaddingInfo)
                    {
                        int estimatedSize = KeySize / 8;
#if DEBUG
                        estimatedSize = 2;  // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised.
#endif
                        SafeNCryptKeyHandle keyHandle = Key.Handle;

                        signature = new byte[estimatedSize];
                        int numBytesNeeded;
                        ErrorCode errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
                        if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
                        {
                            signature = new byte[numBytesNeeded];
                            errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
                        }
                        if (errorCode != ErrorCode.ERROR_SUCCESS)
                            throw errorCode.ToCryptographicException();

                        Array.Resize(ref signature, numBytesNeeded);
                    }
                );
                return signature;
            }
        }
Пример #5
0
        /// <summary>
        ///     Verifies that alleged signature of a hash is, in fact, a valid signature of that hash.
        /// </summary>
        public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (hash == null)
                throw new ArgumentNullException("hash");
            if (signature == null)
                throw new ArgumentNullException("signature");

            unsafe
            {
                bool verified = false;
                SignOrVerify(padding, hashAlgorithm, hash,
                    delegate (AsymmetricPaddingMode paddingMode, void* pPaddingInfo)
                    {
                        SafeNCryptKeyHandle keyHandle = Key.Handle;
                        ErrorCode errorCode = Interop.NCrypt.NCryptVerifySignature(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, paddingMode);
                        if (errorCode == ErrorCode.ERROR_SUCCESS)
                            verified = true;
                        else if (errorCode == ErrorCode.NTE_BAD_SIGNATURE)
                            verified = false;
                        else
                            throw errorCode.ToCryptographicException();
                    }
                );
                return verified;
            }
        }
Пример #6
0
        private IncrementalHash(HashAlgorithmName name, HMACCommon hmac)
        {
            Debug.Assert(name != null);
            Debug.Assert(!string.IsNullOrEmpty(name.Name));
            Debug.Assert(hmac != null);

            _algorithmName = new HashAlgorithmName("HMAC" + name.Name);
            _hmac = hmac;
        }
Пример #7
0
        public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            return SignData(data, 0, data.Length, hashAlgorithm, padding);
        }
Пример #8
0
        private IncrementalHash(HashAlgorithmName name, HashProvider hash)
        {
            Debug.Assert(name != null);
            Debug.Assert(!string.IsNullOrEmpty(name.Name));
            Debug.Assert(hash != null);

            _algorithmName = name;
            _hash = hash;
        }
        public static byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm)
        {
            // The classes that call us are sealed and their base class has checked this already.
            Debug.Assert(data != null);
            Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));

            using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithm))
            {
                return hasher.ComputeHash(data);
            }
        }
Пример #10
0
        public virtual byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw HashAlgorithmNameNullOrEmpty();
            if (padding == null)
                throw new ArgumentNullException(nameof(padding));

            byte[] hash = HashData(data, hashAlgorithm);
            return SignHash(hash, hashAlgorithm, padding);
        }
        public static byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
        {
            // The classes that call us are sealed and their base class has checked this already.
            Debug.Assert(data != null);
            Debug.Assert(count >= 0 && count <= data.Length);
            Debug.Assert(offset >= 0 && offset <= data.Length - count);
            Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));

            using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithm))
            {
                return hasher.ComputeHash(data, offset, count);
            }
        }
Пример #12
0
        public static byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
        {
            // The classes that call us are sealed and their base class has checked this already.
            Debug.Assert(data != null);
            Debug.Assert(offset >= 0 && offset <= data.Length);
            Debug.Assert(count >= 0 && count <= data.Length);
            Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));

            using (HashProviderCng hashProvider = new HashProviderCng(hashAlgorithm.Name, null))
            {
                hashProvider.AppendHashData(data, offset, count);
                byte[] hash = hashProvider.FinalizeHashAndReset();
                return hash;
            }
        }
Пример #13
0
        /// <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));

            unsafe
            {
                byte[] signature = null;
                SignOrVerify(padding, hashAlgorithm, hash,
                    delegate (AsymmetricPaddingMode paddingMode, void* pPaddingInfo)
                    {
                        int estimatedSize = KeySize / 8;
                        signature = GetKeyHandle().SignHash(hash, paddingMode, pPaddingInfo, estimatedSize);
                    }
                );
                return signature;
            }
        }
Пример #14
0
        public static byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm)
        {
            // The classes that call us are sealed and their base class has checked this already.
            Debug.Assert(data != null);
            Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));

            using (HashProviderCng hashProvider = new HashProviderCng(hashAlgorithm.Name, null))
            {
                // Default the buffer size to 4K.
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = data.Read(buffer, 0, buffer.Length)) > 0)
                {
                    hashProvider.AppendHashData(buffer, 0, bytesRead);
                }
                byte[] hash = hashProvider.FinalizeHashAndReset();
                return hash;
            }
        }
Пример #15
0
        /// <summary>
        ///     Verifies that alleged signature of a hash is, in fact, a valid signature of that hash.
        /// </summary>
        public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (hash == null)
                throw new ArgumentNullException(nameof(hash));
            if (signature == null)
                throw new ArgumentNullException(nameof(signature));

            unsafe
            {
                bool verified = false;
                SignOrVerify(padding, hashAlgorithm, hash,
                    delegate (AsymmetricPaddingMode paddingMode, void* pPaddingInfo)
                    {
                        verified = GetKeyHandle().VerifyHash(hash, signature, paddingMode, pPaddingInfo);
                    }
                );
                return verified;
            }
        }
Пример #16
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);
            }
        }
Пример #17
0
        public virtual byte[] SignData(
            byte[] data,
            int offset,
            int count,
            HashAlgorithmName hashAlgorithm,
            RSASignaturePadding padding)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
            if (offset < 0 || offset > data.Length)
                throw new ArgumentOutOfRangeException(nameof(offset));
            if (count < 0 || count > data.Length - offset)
                throw new ArgumentOutOfRangeException(nameof(count));
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw HashAlgorithmNameNullOrEmpty();
            if (padding == null)
                throw new ArgumentNullException(nameof(padding));

            byte[] hash = HashData(data, offset, count, hashAlgorithm);
            return SignHash(hash, hashAlgorithm, padding);
        }
Пример #18
0
        /// <summary>
        ///     Verifies that alleged signature of a hash is, in fact, a valid signature of that hash.
        /// </summary>
        public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (hash == null)
                throw new ArgumentNullException("hash");
            if (signature == null)
                throw new ArgumentNullException("signature");

            unsafe
            {
                bool verified = false;
                SignOrVerify(padding, hashAlgorithm, hash,
                    delegate (AsymmetricPaddingMode paddingMode, void* pPaddingInfo)
                    {
                        SafeNCryptKeyHandle keyHandle = Key.Handle;
                        ErrorCode errorCode = Interop.NCrypt.NCryptVerifySignature(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, paddingMode);
                        verified = (errorCode == ErrorCode.ERROR_SUCCESS);  // For consistency with other RSA classes, return "false" for any error code rather than making the caller catch an exception.
                    }
                );
                return verified;
            }
        }
Пример #19
0
        public virtual bool VerifyData(
            byte[] data,
            int offset,
            int count,
            byte[] signature,
            HashAlgorithmName hashAlgorithm,
            RSASignaturePadding padding)
        {
            if (data == null)
                throw new ArgumentNullException("data");
            if (offset < 0 || offset > data.Length)
                throw new ArgumentOutOfRangeException("offset");
            if (count < 0 || count > data.Length - offset)
                throw new ArgumentOutOfRangeException("count");
            if (signature == null)
                throw new ArgumentNullException("signature");
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw HashAlgorithmNameNullOrEmpty();
            if (padding == null)
                throw new ArgumentNullException("padding");

            byte[] hash = HashData(data, offset, count, hashAlgorithm);
            return VerifyHash(hash, signature, hashAlgorithm, padding);
        }
Пример #20
0
        /// <summary>
        /// Create an <see cref="IncrementalHash"/> for the Hash-based Message Authentication Code (HMAC)
        /// algorithm utilizing the hash algorithm specified by <paramref name="hashAlgorithm"/>, and a
        /// key specified by <paramref name="key"/>.
        /// </summary>
        /// <param name="hashAlgorithm">The name of the hash algorithm to perform within the HMAC.</param>
        /// <param name="key">
        ///     The secret key for the HMAC. The key can be any length, but a key longer than the output size
        ///     of the hash algorithm specified by <paramref name="hashAlgorithm"/> will be hashed (using the
        ///     algorithm specified by <paramref name="hashAlgorithm"/>) to derive a correctly-sized key. Therefore,
        ///     the recommended size of the secret key is the output size of the hash specified by
        ///     <paramref name="hashAlgorithm"/>.
        /// </param>
        /// <returns>
        /// An <see cref="IncrementalHash"/> instance ready to compute the hash algorithm specified
        /// by <paramref name="hashAlgorithm"/>.
        /// </returns>
        /// <exception cref="ArgumentException">
        ///     <paramref name="hashAlgorithm"/>.<see cref="HashAlgorithmName.Name"/> is <c>null</c>, or
        ///     the empty string.
        /// </exception>
        /// <exception cref="CryptographicException"><paramref name="hashAlgorithm"/> is not a known hash algorithm.</exception>
        public static IncrementalHash CreateHMAC(HashAlgorithmName hashAlgorithm, byte[] key)
        {
            if (key == null)
                throw new ArgumentNullException(nameof(key));
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm));

            return new IncrementalHash(hashAlgorithm, new HMACCommon(hashAlgorithm.Name, key, -1));
        }
Пример #21
0
        /// <summary>
        /// Create an <see cref="IncrementalHash"/> for the algorithm specified by <paramref name="hashAlgorithm"/>.
        /// </summary>
        /// <param name="hashAlgorithm">The name of the hash algorithm to perform.</param>
        /// <returns>
        /// An <see cref="IncrementalHash"/> instance ready to compute the hash algorithm specified
        /// by <paramref name="hashAlgorithm"/>.
        /// </returns>
        /// <exception cref="ArgumentException">
        ///     <paramref name="hashAlgorithm"/>.<see cref="HashAlgorithmName.Name"/> is <c>null</c>, or
        ///     the empty string.
        /// </exception>
        /// <exception cref="CryptographicException"><paramref name="hashAlgorithm"/> is not a known hash algorithm.</exception>
        public static IncrementalHash CreateHash(HashAlgorithmName hashAlgorithm)
        {
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm));

            return new IncrementalHash(hashAlgorithm, HashProviderDispenser.CreateHashProvider(hashAlgorithm.Name));
        }
Пример #22
0
 protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
 {
     return OpenSslAsymmetricAlgorithmCore.HashData(data, offset, count, hashAlgorithm);
 }
Пример #23
0
        private bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithmName)
        {
            int algorithmNid = GetAlgorithmNid(hashAlgorithmName);
            SafeRsaHandle rsa = _key.Value;

            return Interop.Crypto.RsaVerify(
                algorithmNid,
                hash,
                hash.Length,
                signature,
                signature.Length,
                rsa);
        }
Пример #24
0
        private static int GetAlgorithmNid(HashAlgorithmName hashAlgorithmName)
        {
            // All of the current HashAlgorithmName values correspond to the SN values in OpenSSL 0.9.8.
            // If there's ever a new one that doesn't, translate it here.
            string sn = hashAlgorithmName.Name;

            int nid = Interop.Crypto.ObjSn2Nid(sn);

            if (nid == Interop.Crypto.NID_undef)
            {
                throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName.Name);
            }

            return nid;
        }
Пример #25
0
        public override bool VerifyHash(
            byte[] hash,
            byte[] signature,
            HashAlgorithmName hashAlgorithm,
            RSASignaturePadding padding)
        {
            if (hash == null)
                throw new ArgumentNullException("hash");
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw HashAlgorithmNameNullOrEmpty();
            if (padding == null)
                throw new ArgumentNullException("padding");
            if (padding != RSASignaturePadding.Pkcs1)
                throw PaddingModeNotSupported();

            return VerifyHash(hash, signature, hashAlgorithm);
        }
Пример #26
0
        private byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithmName)
        {
            int algorithmNid = GetAlgorithmNid(hashAlgorithmName);
            SafeRsaHandle rsa = _key.Value;
            byte[] signature = new byte[Interop.Crypto.RsaSize(rsa)];
            int signatureSize;

            bool success = Interop.Crypto.RsaSign(
                algorithmNid,
                hash,
                hash.Length,
                signature,
                out signatureSize,
                rsa);

            if (!success)
            {
                throw Interop.Crypto.CreateOpenSslCryptographicException();
            }

            Debug.Assert(
                signatureSize == signature.Length,
                "RSA_sign reported an unexpected signature size",
                "RSA_sign reported signatureSize was {0}, when {1} was expected",
                signatureSize,
                signature.Length);

            return signature;
        }
Пример #27
0
 internal byte[] HashData(Stream stream, HashAlgorithmName hashAlgorithmName)
 {
     using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithmName))
     {
         return hasher.ComputeHash(stream);
     }
 }
Пример #28
0
 internal byte[] HashData(byte[] buffer, int offset, int count, HashAlgorithmName hashAlgorithmName)
 {
     using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithmName))
     {
         return hasher.ComputeHash(buffer, offset, count);
     }
 }
Пример #29
0
        public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (hash == null)
                throw new ArgumentNullException(nameof(hash));
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
                throw HashAlgorithmNameNullOrEmpty();
            if (padding == null)
                throw new ArgumentNullException(nameof(padding));
            if (padding != RSASignaturePadding.Pkcs1)
                throw PaddingModeNotSupported();

            return SignHash(hash, hashAlgorithm);
        }
Пример #30
0
 protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm)
 {
     return OpenSslAsymmetricAlgorithmCore.HashData(data, hashAlgorithm);
 }
        public static bool TryHashData(ReadOnlySpan <byte> source, Span <byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten)
        {
            // The classes that call us are sealed and their base class has checked this already.
            Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));

            return
                (hashAlgorithm == HashAlgorithmName.SHA256 ? SHA256.TryHashData(source, destination, out bytesWritten) :
                 hashAlgorithm == HashAlgorithmName.SHA1 ? SHA1.TryHashData(source, destination, out bytesWritten) :
                 hashAlgorithm == HashAlgorithmName.SHA512 ? SHA512.TryHashData(source, destination, out bytesWritten) :
                 hashAlgorithm == HashAlgorithmName.SHA384 ? SHA384.TryHashData(source, destination, out bytesWritten) :
                 hashAlgorithm == HashAlgorithmName.MD5 ? MD5.TryHashData(source, destination, out bytesWritten) :
                 throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name));
        }