Exemple #1
0
        public static ReadOnlyMemory <byte> GenerateSaltBytes(KerberosKey key)
        {
            if (key != null && key.SaltBytes.Length > 0)
            {
                return(key.SaltBytes);
            }

            return(UnicodeStringToUtf8(GenerateSalt(key)));
        }
Exemple #2
0
 public virtual ReadOnlyMemory <byte> MakeChecksum(
     ReadOnlyMemory <byte> data,
     KerberosKey key,
     KeyUsage usage,
     KeyDerivationMode kdf,
     int hashSize)
 {
     throw new NotImplementedException();
 }
Exemple #3
0
 protected override ReadOnlyMemory <byte> SignInternal(KerberosKey key)
 {
     return(decryptor.MakeChecksum(
                Data,
                key,
                Usage,
                KeyDerivationMode.Kc,
                decryptor.ChecksumSize
                ));
 }
Exemple #4
0
        protected override bool ValidateInternal(KerberosKey key)
        {
            var actualChecksum = KerberosHash.KerbChecksumHmacMd5(
                key.GetKey(new MD4Encryptor()),
                (int)KeyUsage.KU_PA_FOR_USER_ENC_CKSUM,
                Pac
                );

            return(KerberosHash.AreEqualSlow(actualChecksum, Signature));
        }
Exemple #5
0
        protected override ReadOnlyMemory <byte> SignInternal(KerberosKey key)
        {
            var crypto = CryptoService.CreateTransform(EncryptionType.RC4_HMAC_NT);

            return(crypto.MakeChecksum(
                       key.GetKey(crypto),
                       Data.Span,
                       Usage
                       ));
        }
Exemple #6
0
 protected override ReadOnlySpan <byte> SignInternal(KerberosKey key)
 {
     return(decryptor.MakeChecksum(
                Pac.Span,
                key,
                KeyUsage.PaForUserChecksum,
                KeyDerivationMode.Kc,
                decryptor.ChecksumSize
                ));
 }
Exemple #7
0
        protected override ReadOnlySpan <byte> SignInternal(KerberosKey key)
        {
            var crypto = CryptoService.CreateTransform(EncryptionType.RC4_HMAC_NT);

            return(crypto.MakeChecksum(
                       key.GetKey(crypto),
                       Pac.Span,
                       KeyUsage.PaForUserChecksum
                       ));
        }
Exemple #8
0
 protected override ReadOnlyMemory <byte> SignInternal(KerberosKey key)
 {
     return(decryptor.MakeChecksum(
                Pac.ToArray(),
                key.GetKey(decryptor),
                KeyUsage.PaForUserChecksum,
                KeyDerivationMode.Kc,
                decryptor.ChecksumSize
                ));
 }
Exemple #9
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.Name.First());
        }
Exemple #10
0
        public KeyEntry(KerberosKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            this.Key            = key;
            this.Principal      = key.PrincipalName;
            this.EncryptionType = key.EncryptionType;
            this.Timestamp      = DateTimeOffset.UtcNow;
        }
        public override ReadOnlyMemory <byte> MakeChecksum(
            ReadOnlyMemory <byte> data,
            KerberosKey key,
            KeyUsage usage,
            KeyDerivationMode kdf,
            int hashSize
            )
        {
            var ki = this.GetOrDeriveKey(key, usage, kdf).Slice(0, hashSize);

            return(this.Hmac(ki, data).Slice(0, hashSize));
        }
Exemple #12
0
        protected ReadOnlyMemory <byte> GetOrDeriveKey(KerberosKey kerberosKey, KeyUsage usage, KeyDerivationMode mode)
        {
            if (kerberosKey == null)
            {
                throw new InvalidOperationException("Key cannot be null");
            }

            return(kerberosKey.GetOrDeriveKey(
                       this,
                       $"{usage}|{mode}|{this.KeySize}|{this.BlockSize}",
                       key => this.DK(key, usage, mode, this.KeySize, this.BlockSize)
                       ));
        }
Exemple #13
0
        public override ReadOnlyMemory <byte> String2Key(KerberosKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            return(this.String2Key(
                       key.PasswordBytes,
                       AesSalts.GenerateSaltBytes(key),
                       key.IterationParameter
                       ));
        }
