/// <summary> /// Derive a key from a password. /// </summary> /// <remarks>Not all encryption types are supported.</remarks> /// <param name="key_encryption">The key encryption to use.</param> /// <param name="password">The password to derice from.</param> /// <param name="iterations">Iterations for the password derivation.</param> /// <param name="name_type">The key name type.</param> /// <param name="principal">Principal for key, in form TYPE/name@realm.</param> /// <param name="salt">Salt for the key.</param> /// <param name="version">Key Version Number (KVNO).</param> /// <returns></returns> public static KerberosAuthenticationKey DeriveKey(KerberosEncryptionType key_encryption, string password, int iterations, KerberosNameType name_type, string principal, string salt, uint version) { if (principal is null) { throw new ArgumentNullException(nameof(principal)); } byte[] key; switch (key_encryption) { case KerberosEncryptionType.ARCFOUR_HMAC_MD5: case KerberosEncryptionType.ARCFOUR_HMAC_MD5_56: case KerberosEncryptionType.ARCFOUR_HMAC_OLD: case KerberosEncryptionType.ARCFOUR_HMAC_OLD_EXP: key = MD4.CalculateHash(Encoding.Unicode.GetBytes(password)); break; case KerberosEncryptionType.AES128_CTS_HMAC_SHA1_96: key = DeriveAesKey(password, MakeSalt(salt, principal), iterations, 16); break; case KerberosEncryptionType.AES256_CTS_HMAC_SHA1_96: key = DeriveAesKey(password, MakeSalt(salt, principal), iterations, 32); break; default: throw new ArgumentException($"Unsupported key type {key_encryption}", nameof(key_encryption)); } return(new KerberosAuthenticationKey(key_encryption, key, name_type, principal, DateTime.Now, version)); }