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);
                    }
                }
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #4
0
        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();
        }
Beispiel #12
0
    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();
    }
Beispiel #13
0
        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);
        }
Beispiel #15
0
        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);
        }
Beispiel #16
0
        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);
                }
            }
        }
Beispiel #20
0
        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);
Beispiel #23
0
 // 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));
 }