Beispiel #1
0
        private static KerberosKey CreateKey()
        {
            var principalName = new PrincipalName(PrincipalNameType.NT_PRINCIPAL, "CORP.IDENTITYINTERVENTION.COM", new[] { "testuser" });
            var host          = "";

            var key = new KerberosKey("P@ssw0rd!", principalName: principalName, host: host, saltType: SaltType.ActiveDirectoryUser);

            return(key);
        }
Beispiel #2
0
        public void ValidateChecksum(KerberosKey key)
        {
            var expected = GenerateChecksum(key, this.UserName, this.UserRealm, this.AuthPackage);

            if (!KerberosCryptoTransformer.AreEqualSlow(expected.Checksum.Span, this.Checksum.Checksum.Span))
            {
                throw new SecurityException("Invalid checksum");
            }
        }
Beispiel #3
0
        public void KrbEncryptedDataFailsMismatchedDerivedKey()
        {
            var key = new KerberosKey(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, etype: EncryptionType.AES256_CTS_HMAC_SHA1_96);

            var encryptedData = KrbEncryptedData.Encrypt(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, key, KeyUsage.Ticket);

            var keyOther = new KerberosKey(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, etype: EncryptionType.AES128_CTS_HMAC_SHA1_96);

            encryptedData.Decrypt(keyOther, KeyUsage.Ticket, d => d);
        }
        private KerberosAuthenticator CreateAuthenticator()
        {
            // This could be done with DI and a factory pattern, but we're keeping it simple here.
            var principalName = new PrincipalName(PrincipalNameType.NT_PRINCIPAL, Options.Domain, new[] { Options.UserName });
            var key           = new KerberosKey(Options.Password, principalName, Options.Password);
            var validator     = new KerberosValidator(key);
            var authenticator = new KerberosAuthenticator(validator);

            return(authenticator);
        }
Beispiel #5
0
        private static void AssertChecksum(string plaintextHex, string keyHex, string checksumHex, ChecksumType type)
        {
            var hmac = CryptoService.CreateChecksum(type, HexToByte(checksumHex), HexToByte(plaintextHex));

            hmac.Usage = KeyUsage.Ticket;

            var key = new KerberosKey(HexToByte(keyHex));

            hmac.Validate(key);
        }
        private DecryptedKrbApReq DecryptApReq(KrbApReq apReq, KerberosKey krbtgtKey)
        {
            var apReqDecrypted = new DecryptedKrbApReq(apReq, MessageType.KRB_TGS_REQ);

            apReqDecrypted.Decrypt(krbtgtKey);

            apReqDecrypted.Validate(Validation);

            return(apReqDecrypted);
        }
Beispiel #7
0
        internal void Sign(Memory <byte> pacUnsigned, KerberosKey key)
        {
            Validator = CryptoService.CreateChecksumValidator(Type, Signature, pacUnsigned.ToArray());

            Validator.Sign(key);

            this.Signature = Validator.Signature.ToArray();

            IsDirty = true;
        }
Beispiel #8
0
        internal void Sign(Memory <byte> pacUnsigned, KerberosKey key)
        {
            Validator = CryptoService.CreateChecksumValidator(Type, Signature, pacUnsigned);

            Validator.Sign(key);

            Signature = MemoryMarshal.AsMemory(Validator.Signature);

            IsDirty = true;
        }
Beispiel #9
0
        private static KrbEncTicketPart ExtractTgt(KrbTgsReq tgsReq)
        {
            var paData = tgsReq.PaData.First(p => p.Type == PaDataType.PA_TGS_REQ);

            var apReq = paData.DecodeApReq();

            var krbtgtKey = new KerberosKey(key: Key, etype: EncryptionType.AES256_CTS_HMAC_SHA1_96);

            return(apReq.Ticket.EncryptedPart.Decrypt(krbtgtKey, KeyUsage.Ticket, b => new KrbEncTicketPart().DecodeAsApplication(b)));
        }
Beispiel #10
0
        internal void Sign(Memory <byte> pacUnsigned, KerberosKey key)
        {
            this.Validator = CryptoService.CreateChecksum(this.Type, this.Signature, pacUnsigned);

            this.Validator.Sign(key);

            this.Signature = MemoryMarshal.AsMemory(this.Validator.Signature);

            this.IsDirty = true;
        }
Beispiel #11
0
        private static void GenerateActiveDirectoryUserSalt(KerberosKey key, StringBuilder salt)
        {
            // User accounts:
            //
            // < DNS of the realm, converted to upper case> | < user name >
            //
            // Ex: REALM.COMusername

            salt.Append(key.PrincipalName.Realm.ToUpperInvariant());
            salt.Append(key.PrincipalName.Names.First());
        }
Beispiel #12
0
        public void Validate(KerberosKey key)
        {
            if (this.Validator == null)
            {
                throw new InvalidOperationException($"Validator not set for checksum type {this.Type}");
            }

            this.Validator.Validate(key);

            this.Validated = true;
        }
        public static KrbEncryptedData Encrypt(ReadOnlyMemory <byte> data, KerberosKey key, KeyUsage usage)
        {
            var crypto = CryptoService.CreateTransform(key.EncryptionType);

            ReadOnlyMemory <byte> cipher = crypto.Encrypt(data, key, usage);

            return(new KrbEncryptedData
            {
                Cipher = cipher,
                EType = key.EncryptionType,
                KeyVersionNumber = key.Version
            });
        }