Exemple #14
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());
        }
Exemple #15
0
        protected override bool ValidateInternal(KerberosKey key)
        {
            var constant = new byte[5];

            KerberosHash.ConvertToBigEndian((int)KeyUsage.KU_PA_FOR_USER_ENC_CKSUM, constant, 0);

            constant[4] = 0x99;

            var Ki = encryptor.DK(key.GetKey(encryptor), constant);

            var actualChecksum = decryptor.MakeChecksum(Ki, Pac, decryptor.ChecksumSize);

            return(KerberosHash.AreEqualSlow(actualChecksum, Signature));
        }
Exemple #16
0
        private static void GenerateActiveDirectoryServiceSalt(KerberosKey key, StringBuilder salt)
        {
            // Computer accounts:
            //
            // < DNS name of the realm, converted to upper case > |
            // "host" |
            // < computer name, converted to lower case with trailing "$" stripped off > |
            // "." |
            // < DNS name of the realm, converted to lower case >
            //
            // Ex: REALM.COMhostappservice.realm.com

            salt.Append(key.PrincipalName.Realm.ToUpperInvariant());

            salt.Append("host");

            string host;

            if (!string.IsNullOrWhiteSpace(key.Host))
            {
                host = key.Host.ToLowerInvariant();
            }
            else
            {
                var spnSplit = key.PrincipalName.FullyQualifiedName.Split('/', '@');

                if (spnSplit.Length == 0)
                {
                    host = "";
                }
                else if (spnSplit.Length == 1 || !key.PrincipalName.FullyQualifiedName.Contains('/'))
                {
                    host = spnSplit[0];
                }
                else
                {
                    host = spnSplit[1];
                }
            }

            if (host.EndsWith("$"))
            {
                host = host.Substring(0, host.Length - 1);
            }

            salt.Append(host);

            salt.Append(".");
            salt.Append(key.PrincipalName.Realm.ToLowerInvariant());
        }
Exemple #17
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.Name)
            {
                salt.Append(name);
            }
        }
Exemple #18
0
        public override int ChecksumSize => 16; // bytes

        protected override ReadOnlyMemory <byte> SignInternal(KerberosKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            var crypto = CryptoService.CreateTransform(EncryptionType.RC4_HMAC_NT);

            return(crypto.MakeChecksum(
                       key.GetKey(crypto),
                       this.Data.Span,
                       this.Usage
                       ));
        }
Exemple #19
0
        public static KerberosKey DeriveFromKeyId(
            string password,
            Guid saltGuid,
            KrbPrincipalName name,
            EncryptionType etype = EncryptionType.AES256_CTS_HMAC_SHA1_96
            )
        {
            var salt = NormalizeGuid(saltGuid);

            var kerbKey = new KerberosKey(
                password: password,
                etype: etype,
                salt: salt,
                principalName: name.ToKeyPrincipal()
                );

            return(kerbKey);
        }
Exemple #20
0
        private static string GenerateSalt(KerberosKey key)
        {
            var salt = new StringBuilder();

            if (key.PrincipalName == null)
            {
                return(salt.ToString());
            }

            salt.Append(key.PrincipalName.Realm);

            salt.Append("host");
            salt.Append(key.Host);
            salt.Append(".");
            salt.Append(key.PrincipalName.Realm.ToLowerInvariant());

            return(salt.ToString());
        }
        public override ReadOnlyMemory <byte> Encrypt(ReadOnlyMemory <byte> data, KerberosKey kerberosKey, KeyUsage usage)
        {
            var ke = this.GetOrDeriveKey(kerberosKey, usage, KeyDerivationMode.Ke);

            ReadOnlyMemory <byte> confounder;

            if (this.Confounder.Length > 0)
            {
                confounder = this.Confounder;
            }
            else
            {
                confounder = this.GenerateRandomBytes(this.ConfounderSize);
            }

            var concatLength = confounder.Length + data.Length;

            using (var cleartextPool = CryptoPool.Rent <byte>(concatLength))
            {
                var cleartext = cleartextPool.Memory.Slice(0, concatLength);

                Concat(confounder.Span, data.Span, cleartext);

                var encrypted = AESCTS.Encrypt(
                    cleartext,
                    ke,
                    AllZerosInitVector
                    );

                var checksumDataLength = AllZerosInitVector.Length + encrypted.Length;

                using (var checksumDataRented = CryptoPool.Rent <byte>(checksumDataLength))
                {
                    var checksumData = checksumDataRented.Memory.Slice(0, checksumDataLength);

                    Concat(AllZerosInitVector.Span, encrypted.Span, checksumData);

                    var checksum = this.MakeChecksum(checksumData, kerberosKey, usage, KeyDerivationMode.Ki, this.ChecksumSize);

                    return(Concat(encrypted.Span, checksum.Span));
                }
            }
        }
