private static BCryptKeyHandle PasswordToPbkdfKeyHandleStep2(BCryptAlgorithmHandle pbkdf2AlgHandle, byte *pbPassword, uint cbPassword, KeyDerivationPrf prf) { const uint PBKDF2_MAX_KEYLENGTH_IN_BYTES = 2048; // GetSupportedKeyLengths() on a Win8 box; value should never be lowered in any future version of Windows if (cbPassword <= PBKDF2_MAX_KEYLENGTH_IN_BYTES) { // Common case: the password is small enough to be consumed directly by the PBKDF2 algorithm. return(pbkdf2AlgHandle.GenerateSymmetricKey(pbPassword, cbPassword)); } else { // Rare case: password is very long; we must hash manually. // PBKDF2 uses the PRFs in HMAC mode, and when the HMAC input key exceeds the hash function's // block length the key is hashed and run back through the key initialization function. BCryptAlgorithmHandle prfAlgorithmHandle; // cached; don't dispose switch (prf) { case KeyDerivationPrf.Sha1: prfAlgorithmHandle = CachedAlgorithmHandles.SHA1; break; case KeyDerivationPrf.Sha256: prfAlgorithmHandle = CachedAlgorithmHandles.SHA256; break; case KeyDerivationPrf.Sha512: prfAlgorithmHandle = CachedAlgorithmHandles.SHA512; break; default: throw CryptoUtil.Fail("Unrecognized PRF."); } // Final sanity check: don't hash the password if the HMAC key initialization function wouldn't have done it for us. if (cbPassword <= prfAlgorithmHandle.GetHashBlockLength() /* in bytes */) { return(pbkdf2AlgHandle.GenerateSymmetricKey(pbPassword, cbPassword)); } // Hash the password and use the hash as input to PBKDF2. uint cbPasswordDigest = prfAlgorithmHandle.GetHashDigestLength(); CryptoUtil.Assert(cbPasswordDigest > 0, "cbPasswordDigest > 0"); fixed(byte *pbPasswordDigest = new byte[cbPasswordDigest]) { try { using (var hashHandle = prfAlgorithmHandle.CreateHash()) { hashHandle.HashData(pbPassword, cbPassword, pbPasswordDigest, cbPasswordDigest); } return(pbkdf2AlgHandle.GenerateSymmetricKey(pbPasswordDigest, cbPasswordDigest)); } finally { UnsafeBufferUtil.SecureZeroMemory(pbPasswordDigest, cbPasswordDigest); } } } }
public CbcAuthenticatedEncryptor(ProtectedMemoryBlob keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, BCryptAlgorithmHandle hmacAlgorithmHandle, IBCryptGenRandom genRandom = null) { CryptoUtil.Assert(KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES, "KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES"); _genRandom = genRandom ?? BCryptGenRandomImpl.Instance; _sp800_108_ctr_hmac_provider = SP800_108_CTR_HMACSHA512Util.CreateProvider(keyDerivationKey); _symmetricAlgorithmHandle = symmetricAlgorithmHandle; _symmetricAlgorithmBlockSizeInBytes = symmetricAlgorithmHandle.GetCipherBlockLength(); _symmetricAlgorithmSubkeyLengthInBytes = symmetricAlgorithmKeySizeInBytes; _hmacAlgorithmHandle = hmacAlgorithmHandle; _hmacAlgorithmDigestLengthInBytes = hmacAlgorithmHandle.GetHashDigestLength(); _hmacAlgorithmSubkeyLengthInBytes = _hmacAlgorithmDigestLengthInBytes; // for simplicity we'll generate HMAC subkeys with a length equal to the digest length CryptoUtil.Assert(SYMMETRIC_ALG_MIN_BLOCK_SIZE_IN_BYTES <= _symmetricAlgorithmBlockSizeInBytes && _symmetricAlgorithmBlockSizeInBytes <= Constants.MAX_STACKALLOC_BYTES, "SYMMETRIC_ALG_MIN_BLOCK_SIZE_IN_BYTES <= _symmetricAlgorithmBlockSizeInBytes && _symmetricAlgorithmBlockSizeInBytes <= Constants.MAX_STACKALLOC_BYTES"); CryptoUtil.Assert(HASH_ALG_MIN_DIGEST_LENGTH_IN_BYTES <= _hmacAlgorithmDigestLengthInBytes, "HASH_ALG_MIN_DIGEST_LENGTH_IN_BYTES <= _hmacAlgorithmDigestLengthInBytes"); CryptoUtil.Assert(KEY_MODIFIER_SIZE_IN_BYTES <= _hmacAlgorithmSubkeyLengthInBytes && _hmacAlgorithmSubkeyLengthInBytes <= Constants.MAX_STACKALLOC_BYTES, "KEY_MODIFIER_SIZE_IN_BYTES <= _hmacAlgorithmSubkeyLengthInBytes && _hmacAlgorithmSubkeyLengthInBytes <= Constants.MAX_STACKALLOC_BYTES"); _contextHeader = CreateContextHeader(); }
private static BCryptAlgorithmHandle GetAesAlgorithm(string chainingMode) { var algHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(Constants.BCRYPT_AES_ALGORITHM); algHandle.SetChainingMode(chainingMode); return(algHandle); }
private static BCryptAlgorithmHandle GetEncryptionAlgorithmHandleAndCheckKeySize(string encryptionAlgorithm, string encryptionAlgorithmProvider, uint keyLengthInBits) { BCryptAlgorithmHandle algorithmHandle = null; // Special-case cached providers if (encryptionAlgorithmProvider == null) { if (encryptionAlgorithm == Constants.BCRYPT_AES_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.AES_GCM; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(encryptionAlgorithm, encryptionAlgorithmProvider); algorithmHandle.SetChainingMode(Constants.BCRYPT_CHAIN_MODE_GCM); } // make sure we're using a block cipher with an appropriate block size uint cipherBlockSizeInBytes = algorithmHandle.GetCipherBlockLength(); CryptoUtil.Assert(cipherBlockSizeInBytes == 128 / 8, "cipherBlockSizeInBytes == 128 / 8"); // make sure the provided key length is valid algorithmHandle.GetSupportedKeyLengths().EnsureValidKeyLength(keyLengthInBits); // all good! return(algorithmHandle); }
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa375453(v=vs.85).aspx internal static extern int BCryptGenerateSymmetricKey( [In] BCryptAlgorithmHandle hAlgorithm, [Out] out BCryptKeyHandle phKey, [In] IntPtr pbKeyObject, [In] uint cbKeyObject, [In] byte *pbSecret, [In] uint cbSecret, [In] uint dwFlags);
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa375383(v=vs.85).aspx internal static extern int BCryptCreateHash( [In] BCryptAlgorithmHandle hAlgorithm, [Out] out BCryptHashHandle phHash, [In] IntPtr pbHashObject, [In] uint cbHashObject, [In] byte *pbSecret, [In] uint cbSecret, [In] uint dwFlags);
internal static extern int BCryptGenerateSymmetricKey( #endif BCryptAlgorithmHandle hAlgorithm, out BCryptKeyHandle phKey, IntPtr pbKeyObject, uint cbKeyObject, byte *pbSecret, uint cbSecret, uint dwFlags);
internal static extern int BCryptCreateHash( #endif BCryptAlgorithmHandle hAlgorithm, out BCryptHashHandle phHash, IntPtr pbHashObject, uint cbHashObject, byte *pbSecret, uint cbSecret, uint dwFlags);
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd433795(v=vs.85).aspx internal static extern int BCryptDeriveKeyPBKDF2( [In] BCryptAlgorithmHandle hPrf, [In] byte *pbPassword, [In] uint cbPassword, [In] byte *pbSalt, [In] uint cbSalt, [In] ulong cIterations, [In] byte *pbDerivedKey, [In] uint cbDerivedKey, [In] uint dwFlags);
internal static extern int BCryptDeriveKeyPBKDF2( #endif BCryptAlgorithmHandle hPrf, byte *pbPassword, uint cbPassword, byte *pbSalt, uint cbSalt, ulong cIterations, byte *pbDerivedKey, uint cbDerivedKey, uint dwFlags);
public GcmAuthenticatedEncryptor(ProtectedMemoryBlob keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, IBCryptGenRandom genRandom = null) { CryptoUtil.Assert(KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES, "KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES"); _genRandom = genRandom ?? BCryptGenRandomImpl.Instance; _sp800_108_ctr_hmac_provider = SP800_108_CTR_HMACSHA512Util.CreateProvider(keyDerivationKey); _symmetricAlgorithmHandle = symmetricAlgorithmHandle; _symmetricAlgorithmSubkeyLengthInBytes = symmetricAlgorithmKeySizeInBytes; _contextHeader = CreateContextHeader(); }
public CngGcmAuthenticatedEncryptor(Secret keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, IBCryptGenRandom?genRandom = null) { // Is the key size appropriate? AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked (symmetricAlgorithmKeySizeInBytes * 8)); CryptoUtil.Assert(symmetricAlgorithmHandle.GetCipherBlockLength() == 128 / 8, "GCM requires a block cipher algorithm with a 128-bit block size."); _genRandom = genRandom ?? BCryptGenRandomImpl.Instance; _sp800_108_ctr_hmac_provider = SP800_108_CTR_HMACSHA512Util.CreateProvider(keyDerivationKey); _symmetricAlgorithmHandle = symmetricAlgorithmHandle; _symmetricAlgorithmSubkeyLengthInBytes = symmetricAlgorithmKeySizeInBytes; _contextHeader = CreateContextHeader(); }
internal IAuthenticatedEncryptor CreateAuthenticatedEncryptor([NotNull] ISecret secret) { // Create the encryption object string encryptionAlgorithm = GetPropertyValueNotNullOrEmpty(EncryptionAlgorithm, nameof(EncryptionAlgorithm)); string encryptionAlgorithmProvider = GetPropertyValueNormalizeToNull(EncryptionAlgorithmProvider); uint encryptionAlgorithmKeySizeInBits = GetKeySizeInBits(EncryptionAlgorithmKeySize); BCryptAlgorithmHandle encryptionAlgorithmHandle = GetEncryptionAlgorithmHandleAndCheckKeySize(encryptionAlgorithm, encryptionAlgorithmProvider, encryptionAlgorithmKeySizeInBits); // and we're good to go! return(new GcmAuthenticatedEncryptor( keyDerivationKey: new ProtectedMemoryBlob(secret), symmetricAlgorithmHandle: encryptionAlgorithmHandle, symmetricAlgorithmKeySizeInBytes: encryptionAlgorithmKeySizeInBits / 8)); }
private BCryptAlgorithmHandle GetHmacAlgorithmHandle(ILogger logger) { // basic argument checking if (String.IsNullOrEmpty(HashAlgorithm)) { throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(HashAlgorithm)); } if (logger.IsVerboseLevelEnabled()) { logger.LogVerboseF($"Opening CNG algorithm '{HashAlgorithm}' from provider '{HashAlgorithmProvider}' with HMAC."); } BCryptAlgorithmHandle algorithmHandle = null; // Special-case cached providers if (HashAlgorithmProvider == null) { if (HashAlgorithm == Constants.BCRYPT_SHA1_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA1; } else if (HashAlgorithm == Constants.BCRYPT_SHA256_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA256; } else if (HashAlgorithm == Constants.BCRYPT_SHA512_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA512; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(HashAlgorithm, HashAlgorithmProvider, hmac: true); } // Make sure we're using a hash algorithm. We require a minimum 128-bit digest. uint digestSize = algorithmHandle.GetHashDigestLength(); AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked (digestSize * 8)); // all good! return(algorithmHandle); }
private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(ILogger logger) { // basic argument checking if (String.IsNullOrEmpty(EncryptionAlgorithm)) { throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(EncryptionAlgorithm)); } if (EncryptionAlgorithmKeySize < 0) { throw Error.Common_PropertyMustBeNonNegative(nameof(EncryptionAlgorithmKeySize)); } BCryptAlgorithmHandle algorithmHandle = null; if (logger.IsVerboseLevelEnabled()) { logger.LogVerboseF($"Opening CNG algorithm '{EncryptionAlgorithm}' from provider '{EncryptionAlgorithmProvider}' with chaining mode GCM."); } // Special-case cached providers if (EncryptionAlgorithmProvider == null) { if (EncryptionAlgorithm == Constants.BCRYPT_AES_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.AES_GCM; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(EncryptionAlgorithm, EncryptionAlgorithmProvider); algorithmHandle.SetChainingMode(Constants.BCRYPT_CHAIN_MODE_GCM); } // make sure we're using a block cipher with an appropriate key size & block size CryptoUtil.Assert(algorithmHandle.GetCipherBlockLength() == 128 / 8, "GCM requires a block cipher algorithm with a 128-bit block size."); AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked ((uint)EncryptionAlgorithmKeySize)); // make sure the provided key length is valid algorithmHandle.GetSupportedKeyLengths().EnsureValidKeyLength((uint)EncryptionAlgorithmKeySize); // all good! return(algorithmHandle); }
public CbcAuthenticatedEncryptor(Secret keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, BCryptAlgorithmHandle hmacAlgorithmHandle, IBCryptGenRandom?genRandom = null) { _genRandom = genRandom ?? BCryptGenRandomImpl.Instance; _sp800_108_ctr_hmac_provider = SP800_108_CTR_HMACSHA512Util.CreateProvider(keyDerivationKey); _symmetricAlgorithmHandle = symmetricAlgorithmHandle; _symmetricAlgorithmBlockSizeInBytes = symmetricAlgorithmHandle.GetCipherBlockLength(); _symmetricAlgorithmSubkeyLengthInBytes = symmetricAlgorithmKeySizeInBytes; _hmacAlgorithmHandle = hmacAlgorithmHandle; _hmacAlgorithmDigestLengthInBytes = hmacAlgorithmHandle.GetHashDigestLength(); _hmacAlgorithmSubkeyLengthInBytes = _hmacAlgorithmDigestLengthInBytes; // for simplicity we'll generate HMAC subkeys with a length equal to the digest length // Argument checking on the algorithms and lengths passed in to us AlgorithmAssert.IsAllowableSymmetricAlgorithmBlockSize(checked (_symmetricAlgorithmBlockSizeInBytes * 8)); AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked (_symmetricAlgorithmSubkeyLengthInBytes * 8)); AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked (_hmacAlgorithmDigestLengthInBytes * 8)); _contextHeader = CreateContextHeader(); }
private BCryptAlgorithmHandle GetHmacAlgorithmHandle(CngCbcAuthenticatedEncryptorConfiguration configuration) { // basic argument checking if (String.IsNullOrEmpty(configuration.HashAlgorithm)) { throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(configuration.HashAlgorithm)); } _logger.OpeningCNGAlgorithmFromProviderWithHMAC(configuration.HashAlgorithm, configuration.HashAlgorithmProvider); BCryptAlgorithmHandle?algorithmHandle = null; // Special-case cached providers if (configuration.HashAlgorithmProvider == null) { if (configuration.HashAlgorithm == Constants.BCRYPT_SHA1_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA1; } else if (configuration.HashAlgorithm == Constants.BCRYPT_SHA256_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA256; } else if (configuration.HashAlgorithm == Constants.BCRYPT_SHA512_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA512; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.HashAlgorithm, configuration.HashAlgorithmProvider, hmac: true); } // Make sure we're using a hash algorithm. We require a minimum 128-bit digest. uint digestSize = algorithmHandle.GetHashDigestLength(); AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked (digestSize * 8)); // all good! return(algorithmHandle); }
private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(CngCbcAuthenticatedEncryptorConfiguration configuration) { // basic argument checking if (String.IsNullOrEmpty(configuration.EncryptionAlgorithm)) { throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(EncryptionAlgorithm)); } if (configuration.EncryptionAlgorithmKeySize < 0) { throw Error.Common_PropertyMustBeNonNegative(nameof(configuration.EncryptionAlgorithmKeySize)); } _logger.OpeningCNGAlgorithmFromProviderWithChainingModeCBC(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); BCryptAlgorithmHandle?algorithmHandle = null; // Special-case cached providers if (configuration.EncryptionAlgorithmProvider == null) { if (configuration.EncryptionAlgorithm == Constants.BCRYPT_AES_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.AES_CBC; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); algorithmHandle.SetChainingMode(Constants.BCRYPT_CHAIN_MODE_CBC); } // make sure we're using a block cipher with an appropriate key size & block size AlgorithmAssert.IsAllowableSymmetricAlgorithmBlockSize(checked (algorithmHandle.GetCipherBlockLength() * 8)); AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked ((uint)configuration.EncryptionAlgorithmKeySize)); // make sure the provided key length is valid algorithmHandle.GetSupportedKeyLengths().EnsureValidKeyLength((uint)configuration.EncryptionAlgorithmKeySize); // all good! return(algorithmHandle); }
private static BCryptKeyHandle PasswordToPbkdfKeyHandle(string password, BCryptAlgorithmHandle pbkdf2AlgHandle, KeyDerivationPrf prf) { byte dummy; // CLR doesn't like pinning zero-length buffers, so this provides a valid memory address when working with zero-length buffers // Convert password string to bytes. // Allocate on the stack whenever we can to save allocations. int cbPasswordBuffer = Encoding.UTF8.GetMaxByteCount(password.Length); fixed(byte *pbHeapAllocatedPasswordBuffer = (cbPasswordBuffer > Constants.MAX_STACKALLOC_BYTES)?new byte[cbPasswordBuffer] : null) { byte *pbPasswordBuffer = pbHeapAllocatedPasswordBuffer; if (pbPasswordBuffer == null) { if (cbPasswordBuffer == 0) { pbPasswordBuffer = &dummy; } else { byte *pbStackAllocPasswordBuffer = stackalloc byte[cbPasswordBuffer]; // will be released when the frame unwinds pbPasswordBuffer = pbStackAllocPasswordBuffer; } } try { int cbPasswordBufferUsed; // we're not filling the entire buffer, just a partial buffer fixed(char *pszPassword = password) { cbPasswordBufferUsed = Encoding.UTF8.GetBytes(pszPassword, password.Length, pbPasswordBuffer, cbPasswordBuffer); } return(PasswordToPbkdfKeyHandleStep2(pbkdf2AlgHandle, pbPasswordBuffer, (uint)cbPasswordBufferUsed, prf)); } finally { UnsafeBufferUtil.SecureZeroMemory(pbPasswordBuffer, cbPasswordBuffer); } } }
public void CreateAuthenticatedEncryptor_RoundTripsData_CngCbcImplementation(EncryptionAlgorithm encryptionAlgorithm, ValidationAlgorithm validationAlgorithm) { // Parse test input int keyLengthInBits = Int32.Parse(Regex.Match(encryptionAlgorithm.ToString(), @"^AES_(?<keyLength>\d{3})_CBC$").Groups["keyLength"].Value, CultureInfo.InvariantCulture); string hashAlgorithm = Regex.Match(validationAlgorithm.ToString(), @"^HMAC(?<hashAlgorithm>.*)$").Groups["hashAlgorithm"].Value; // Arrange var masterKey = Secret.Random(512 / 8); var control = new CbcAuthenticatedEncryptor( keyDerivationKey: masterKey, symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, symmetricAlgorithmKeySizeInBytes: (uint)(keyLengthInBits / 8), hmacAlgorithmHandle: BCryptAlgorithmHandle.OpenAlgorithmHandle(hashAlgorithm, hmac: true)); var test = CreateEncryptorInstanceFromDescriptor(CreateDescriptor(encryptionAlgorithm, validationAlgorithm, masterKey)); // Act & assert - data round trips properly from control to test byte[] plaintext = new byte[] { 1, 2, 3, 4, 5 }; byte[] aad = new byte[] { 2, 4, 6, 8, 0 }; byte[] ciphertext = control.Encrypt(new ArraySegment <byte>(plaintext), new ArraySegment <byte>(aad)); byte[] roundTripPlaintext = test.Decrypt(new ArraySegment <byte>(ciphertext), new ArraySegment <byte>(aad)); Assert.Equal(plaintext, roundTripPlaintext); }
private static BCryptAlgorithmHandle GetHashAlgorithmHandle(string hashAlgorithm, string hashAlgorithmProvider) { BCryptAlgorithmHandle algorithmHandle = null; // Special-case cached providers if (hashAlgorithmProvider == null) { if (hashAlgorithm == Constants.BCRYPT_SHA1_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA1; } else if (hashAlgorithm == Constants.BCRYPT_SHA256_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA256; } else if (hashAlgorithm == Constants.BCRYPT_SHA512_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA512; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(hashAlgorithm, hashAlgorithmProvider, hmac: true); } // Make sure we're using a hash algorithm. We require a minimum 128-bit digest. uint digestSize = algorithmHandle.GetHashDigestLength(); CryptoUtil.Assert(digestSize >= CbcAuthenticatedEncryptor.HASH_ALG_MIN_DIGEST_LENGTH_IN_BYTES, "digestSize >= CbcAuthenticatedEncryptor.HASH_ALG_MIN_DIGEST_LENGTH_IN_BYTES"); // all good! return(algorithmHandle); }
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa375479(v=vs.85).aspx internal static extern int BCryptOpenAlgorithmProvider( [Out] out BCryptAlgorithmHandle phAlgorithm, [In, MarshalAs(UnmanagedType.LPWStr)] string pszAlgId, [In, MarshalAs(UnmanagedType.LPWStr)] string?pszImplementation, [In] uint dwFlags);
// We don't actually need to hold a reference to the algorithm handle, as the native CNG library // already holds the reference for us. But once we create a key from an algorithm provider, odds // are good that we'll create another key from the same algorithm provider at some point in the // future. And since algorithm providers are expensive to create, we'll hold a strong reference // to all known in-use providers. This way the cached algorithm provider handles utility class // doesn't keep creating providers over and over. internal void SetAlgorithmProviderHandle(BCryptAlgorithmHandle algProviderHandle) { _algProviderHandle = algProviderHandle; }
private static BCryptAlgorithmHandle GetHashAlgorithm(string algorithm) { return(BCryptAlgorithmHandle.OpenAlgorithmHandle(algorithm, hmac: false)); }
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375458(v=vs.85).aspx internal static extern ErrorCode BCryptGenRandom( BCryptAlgorithmHandle hAlgorithm, [In, Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbBuffer, int cbBuffer, int dwFlags);
private static BCryptAlgorithmHandle GetHmacAlgorithm(string algorithm) { return(BCryptAlgorithmHandle.OpenAlgorithmHandle(algorithm, hmac: true)); }
private static BCryptAlgorithmHandle GetPbkdf2Algorithm() { return(BCryptAlgorithmHandle.OpenAlgorithmHandle(Constants.BCRYPT_PBKDF2_ALGORITHM, implementation: Constants.MS_PRIMITIVE_PROVIDER)); }
private static BCryptAlgorithmHandle GetSP800_108_CTR_HMACAlgorithm() { return(BCryptAlgorithmHandle.OpenAlgorithmHandle(Constants.BCRYPT_SP800108_CTR_HMAC_ALGORITHM, implementation: Constants.MS_PRIMITIVE_PROVIDER)); }