Beispiel #14
0
        public T Decrypt <T>(KerberosKey key, KeyUsage usage, Func <ReadOnlyMemory <byte>, T> func)
        {
            var crypto = CryptoService.CreateTransform(this.EType);

            if (crypto == null)
            {
                throw new InvalidOperationException($"CryptoService couldn't create a transform for type {key.EncryptionType}");
            }

            var decrypted = crypto.Decrypt(this.Cipher, key, usage);

            return(func(decrypted));
        }
Beispiel #15
0
        public static string GenerateSalt(KerberosKey key)
        {
            if (!string.IsNullOrWhiteSpace(key.Salt))
            {
                return(key.Salt);
            }

            var salt = new StringBuilder();

            GenerateSalt(key, salt);

            return(salt.ToString());
        }
Beispiel #16
0
        public override ReadOnlyMemory <byte> String2Key(KerberosKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            return(this.String2Key(
                       key.PasswordBytes,
                       AesSalts.GenerateSalt(key),
                       key.IterationParameter
                       ));
        }
Beispiel #17
0
        private ReadOnlyMemory <byte> GetOrDeriveKey(KerberosKey kerberosKey, KeyUsage usage)
        {
            if (kerberosKey == null)
            {
                throw new InvalidOperationException("Key cannot be null");
            }

            return(kerberosKey.GetOrDeriveKey(
                       this,
                       $"{usage}|Ke|{KeySize}|{BlockSize}",
                       key => DK(key, usage, KeyDerivationMode.Ke, KeySize, BlockSize)
                       ));
        }
Beispiel #18
0
        public void KerberosKeyIdMatches()
        {
            var key = KerberosKey.DeriveFromKeyId(
                "P@ssw0rd!",
                new Guid("0aa29dcb-3a9b-413f-aee2-8df91fd1118e"),
                KrbPrincipalName.FromString(
                    "host/test.identityintervention.com",
                    PrincipalNameType.NT_SRV_INST,
                    "corp.identityintervention.com"
                    )
                );

            AssertKeyMatchesGuid(key.EncryptionType, key);
        }
Beispiel #19
0
        public void DecryptAsReqApplicationMessage()
        {
            var asReqBin = ReadDataFile("messages\\as-req-preauth").Skip(4).ToArray();

            var asReq = KrbAsReq.DecodeApplication(asReqBin);

            Assert.IsNotNull(asReq);

            KerberosKey key = CreateKey();

            var ts = asReq.DecryptTimestamp(key);

            Assert.AreEqual(636985444450060358L, ts.Ticks);
        }
Beispiel #20
0
        public void ThrowsUnknownChecksumType()
        {
            var principal = new FakeKerberosPrincipal("*****@*****.**");

            var pac = principal.GeneratePac();

            var kdcKey    = new KerberosKey(new byte[234], etype: (EncryptionType)(-1));
            var serverKey = new KerberosKey(new byte[32], etype: EncryptionType.AES256_CTS_HMAC_SHA1_96);

            CryptoService.UnregisterChecksumAlgorithm((ChecksumType)(-1));
            CryptoService.UnregisterCryptographicAlgorithm((EncryptionType)(-1));

            pac.Encode(kdcKey, serverKey);
        }
Beispiel #21
0
        private static void GenerateRfc4120Salt(KerberosKey key, StringBuilder salt)
        {
            // RFC 4120 section 4
            // if none is provided via pre-authentication data, is the
            // concatenation of the principal's realm and name components, in order,
            // with no separators

            salt.Append(key.PrincipalName.Realm);

            foreach (var name in key.PrincipalName.Names)
            {
                salt.Append(name);
            }
        }
Beispiel #22
0
        public void TestKerberosValidatorRC4ModifiedPac()
        {
            var key     = ReadDataFile("rc4-key-data");
            var kerbKey = new KerberosKey(key);

            var pacValidated = ValidatePac(
                kerbKey,
                Convert.FromBase64String(RC4_PAC_SIGNATURE),
                Convert.FromBase64String(RC4_PAC)
                );

            Assert.IsTrue(pacValidated);

            GenerateCorruptPac(RC4_PAC_SIGNATURE, RC4_PAC).Validator.Validate(kerbKey);
        }
Beispiel #23
0
        private static KerberosKey CreateKey()
        {
            var principalName = new PrincipalName(PrincipalNameType.NT_PRINCIPAL, "CORP.IDENTITYINTERVENTION.COM", new[] { "testuser" });
            var host          = string.Empty;

            var key = new KerberosKey(
                "P@ssw0rd!",
                principalName: principalName,
                host: host,
                saltType: SaltType.ActiveDirectoryUser,
                etype: EncryptionType.AES256_CTS_HMAC_SHA1_96
                );

            return(key);
        }
