private byte[] DeriveTempKey(KerberosAuthenticationKey key, KeyUsage 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));
 }
コード例 #2
0
        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 = KerberosAuthenticationKey.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);
        }
        private bool DecryptAESWithKey(KerberosAuthenticationKey key, KeyUsage 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);
        }
コード例 #4
0
        private static byte[] SerializeEntry(KerberosAuthenticationKey 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 DecryptRC4WithKey(KerberosAuthenticationKey key, KeyUsage 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 bool DecryptAES(KerberosKeySet keyset, string realm, KerberosPrincipalName server_name, KeyUsage 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);
        }
        internal static bool Parse(KerberosTicket orig_ticket, KerberosEncryptedData orig_data, byte[] decrypted, KerberosKeySet keyset, 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 = 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 = KerberosAuthenticationKey.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);
                    }
                }

                if (ret.Checksum is KerberosChecksumGSSApi gssapi && gssapi.Credentials != null)
                {
                    KerberosKeySet tmp_keyset = new KerberosKeySet(keyset.AsEnumerable() ?? new KerberosAuthenticationKey[0]);
                    if (ret.SubKey != null)
                    {
                        tmp_keyset.Add(ret.SubKey);
                    }

                    gssapi.Decrypt(tmp_keyset);
                }

                ticket = ret;
            }
            catch (InvalidDataException)
            {
                return(false);
            }
            catch (EndOfStreamException)
            {
                return(false);
            }
            return(true);
        }
コード例 #8
0
        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 = KerberosAuthenticationKey.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);
        }