BCryptHashAlgorithm.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Security / Cryptography / BCryptHashAlgorithm.cs / 1305376 / BCryptHashAlgorithm.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 

using System; 
using System.Diagnostics; 
using System.Diagnostics.CodeAnalysis;
using System.IO; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics.Contracts;
using Microsoft.Win32.SafeHandles; 

namespace System.Security.Cryptography { 
    ///  
    ///     Implementation of a generic BCrypt hashing algorithm, concrete HashAlgorithm classes
    ///     implemented by BCrypt can contain an instance of this class and delegate the work to it. 
    /// 
    internal sealed class BCryptHashAlgorithm : IDisposable {
        private SafeBCryptAlgorithmHandle m_algorithmHandle;
        private SafeBCryptHashHandle m_hashHandle; 

        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public BCryptHashAlgorithm(CngAlgorithm algorithm, string implementation) { 
            Contract.Requires(algorithm != null);
            Contract.Requires(!String.IsNullOrEmpty(implementation)); 
            Contract.Ensures(m_algorithmHandle != null && !m_algorithmHandle.IsInvalid && !m_algorithmHandle.IsClosed);
            Contract.Ensures(m_hashHandle != null && !m_hashHandle.IsInvalid && !m_hashHandle.IsClosed);

            // Make sure CNG is supported on this platform 
            if (!BCryptNative.BCryptSupported) {
                throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); 
            } 

            m_algorithmHandle = BCryptNative.OpenAlgorithm(algorithm.Algorithm, implementation); 

            Initialize();
        }
 
        /// 
        ///     Clean up the hash algorithm 
        ///  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public void Dispose() { 
            Contract.Ensures(m_hashHandle == null || m_hashHandle.IsClosed); 
            Contract.Ensures(m_algorithmHandle == null || m_algorithmHandle.IsClosed);
 
            if (m_hashHandle != null) {
                m_hashHandle.Dispose();
            }
 
