private byte[] DeriveTempKey(KerberosAuthenticationKey key, KerberosKeyUsage key_usage, byte key_type)
 {
     byte[] r = BitConverter.GetBytes((int)key_usage).Reverse().ToArray();
     Array.Resize(ref r, 5);
     r[4] = key_type;
     return(NFold.Compute(r, 16));
 }
Example #2
0
        internal bool Decrypt(KerberosKeySet keyset, KerberosKeyUsage key_usage, out KerberosTicket ticket)
        {
            if (this is KerberosTicketDecrypted)
            {
                ticket = this;
                return(true);
            }

            ticket = null;
            if (!EncryptedData.Decrypt(keyset, Realm, ServerName, key_usage, out byte[] decrypted))
        private bool DecryptAESWithKey(KerberosAuthenticationKey key, KerberosKeyUsage key_usage, out byte[] decrypted)
        {
            byte[] derive_enc_key = DeriveTempKey(key, key_usage, EncryptionKey);
            byte[] derive_mac_key = DeriveTempKey(key, key_usage, VerificationKey);

            byte[] new_key = KerberosAuthenticationKey.DeriveAesKey(key.Key, derive_enc_key);

            int cipher_text_length = CipherText.Length - AES_CHECKSUM_SIZE;
            int remaining          = AES_BLOCK_SIZE - (cipher_text_length % AES_BLOCK_SIZE);

            decrypted = new byte[AlignBlock(cipher_text_length)];
            Array.Copy(CipherText, decrypted, cipher_text_length);

            if (remaining > 0)
            {
                byte[] decrypted_block = DecryptAESBlock(new_key, decrypted, decrypted.Length - (AES_BLOCK_SIZE * 2));
                Array.Copy(decrypted_block, AES_BLOCK_SIZE - remaining, decrypted, decrypted.Length - remaining, remaining);
            }

            SwapEndBlocks(decrypted);

            AesManaged aes = new AesManaged();

            aes.Mode    = CipherMode.CBC;
            aes.Padding = PaddingMode.None;
            aes.Key     = new_key;
            aes.IV      = new byte[16];
            var dec = aes.CreateDecryptor();

            dec.TransformBlock(decrypted, 0, decrypted.Length, decrypted, 0);

            // Obviously not a secure check. This is for information only.
            HMACSHA1 hmac = new HMACSHA1(KerberosAuthenticationKey.DeriveAesKey(key.Key, derive_mac_key));

            byte[] hash = hmac.ComputeHash(decrypted, 0, cipher_text_length);
            for (int i = 0; i < AES_CHECKSUM_SIZE; ++i)
            {
                if (hash[i] != CipherText[cipher_text_length + i])
                {
                    return(false);
                }
            }
            Array.Copy(decrypted, AES_CONFOUNDER_SIZE, decrypted, 0, cipher_text_length - AES_CONFOUNDER_SIZE);
            Array.Resize(ref decrypted, cipher_text_length - AES_CONFOUNDER_SIZE);
            return(true);
        }
        private bool DecryptRC4WithKey(KerberosAuthenticationKey key, KerberosKeyUsage key_usage, out byte[] decrypted)
        {
            HMACMD5 hmac = new HMACMD5(key.Key);

            byte[] key1 = hmac.ComputeHash(BitConverter.GetBytes((int)key_usage));
            hmac = new HMACMD5(key1);

            byte[] checksum = new byte[16];
            Buffer.BlockCopy(CipherText, 0, checksum, 0, checksum.Length);
            byte[] key2 = hmac.ComputeHash(checksum);

            byte[] result = ARC4.Transform(CipherText, 16, CipherText.Length - 16, key2);
            hmac = new HMACMD5(key1);
            byte[] calculated_checksum = hmac.ComputeHash(result);

            decrypted = new byte[result.Length - 8];
            Buffer.BlockCopy(result, 8, decrypted, 0, decrypted.Length);
            return(NtObjectUtils.EqualByteArray(checksum, calculated_checksum));
        }
 internal bool Decrypt(KerberosKeySet keyset, string realm, KerberosPrincipalName server_name, KerberosKeyUsage key_usage, out byte[] decrypted)
 {
     if (EncryptionType == KerberosEncryptionType.ARCFOUR_HMAC_MD5)
     {
         return(DecryptRC4(keyset, realm, server_name, key_usage, out decrypted));
     }
     else if (EncryptionType == KerberosEncryptionType.AES128_CTS_HMAC_SHA1_96 ||
              EncryptionType == KerberosEncryptionType.AES256_CTS_HMAC_SHA1_96)
     {
         return(DecryptAES(keyset, realm, server_name, key_usage, out decrypted));
     }
     decrypted = null;
     return(false);
 }
        private bool DecryptAES(KerberosKeySet keyset, string realm, KerberosPrincipalName server_name, KerberosKeyUsage key_usage, out byte[] decrypted)
        {
            KerberosAuthenticationKey key = keyset.FindKey(EncryptionType, server_name.NameType, server_name.GetPrincipal(realm), KeyVersion ?? 0);

            if (key != null)
            {
                if (DecryptAESWithKey(key, key_usage, out decrypted))
                {
                    return(true);
                }
            }
            foreach (var next in keyset.GetKeysForEncryption(EncryptionType))
            {
                if (DecryptAESWithKey(next, key_usage, out decrypted))
                {
                    return(true);
                }
            }
            decrypted = null;
            return(false);
        }