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)); }
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); }