            if (m_algorithmHandle != null) {
                m_algorithmHandle.Dispose(); 
            } 
        }
 
        /// 
        ///     Reset the hash algorithm to begin hashing a new set of data
        /// 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Reviewed")]
        public void Initialize() {
            Contract.Ensures(m_hashHandle != null && !m_hashHandle.IsInvalid && !m_hashHandle.IsClosed); 
            Contract.Assert(m_algorithmHandle != null);
 
            // Try to create a new hash algorithm to use 
            SafeBCryptHashHandle newHashAlgorithm = null;
            IntPtr hashObjectBuffer = IntPtr.Zero; 

            // Creating a BCRYPT_HASH_HANDLE requires providing a buffer to hold the hash object in, which
            // is tied to the lifetime of the hash handle. Wrap this in a CER so we can tie the lifetimes together
            // safely. 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
 
                int hashObjectSize = BCryptNative.GetInt32Property(m_algorithmHandle,
                                                                   BCryptNative.ObjectPropertyName.ObjectLength); 
                Debug.Assert(hashObjectSize > 0, "hashObjectSize > 0");

                // Allocate in a CER because we could fail between the alloc and the assignment
                RuntimeHelpers.PrepareConstrainedRegions(); 
                try { }
                finally { 
                    hashObjectBuffer = Marshal.AllocCoTaskMem(hashObjectSize); 
                }
 
                BCryptNative.ErrorCode error = BCryptNative.UnsafeNativeMethods.BCryptCreateHash(m_algorithmHandle,
                                                                                                 out newHashAlgorithm,
                                                                                                 hashObjectBuffer,
                                                                                                 hashObjectSize, 
                                                                                                 IntPtr.Zero,
                                                                                                 0, 
                                                                                                 0); 

                if (error != BCryptNative.ErrorCode.Success) { 
                    throw new CryptographicException((int)error);
                }

                newHashAlgorithm.HashObject = hashObjectBuffer; 
            }
            finally { 
                // Make sure we've successfully transfered ownership of the hash object buffer to the safe handle 
                if (hashObjectBuffer != IntPtr.Zero && (newHashAlgorithm == null || newHashAlgorithm.HashObject == IntPtr.Zero)) {
                    Marshal.FreeCoTaskMem(hashObjectBuffer); 
                }
            }

            // If we could create it, dispose of any old hash handle we had and replace it with the new one 
            if (m_hashHandle != null) {
                m_hashHandle.Dispose(); 
            } 
            m_hashHandle = newHashAlgorithm;
        } 

        /// 
        ///     Hash a block of data
        ///  
        // 
        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        public void HashCore(byte[] array, int ibStart, int cbSize) {
            Contract.Assert(m_hashHandle != null);

            if (array == null) { 
                throw new ArgumentNullException("array");
            } 
            if (ibStart < 0 || ibStart > array.Length - cbSize) { 
                throw new ArgumentOutOfRangeException("ibStart");
            } 
            if (cbSize < 0 || cbSize > array.Length) {
                throw new ArgumentOutOfRangeException("cbSize");
            }
 
            byte[] hashData = new byte[cbSize];
            Buffer.BlockCopy(array, ibStart, hashData, 0, cbSize); 
 
            BCryptNative.ErrorCode error = BCryptNative.UnsafeNativeMethods.BCryptHashData(m_hashHandle,
                                                                                           hashData, 
                                                                                           hashData.Length,
                                                                                           0);

            if (error != BCryptNative.ErrorCode.Success) { 
                throw new CryptographicException((int)error);
            } 
        } 

        ///  
        ///     Complete the hash, returning its value
        /// 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public byte[] HashFinal() { 
            Contract.Ensures(Contract.Result() != null);
            Contract.Assert(m_hashHandle != null);

            int hashSize = BCryptNative.GetInt32Property(m_hashHandle, BCryptNative.HashPropertyName.HashLength); 

            byte[] hashValue = new byte[hashSize]; 
            BCryptNative.ErrorCode error = BCryptNative.UnsafeNativeMethods.BCryptFinishHash(m_hashHandle, 
                                                                                             hashValue,
                                                                                             hashValue.Length, 
                                                                                             0);

            if (error != BCryptNative.ErrorCode.Success) {
                throw new CryptographicException((int)error); 
            }
 
            return hashValue; 
        }
 
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public void HashStream(Stream stream) {
            Contract.Requires(stream != null); 
 
            // Read the data 4KB at a time, providing similar read characteristics to a standard HashAlgorithm
            byte[] buffer = new byte[4096]; 
            int bytesRead = 0;
            do {
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                if (bytesRead > 0) { 
                    HashCore(buffer, 0, bytesRead);
                } 
            } while (bytesRead > 0); 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 

using System; 
using System.Diagnostics; 
using System.Diagnostics.CodeAnalysis;
using System.IO; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics.Contracts;
using Microsoft.Win32.SafeHandles; 

namespace System.Security.Cryptography { 
    ///  
    ///     Implementation of a generic BCrypt hashing algorithm, concrete HashAlgorithm classes
    ///     implemented by BCrypt can contain an instance of this class and delegate the work to it. 
    /// 
    internal sealed class BCryptHashAlgorithm : IDisposable {
        private SafeBCryptAlgorithmHandle m_algorithmHandle;
        private SafeBCryptHashHandle m_hashHandle; 

        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        public BCryptHashAlgorithm(CngAlgorithm algorithm, string implementation) { 
            Contract.Requires(algorithm != null);
            Contract.Requires(!String.IsNullOrEmpty(implementation)); 
            Contract.Ensures(m_algorithmHandle != null && !m_algorithmHandle.IsInvalid && !m_algorithmHandle.IsClosed);
            Contract.Ensures(m_hashHandle != null && !m_hashHandle.IsInvalid && !m_hashHandle.IsClosed);

            // Make sure CNG is supported on this platform 
            if (!BCryptNative.BCryptSupported) {
                throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); 
            } 

            m_algorithmHandle = BCryptNative.OpenAlgorithm(algorithm.Algorithm, implementation); 

            Initialize();
        }
 
        /// 
        ///     Clean up the hash algorithm 
        ///  
        // 
        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        public void Dispose() { 
            Contract.Ensures(m_hashHandle == null || m_hashHandle.IsClosed); 
            Contract.Ensures(m_algorithmHandle == null || m_algorithmHandle.IsClosed);
 
            if (m_hashHandle != null) {
                m_hashHandle.Dispose();
            }
 
            if (m_algorithmHandle != null) {
                m_algorithmHandle.Dispose(); 
            } 
        }
 
        /// 
        ///     Reset the hash algorithm to begin hashing a new set of data
        /// 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        [System.Security.SecurityCritical]
        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Reviewed")]
        public void Initialize() {
            Contract.Ensures(m_hashHandle != null && !m_hashHandle.IsInvalid && !m_hashHandle.IsClosed); 
            Contract.Assert(m_algorithmHandle != null);
 
            // Try to create a new hash algorithm to use 
            SafeBCryptHashHandle newHashAlgorithm = null;
            IntPtr hashObjectBuffer = IntPtr.Zero; 

            // Creating a BCRYPT_HASH_HANDLE requires providing a buffer to hold the hash object in, which
            // is tied to the lifetime of the hash handle. Wrap this in a CER so we can tie the lifetimes together
            // safely. 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
 
                int hashObjectSize = BCryptNative.GetInt32Property(m_algorithmHandle,
                                                                   BCryptNative.ObjectPropertyName.ObjectLength); 
                Debug.Assert(hashObjectSize > 0, "hashObjectSize > 0");

                // Allocate in a CER because we could fail between the alloc and the assignment
                RuntimeHelpers.PrepareConstrainedRegions(); 
                try { }
                finally { 
                    hashObjectBuffer = Marshal.AllocCoTaskMem(hashObjectSize); 
                }
 
                BCryptNative.ErrorCode error = BCryptNative.UnsafeNativeMethods.BCryptCreateHash(m_algorithmHandle,
                                                                                                 out newHashAlgorithm,
                                                                                                 hashObjectBuffer,
                                                                                                 hashObjectSize, 
                                                                                                 IntPtr.Zero,
                                                                                                 0, 
                                                                                                 0); 

                if (error != BCryptNative.ErrorCode.Success) { 
                    throw new CryptographicException((int)error);
                }

                newHashAlgorithm.HashObject = hashObjectBuffer; 
            }
            finally { 
                // Make sure we've successfully transfered ownership of the hash object buffer to the safe handle 
                if (hashObjectBuffer != IntPtr.Zero && (newHashAlgorithm == null || newHashAlgorithm.HashObject == IntPtr.Zero)) {
                    Marshal.FreeCoTaskMem(hashObjectBuffer); 
                }
            }

            // If we could create it, dispose of any old hash handle we had and replace it with the new one 
            if (m_hashHandle != null) {
                m_hashHandle.Dispose(); 
            } 
            m_hashHandle = newHashAlgorithm;
        } 

        /// 
        ///     Hash a block of data
        ///  
        // 
        //  
        //  
        // 
        [System.Security.SecurityCritical] 
        public void HashCore(byte[] array, int ibStart, int cbSize) {
            Contract.Assert(m_hashHandle != null);

            if (array == null) { 
                throw new ArgumentNullException("array");
            } 
            if (ibStart < 0 || ibStart > array.Length - cbSize) { 
                throw new ArgumentOutOfRangeException("ibStart");
            } 
            if (cbSize < 0 || cbSize > array.Length) {
                throw new ArgumentOutOfRangeException("cbSize");
            }
 
            byte[] hashData = new byte[cbSize];
            Buffer.BlockCopy(array, ibStart, hashData, 0, cbSize); 
 
            BCryptNative.ErrorCode error = BCryptNative.UnsafeNativeMethods.BCryptHashData(m_hashHandle,
                                                                                           hashData, 
                                                                                           hashData.Length,
                                                                                           0);

            if (error != BCryptNative.ErrorCode.Success) { 
                throw new CryptographicException((int)error);
            } 
        } 

        ///  
        ///     Complete the hash, returning its value
        /// 
        // 
        //  
        // 
        //  
        //  
        [System.Security.SecurityCritical]
        public byte[] HashFinal() { 
            Contract.Ensures(Contract.Result() != null);
            Contract.Assert(m_hashHandle != null);

            int hashSize = BCryptNative.GetInt32Property(m_hashHandle, BCryptNative.HashPropertyName.HashLength); 

            byte[] hashValue = new byte[hashSize]; 
            BCryptNative.ErrorCode error = BCryptNative.UnsafeNativeMethods.BCryptFinishHash(m_hashHandle, 
                                                                                             hashValue,
                                                                                             hashValue.Length, 
                                                                                             0);

            if (error != BCryptNative.ErrorCode.Success) {
                throw new CryptographicException((int)error); 
            }
 
            return hashValue; 
        }
 
        // 
        // 
        // 
        [System.Security.SecurityCritical] 
        public void HashStream(Stream stream) {
            Contract.Requires(stream != null); 
 
            // Read the data 4KB at a time, providing similar read characteristics to a standard HashAlgorithm
            byte[] buffer = new byte[4096]; 
            int bytesRead = 0;
            do {
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                if (bytesRead > 0) { 
                    HashCore(buffer, 0, bytesRead);
                } 
            } while (bytesRead > 0); 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK