private bool DecryptRC4WithKey(KerberosKey key, RC4KeyUsage 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)); }
private static byte[] SerializeEntry(KerberosKey entry) { MemoryStream stm = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stm); WriteUInt16(writer, (ushort)entry.Components.Count()); WriteString(writer, entry.Realm); foreach (string s in entry.Components) { WriteString(writer, s); } WriteInt32(writer, (int)entry.NameType); WriteUInt32(writer, (uint)entry.Timestamp.Subtract(new DateTime(1970, 1, 1)).TotalSeconds); writer.Write((byte)entry.Version); WriteUInt16(writer, (ushort)entry.KeyEncryption); WriteOctets(writer, entry.Key); WriteUInt32(writer, entry.Version); return(stm.ToArray()); }
private bool DecryptRC4(KerberosKeySet keyset, string realm, KerberosPrincipalName server_name, RC4KeyUsage key_usage, out byte[] decrypted) { KerberosKey key = keyset.FindKey(EncryptionType, server_name.NameType, server_name.GetPrincipal(realm), KeyVersion ?? 0); if (key != null) { if (DecryptRC4WithKey(key, key_usage, out decrypted)) { return(true); } } foreach (var next in keyset.GetKeysForEncryption(EncryptionType)) { if (DecryptRC4WithKey(key, key_usage, out decrypted)) { return(true); } } decrypted = null; return(false); }
/// <summary> /// Remove a key from the key set. /// </summary> /// <param name="key">The key to remove.</param> /// <returns>True if the key was removed.</returns> public bool Remove(KerberosKey key) { return(_keys.Remove(key)); }
/// <summary> /// Add a key to the key set. /// </summary> /// <param name="key">The key to add.</param> /// <returns>True if the key was added, false if the key already existed.</returns> public bool Add(KerberosKey key) { return(_keys.Add(key)); }
/// <summary> /// Constructor. /// </summary> /// <param name="key">The single kerberos key.</param> public KerberosKeySet(KerberosKey key) : this(new KerberosKey[] { key }) { }
internal static bool Parse(KerberosTicket orig_ticket, KerberosEncryptedData orig_data, byte[] decrypted, out KerberosEncryptedData ticket) { ticket = null; try { DERValue[] values = DERParser.ParseData(decrypted, 0); if (values.Length != 1) { return(false); } DERValue value = values[0]; if (!value.CheckApplication(2) || !value.HasChildren()) { return(false); } if (!value.Children[0].CheckSequence()) { return(false); } var ret = new KerberosAuthenticator(orig_data); foreach (var next in value.Children[0].Children) { if (next.Type != DERTagType.ContextSpecific) { return(false); } switch (next.Tag) { case 0: if (next.ReadChildInteger() != 5) { return(false); } break; case 1: ret.ClientRealm = next.ReadChildGeneralString(); break; case 2: if (!next.Children[0].CheckSequence()) { return(false); } ret.ClientName = KerberosPrincipalName.Parse(next.Children[0]); break; case 3: if (!next.Children[0].CheckSequence()) { return(false); } ret.Checksum = Kerberos.KerberosChecksum.Parse(next.Children[0]); break; case 4: ret.ClientUSec = next.ReadChildInteger(); break; case 5: ret.ClientTime = next.ReadChildGeneralizedTime(); break; case 6: if (!next.HasChildren()) { return(false); } ret.SubKey = KerberosKey.Parse(next.Children[0], orig_ticket.Realm, orig_ticket.ServerName); break; case 7: ret.SequenceNumber = next.ReadChildInteger(); break; case 8: if (!next.HasChildren()) { return(false); } ret.AuthorizationData = KerberosAuthorizationData.ParseSequence(next.Children[0]); break; default: return(false); } } ticket = ret; } catch (InvalidDataException) { return(false); } catch (EndOfStreamException) { return(false); } return(true); }
private bool DecryptAESWithKey(KerberosKey key, KeyUsage key_usage, out byte[] decrypted) { byte[] derive_enc_key; byte[] derive_mac_key; switch (key_usage) { case KeyUsage.AsRepTgsRepTicket: derive_enc_key = _aes_encrypt_ticket; derive_mac_key = _aes_verify_ticket; break; case KeyUsage.ApReqAuthSubKey: derive_enc_key = _aes_encrypt_auth; derive_mac_key = _aes_verify_auth; break; case KeyUsage.ApRepEncryptedPart: derive_enc_key = _aes_encrypt_ap_rep; derive_mac_key = _aes_verify_ap_rep; break; case KeyUsage.KrbCred: derive_enc_key = _aes_encrypt_krb_cred; derive_mac_key = _aes_verify_krb_cred; break; default: throw new ArgumentException("Unknown key usage type."); } byte[] new_key = KerberosKey.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(KerberosKey.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); }
internal static bool Parse(KerberosEncryptedData orig_data, byte[] decrypted, out KerberosEncryptedData ticket) { ticket = null; try { DERValue[] values = DERParser.ParseData(decrypted, 0); if (values.Length != 1) { return(false); } DERValue value = values[0]; if (!value.CheckApplication(27) || !value.HasChildren()) { return(false); } if (!value.Children[0].CheckSequence()) { return(false); } var ret = new KerberosAPReplyEncryptedPart(orig_data); foreach (var next in value.Children[0].Children) { if (next.Type != DERTagType.ContextSpecific) { return(false); } switch (next.Tag) { case 0: ret.ClientTime = next.ReadChildGeneralizedTime(); break; case 1: ret.ClientUSec = next.ReadChildInteger(); break; case 2: if (!next.HasChildren()) { return(false); } ret.SubKey = KerberosKey.Parse(next.Children[0], string.Empty, new KerberosPrincipalName()); break; case 3: ret.SequenceNumber = next.ReadChildInteger(); break; default: return(false); } } ticket = ret; } catch (InvalidDataException) { return(false); } catch (EndOfStreamException) { return(false); } return(true); }
internal static bool Parse(KerberosTicket orig_ticket, byte[] decrypted, KerberosKeySet keyset, out KerberosTicket ticket) { ticket = null; try { DERValue[] values = DERParser.ParseData(decrypted, 0); if (values.Length != 1) { return(false); } DERValue value = values[0]; if (!value.CheckApplication(3) || !value.HasChildren()) { return(false); } if (!value.Children[0].CheckSequence()) { return(false); } var ret = new KerberosTicketDecrypted(orig_ticket); foreach (var next in value.Children[0].Children) { if (next.Type != DERTagType.ContextSpecific) { return(false); } switch (next.Tag) { case 0: ret.Flags = ConvertTicketFlags(next.ReadChildBitString()); break; case 1: if (!next.HasChildren()) { return(false); } ret.Key = KerberosKey.Parse(next.Children[0], orig_ticket.Realm, orig_ticket.ServerName); keyset.Add(ret.Key); break; case 2: ret.ClientRealm = next.ReadChildGeneralString(); break; case 3: if (!next.Children[0].CheckSequence()) { return(false); } ret.ClientName = KerberosPrincipalName.Parse(next.Children[0]); break; case 4: if (!next.HasChildren()) { return(false); } ret.TransitedType = KerberosTransitedEncoding.Parse(next.Children[0]); break; case 5: ret.AuthTime = next.ReadChildGeneralizedTime(); break; case 6: ret.StartTime = next.ReadChildGeneralizedTime(); break; case 7: ret.EndTime = next.ReadChildGeneralizedTime(); break; case 8: ret.RenewTill = next.ReadChildGeneralizedTime(); break; case 9: if (!next.HasChildren()) { return(false); } ret.HostAddresses = KerberosHostAddress.ParseSequence(next.Children[0]); break; case 10: if (!next.HasChildren()) { return(false); } ret.AuthorizationData = KerberosAuthorizationData.ParseSequence(next.Children[0]); break; default: return(false); } } ticket = ret; } catch (InvalidDataException) { return(false); } catch (EndOfStreamException) { return(false); } return(true); }