public static ReadOnlyMemory <byte> GenerateSaltBytes(KerberosKey key) { if (key != null && key.SaltBytes.Length > 0) { return(key.SaltBytes); } return(UnicodeStringToUtf8(GenerateSalt(key))); }
public virtual ReadOnlyMemory <byte> MakeChecksum( ReadOnlyMemory <byte> data, KerberosKey key, KeyUsage usage, KeyDerivationMode kdf, int hashSize) { throw new NotImplementedException(); }
protected override ReadOnlyMemory <byte> SignInternal(KerberosKey key) { return(decryptor.MakeChecksum( Data, key, Usage, KeyDerivationMode.Kc, decryptor.ChecksumSize )); }
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)); }
protected override ReadOnlyMemory <byte> SignInternal(KerberosKey key) { var crypto = CryptoService.CreateTransform(EncryptionType.RC4_HMAC_NT); return(crypto.MakeChecksum( key.GetKey(crypto), Data.Span, Usage )); }
protected override ReadOnlySpan <byte> SignInternal(KerberosKey key) { return(decryptor.MakeChecksum( Pac.Span, key, KeyUsage.PaForUserChecksum, KeyDerivationMode.Kc, decryptor.ChecksumSize )); }
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 )); }
protected override ReadOnlyMemory <byte> SignInternal(KerberosKey key) { return(decryptor.MakeChecksum( Pac.ToArray(), key.GetKey(decryptor), KeyUsage.PaForUserChecksum, KeyDerivationMode.Kc, decryptor.ChecksumSize )); }
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()); }
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)); }
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) )); }
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 )); }
public static string GenerateSalt(KerberosKey key) { if (!string.IsNullOrWhiteSpace(key.Salt)) { return(key.Salt); } var salt = new StringBuilder(); GenerateSalt(key, salt); return(salt.ToString()); }
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)); }
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()); }
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); } }
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 )); }
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); }
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)); } } }
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; } } }
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())); }
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);
public KeyEntry(KerberosKey key) { Key = key; Principal = key.PrincipalName; }
protected override bool ValidateInternal(KerberosKey key) { var actualChecksum = SignInternal(key); return(KerberosCryptoTransformer.AreEqualSlow(actualChecksum, Signature.Span)); }