Exemple #22
0
        public static void GenerateSalt(KerberosKey key, StringBuilder salt)
        {
            if (key.PrincipalName != null)
            {
                switch (key.SaltFormat)
                {
                case SaltType.ActiveDirectoryService:
                    GenerateActiveDirectoryServiceSalt(key, salt);
                    break;

                case SaltType.ActiveDirectoryUser:
                    GenerateActiveDirectoryUserSalt(key, salt);
                    break;

                case SaltType.Rfc4120:
                    GenerateRfc4120Salt(key, salt);
                    break;
                }
            }
        }
Exemple #23
0
        public override ReadOnlyMemory <byte> Decrypt(ReadOnlyMemory <byte> cipher, KerberosKey kerberosKey, KeyUsage usage)
        {
            var cipherLength = cipher.Length - this.ChecksumSize;

            var ke = this.GetOrDeriveKey(kerberosKey, usage, KeyDerivationMode.Ke);

            var decrypted = AESCTS.Decrypt(
                cipher.Slice(0, cipherLength),
                ke,
                AllZerosInitVector
                );

            var actualChecksum = this.MakeChecksum(decrypted, kerberosKey, usage, KeyDerivationMode.Ki, this.ChecksumSize);

            var expectedChecksum = cipher.Slice(cipherLength, this.ChecksumSize);

            if (!AreEqualSlow(expectedChecksum.Span, actualChecksum.Span))
            {
                throw new SecurityException("Invalid checksum");
            }

            return(decrypted.Slice(this.ConfounderSize, cipherLength - this.ConfounderSize));
        }
        public override ReadOnlyMemory <byte> Encrypt(ReadOnlyMemory <byte> data, KerberosKey key, KeyUsage usage)
        {
            var k1 = key.GetKey(this);

            var salt = GetSalt((int)usage);

            var k2 = HMACMD5(k1, salt);

            var confounder = GenerateRandomBytes(ConfounderSize);

            var plaintext = new byte[data.Length + confounder.Length];

            Buffer.BlockCopy(confounder.ToArray(), 0, plaintext, 0, confounder.Length);
            Buffer.BlockCopy(data.ToArray(), 0, plaintext, confounder.Length, data.Length);

            var checksum = HMACMD5(k2, plaintext);

            var k3 = HMACMD5(k2, checksum);

            var ciphertext = RC4.Transform(k3, plaintext);

            return(new ReadOnlyMemory <byte>(checksum.Concat(ciphertext.ToArray()).ToArray()));
        }
Exemple #25
0
        private static void WriteKey(BinaryWriter writer, KerberosKey key)
        {
            WriteInt16(writer, (short)key.EncryptionType);

            WriteBytes(writer, key.GetKey());
        }
 public abstract ReadOnlyMemory <byte> Encrypt(ReadOnlyMemory <byte> data, KerberosKey key, KeyUsage usage);
 public abstract ReadOnlyMemory <byte> Decrypt(ReadOnlyMemory <byte> cipher, KerberosKey key, KeyUsage usage);
 public abstract ReadOnlyMemory <byte> String2Key(KerberosKey key);
Exemple #29
0
 public KeyEntry(KerberosKey key)
 {
     Key       = key;
     Principal = key.PrincipalName;
 }
Exemple #30
0
        protected override bool ValidateInternal(KerberosKey key)
        {
            var actualChecksum = SignInternal(key);

            return(KerberosCryptoTransformer.AreEqualSlow(actualChecksum, Signature.Span));
        }