Beispiel #1
0
        public override bool VerifyPassword(string password)
        {
            byte[] secretKey;
            using (var hashAlgorithm = CryptoHelpers.Create(PasswordHashAlgorithm))
                secretKey = HashPassword(password, PasswordSaltValue, hashAlgorithm, PasswordSpinCount);

            var inputBlockKey = CryptoHelpers.HashBytes(
                CryptoHelpers.Combine(secretKey, new byte[] { 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79 }),
                PasswordHashAlgorithm);

            Array.Resize(ref inputBlockKey, PasswordKeyBits / 8);

            var valueBlockKey = CryptoHelpers.HashBytes(
                CryptoHelpers.Combine(secretKey, new byte[] { 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e }),
                PasswordHashAlgorithm);

            Array.Resize(ref valueBlockKey, PasswordKeyBits / 8);

            using (var cipher = CryptoHelpers.CreateCipher(PasswordCipherAlgorithm, PasswordKeyBits, PasswordBlockSize * 8, PasswordCipherChaining))
            {
                var decryptedVerifier     = CryptoHelpers.DecryptBytes(cipher, PasswordEncryptedVerifierHashInput, inputBlockKey, PasswordSaltValue);
                var decryptedVerifierHash = CryptoHelpers.DecryptBytes(cipher, PasswordEncryptedVerifierHashValue, valueBlockKey, PasswordSaltValue);

                var verifierHash = CryptoHelpers.HashBytes(decryptedVerifier, PasswordHashAlgorithm);
                for (var i = 0; i < Math.Min(decryptedVerifierHash.Length, verifierHash.Length); ++i)
                {
                    if (decryptedVerifierHash[i] != verifierHash[i])
                    {
                        return(false);
                    }
                }

                return(true);
            }
        }
Beispiel #2
0
        private static byte[] GenerateSecretKey(string password, byte[] saltValue, HashIdentifier hashIdentifier, byte[] encryptedKeyValue, int spinCount, int keyBits, SymmetricAlgorithm cipher)
        {
            var block3 = new byte[] { 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6 };

            byte[] hash;
            using (var hashAlgorithm = CryptoHelpers.Create(hashIdentifier))
            {
                hash = HashPassword(password, saltValue, hashAlgorithm, spinCount);

                hash = CryptoHelpers.HashBytes(CryptoHelpers.Combine(hash, block3), hashIdentifier);
            }

            // Truncate or pad with 0x36
            var hashSize = hash.Length;

            Array.Resize(ref hash, keyBits / 8);
            for (var i = hashSize; i < keyBits / 8; i++)
            {
                hash[i] = 0x36;
            }

            // NOTE: the stored salt is padded to a multiple of the block size which affects AES-192
            var decryptedKeyValue = CryptoHelpers.DecryptBytes(cipher, encryptedKeyValue, hash, saltValue);

            Array.Resize(ref decryptedKeyValue, keyBits / 8);
            return(decryptedKeyValue);
        }
Beispiel #3
0
        /// <summary>
        /// 2.3.4.7 ECMA-376 Document Encryption Key Generation (Standard Encryption)
        /// </summary>
        private static byte[] GenerateEcma376SecretKey(string password, byte[] saltValue, HashIdentifier hashIdentifier, int keySize, int verifierHashSize)
        {
            byte[] hash;
            using (var hashAlgorithm = CryptoHelpers.Create(hashIdentifier))
            {
                hash = hashAlgorithm.ComputeHash(CryptoHelpers.Combine(saltValue, System.Text.Encoding.Unicode.GetBytes(password)));
                for (int i = 0; i < 50000; i++)
                {
                    hash = hashAlgorithm.ComputeHash(CryptoHelpers.Combine(BitConverter.GetBytes(i), hash));
                }

                hash = hashAlgorithm.ComputeHash(CryptoHelpers.Combine(hash, BitConverter.GetBytes(0)));

                // The algorithm in this 'DeriveKey' function is the bit that's not clear from the documentation
                hash = DeriveKey(hash, hashAlgorithm, keySize, verifierHashSize);
            }

            Array.Resize(ref hash, keySize / 8);

            return(hash);
        }