Beispiel #24
0
        private static async Task <IEnumerable <KrbAuthorizationData> > GenerateAuthorizationData(
            IKerberosPrincipal principal,
            KerberosKey krbtgt
            )
        {
            // authorization-data is annoying because it's a sequence of
            // ad-if-relevant, which is a sequence of sequences
            // it ends up looking something like
            //
            // [
            //   {
            //      Type = ad-if-relevant,
            //      Data =
            //      [
            //        {
            //           Type = pac,
            //           Data = encoded-pac
            //        },
            //        ...
            //      ],
            //   },
            //   ...
            // ]

            var pac = await principal.GeneratePac();

            var authz = new List <KrbAuthorizationData>();

            var sequence = new KrbAuthorizationDataSequence
            {
                AuthorizationData = new[]
                {
                    new KrbAuthorizationData
                    {
                        Type = AuthorizationDataType.AdWin2kPac,
                        Data = pac.Encode(krbtgt, krbtgt)
                    }
                }
            };

            authz.Add(new KrbAuthorizationData
            {
                Type = AuthorizationDataType.AdIfRelevant,
                Data = sequence.Encode().AsMemory()
            });

            return(authz);
        }
Beispiel #25
0
        public void KerberosValidatorAes128ModifiedPac()
        {
            var key = ReadDataFile("aes128-key-data");

            var kerbKey = new KerberosKey(key);

            var pacValidated = ValidatePac(
                kerbKey,
                Convert.FromBase64String(AES128_PAC_SIGNATURE),
                Convert.FromBase64String(AES128_PAC)
                );

            Assert.IsTrue(pacValidated);

            GenerateCorruptPac(AES128_PAC_SIGNATURE, AES128_PAC).Validator.Validate(kerbKey);
        }
Beispiel #26
0
        public async Task TestPacRoundtrip()
        {
            var keyBytes = ReadDataFile("rc4-key-data");
            var key      = new KerberosKey(keyBytes, etype: EncryptionType.RC4_HMAC_NT);

            var pac = await GeneratePac();

            var encoded = pac.Encode(key, key);

            var pacDecoded = new PrivilegedAttributeCertificate(encoded.ToArray());

            ;

            pacDecoded.ServerSignature.Validator.Validate(key);
            pacDecoded.KdcSignature.Validator.Validate(key);
        }
Beispiel #27
0
        private static void AssertSaltGeneration(EncryptionType etype, SaltType saltType, byte[] expectedKey)
        {
            var key = new KerberosKey(
                "P@ssw0rd!",
                principalName: new PrincipalName(PrincipalNameType.NT_PRINCIPAL, "domain.com", new string[] { "appservice" }),
                host: "appservice",
                etype: etype,
                saltType: saltType
                );

            Assert.AreEqual(saltType, key.SaltFormat);

            var gen = key.GetKey();

            Assert.IsTrue(KerberosCryptoTransformer.AreEqualSlow(gen.Span, expectedKey));
        }
Beispiel #28
0
        public override ReadOnlyMemory <byte> MakeChecksum(
            ReadOnlyMemory <byte> data,
            KerberosKey key,
            KeyUsage usage,
            KeyDerivationMode kdf,
            int hashSize
            )
        {
            var ki = key.GetOrDeriveKey(
                this,
                $"{usage}|{kdf}|{KeySize}|{BlockSize}",
                k => DK(k, usage, kdf, KeySize, BlockSize)
                );

            return(Hmac(ki, data).Slice(0, hashSize));
        }
Beispiel #29
0
        private static void AssertKeyMatchesGuid(EncryptionType etype, KerberosKey kerbKey)
        {
            Assert.AreEqual(EncryptionType.AES256_CTS_HMAC_SHA1_96, etype);

            var derivedKey = kerbKey.GetKey(null);

            Assert.IsNotNull(derivedKey);

            var expectedKey = new byte[]
            {
                0xbc, 0x31, 0x7e, 0x82, 0x48, 0x55, 0xcb, 0xa0, 0x3f, 0x70, 0xbe, 0x93, 0x0a, 0xa5, 0x0f, 0xef,
                0x6a, 0x64, 0x7c, 0xc3, 0x99, 0x36, 0x63, 0xee, 0xa5, 0x39, 0x2f, 0xab, 0xd9, 0x01, 0xad, 0xce
            };

            Assert.IsTrue(expectedKey.SequenceEqual(derivedKey.ToArray()));
        }
        public void TgsParse()
        {
            var tgsReqBytes = ReadDataFile("messages\\tgs-req-testuser-host-app03").Skip(4).ToArray();

            var tgsReq = KrbTgsReq.DecodeApplication(tgsReqBytes);

            var paData = tgsReq.PaData.First(p => p.Type == PaDataType.PA_TGS_REQ);

            var apReq = paData.DecodeApReq();

            var krbtgtKey = new KerberosKey(key: key);

            var krbtgt = apReq.Ticket.EncryptedPart.Decrypt(krbtgtKey, KeyUsage.Ticket, b => new KrbEncTicketPart().DecodeAsApplication(b));

            Assert.AreEqual("testuser", krbtgt.CName.FullyQualifiedName);
        }