예제 #1
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);
        }
예제 #2
0
        public static byte[] HashBytes(byte[] bytes, HashIdentifier hashAlgorithm)
        {
            HashAlgorithm hash;

            if (hashAlgorithm == HashIdentifier.SHA512)
            {
                hash = SHA512.Create();
            }
            else if (hashAlgorithm == HashIdentifier.SHA384)
            {
                hash = SHA384.Create();
            }
            else if (hashAlgorithm == HashIdentifier.SHA256)
            {
                hash = SHA256.Create();
            }
            else if (hashAlgorithm == HashIdentifier.SHA1)
            {
                hash = SHA1.Create();
            }
            else if (hashAlgorithm == HashIdentifier.MD5)
            {
                hash = MD5.Create();
            }
            else
            {
                throw new InvalidOperationException("Unsupported hash algorithm");
            }

            using (hash)
            {
                return(hash.ComputeHash(bytes));
            }
        }
예제 #3
0
 public static byte[] HashBytes(byte[] bytes, HashIdentifier hashAlgorithm)
 {
     using (HashAlgorithm hash = Create(hashAlgorithm))
     {
         return(hash.ComputeHash(bytes));
     }
 }
        private static byte[] DeriveKey(byte[] hashValue, HashIdentifier hashAlgorithm, int keySize, int verifierHashSize)
        {
            // And one more hash to derive the key
            byte[] derivedKey = new byte[64];

            // This is step 4a in 2.3.4.7 of MS_OFFCRYPT version 1.0
            // and is required even though the notes say it should be
            // used only when the encryption algorithm key > hash length.
            for (int i = 0; i < derivedKey.Length; i++)
            {
                derivedKey[i] = (byte)(i < hashValue.Length ? 0x36 ^ hashValue[i] : 0x36);
            }

            byte[] x1 = CryptoHelpers.HashBytes(derivedKey, hashAlgorithm);

            if (verifierHashSize > keySize / 8)
            {
                return(x1);
            }

            for (int i = 0; i < derivedKey.Length; i++)
            {
                derivedKey[i] = (byte)(i < hashValue.Length ? 0x5C ^ hashValue[i] : 0x5C);
            }

            byte[] x2 = CryptoHelpers.HashBytes(derivedKey, hashAlgorithm);
            return(CryptoHelpers.Combine(x1, x2));
        }
예제 #5
0
        private static byte[] HashPassword(string password, byte[] saltValue, HashIdentifier hashAlgorithm, int spinCount)
        {
            var h = CryptoHelpers.HashBytes(CryptoHelpers.Combine(saltValue, System.Text.Encoding.Unicode.GetBytes(password)), hashAlgorithm);

            for (var i = 0; i < spinCount; i++)
            {
                h = CryptoHelpers.HashBytes(CryptoHelpers.Combine(BitConverter.GetBytes(i), h), hashAlgorithm);
            }

            return(h);
        }
예제 #6
0
        public static HashAlgorithm Create(HashIdentifier hashAlgorithm)
        {
            switch (hashAlgorithm)
            {
            case HashIdentifier.SHA512:
                return(SHA512.Create());

            case HashIdentifier.SHA384:
                return(SHA384.Create());

            case HashIdentifier.SHA256:
                return(SHA256.Create());

            case HashIdentifier.SHA1:
                return(SHA1.Create());

            case HashIdentifier.MD5:
                return(MD5.Create());

            default:
                throw new InvalidOperationException("Unsupported hash algorithm");
            }
        }
예제 #7
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);
        }
예제 #8
0
 /// <summary>
 /// 2.3.5.2 RC4 CryptoAPI Encryption Key Generation
 /// </summary>
 private static byte[] GenerateCryptoApiSecretKey(string password, byte[] saltValue, HashIdentifier hashAlgorithm, int keySize)
 {
     return(CryptoHelpers.HashBytes(CryptoHelpers.Combine(saltValue, System.Text.Encoding.Unicode.GetBytes(password)), hashAlgorithm));
 }
예제 #9
0
        public void TestHashDetection(string hash, bool accepted)
        {
            var hashed = HashIdentifier.GetHashAlgorithm(hash);

            accepted.Should().Be(hashed != null);
        }
예제 #10
0
        private BlobIdentifier CreateBlobIdentifier()
        {
            const string HashIdentifier = "54CE418A2A89A74B42CC39630167795DED5F3B16A75FF32A01B2B01C59697784";

            return(BlobIdentifier.CreateFromAlgorithmResult(HashIdentifier.ToUpperInvariant()));
        }