This is an implementation of the HMACT64 keyed hashing algorithm.
This is an implementation of the HMACT64 keyed hashing algorithm. HMACT64 is defined by Luke Leighton as a modified HMAC-MD5 (RFC 2104) in which the key is truncated at 64 bytes (rather than being hashed via MD5).
Inheritance: SharpCifs.Util.Sharpen.MessageDigest
		/// <summary>Calculates the effective user session key.</summary>
		/// <remarks>Calculates the effective user session key.</remarks>
		/// <param name="challenge">The server challenge.</param>
		/// <param name="dest">
		/// The destination array in which the user session key will be
		/// placed.
		/// </param>
		/// <param name="offset">
		/// The offset in the destination array at which the
		/// session key will start.
		/// </param>
		/// <exception cref="SharpCifs.Smb.SmbException"></exception>
		internal void GetUserSessionKey(byte[] challenge, byte[] dest, int offset)
		{
			if (HashesExternal)
			{
				return;
			}
			try
			{
				Md4 md4 = new Md4();
				md4.Update(Runtime.GetBytesForString(Password, SmbConstants.UniEncoding)
					);
				switch (LmCompatibility)
				{
					case 0:
					case 1:
					case 2:
					{
						md4.Update(md4.Digest());
						md4.Digest(dest, offset, 16);
						break;
					}

					case 3:
					case 4:
					case 5:
					{
						if (ClientChallenge == null)
						{
							ClientChallenge = new byte[8];
							Random.NextBytes(ClientChallenge);
						}
						Hmact64 hmac = new Hmact64(md4.Digest());
						hmac.Update(Runtime.GetBytesForString(Username.ToUpper(), SmbConstants.UniEncoding
							));
						hmac.Update(Runtime.GetBytesForString(Domain.ToUpper(), SmbConstants.UniEncoding
							));
						byte[] ntlmv2Hash = hmac.Digest();
						hmac = new Hmact64(ntlmv2Hash);
						hmac.Update(challenge);
						hmac.Update(ClientChallenge);
						Hmact64 userKey = new Hmact64(ntlmv2Hash);
						userKey.Update(hmac.Digest());
						userKey.Digest(dest, offset, 16);
						break;
					}

					default:
					{
						md4.Update(md4.Digest());
						md4.Digest(dest, offset, 16);
						break;
					}
				}
			}
			catch (Exception e)
			{
				throw new SmbException(string.Empty, e);
			}
		}
		internal static byte[] ComputeResponse(byte[] responseKey, byte[] serverChallenge
			, byte[] clientData, int offset, int length)
		{
			Hmact64 hmac = new Hmact64(responseKey);
			hmac.Update(serverChallenge);
			hmac.Update(clientData, offset, length);
			byte[] mac = hmac.Digest();
			byte[] ret = new byte[mac.Length + clientData.Length];
			Array.Copy(mac, 0, ret, 0, mac.Length);
			Array.Copy(clientData, 0, ret, mac.Length, clientData.Length);
			return ret;
		}
		/// <summary>Creates the LMv2 response for the supplied information.</summary>
		/// <remarks>Creates the LMv2 response for the supplied information.</remarks>
		/// <param name="domain">The domain in which the username exists.</param>
		/// <param name="user">The username.</param>
		/// <param name="password">The user's password.</param>
		/// <param name="challenge">The server challenge.</param>
		/// <param name="clientChallenge">The client challenge (nonce).</param>
		public static byte[] GetLMv2Response(string domain, string user, string password, 
			byte[] challenge, byte[] clientChallenge)
		{
			try
			{
				byte[] hash = new byte[16];
				byte[] response = new byte[24];
				// The next 2-1/2 lines of this should be placed with nTOWFv1 in place of password
				Md4 md4 = new Md4();
				md4.Update(Runtime.GetBytesForString(password, SmbConstants.UniEncoding)
					);
				Hmact64 hmac = new Hmact64(md4.Digest());
				hmac.Update(Runtime.GetBytesForString(user.ToUpper(), SmbConstants.UniEncoding
					));
				hmac.Update(Runtime.GetBytesForString(domain.ToUpper(), SmbConstants.UniEncoding
					));
				hmac = new Hmact64(hmac.Digest());
				hmac.Update(challenge);
				hmac.Update(clientChallenge);
				hmac.Digest(response, 0, 16);
				Array.Copy(clientChallenge, 0, response, 16, 8);
				return response;
			}
			catch (Exception ex)
			{
				if (_log.Level > 0)
				{
					Runtime.PrintStackTrace(ex, _log);
				}
				return null;
			}
		}
		public static byte[] NtowFv2(string domain, string username, string password)
		{
			try
			{
				Md4 md4 = new Md4();
				md4.Update(Runtime.GetBytesForString(password, SmbConstants.UniEncoding)
					);
				Hmact64 hmac = new Hmact64(md4.Digest());
				hmac.Update(Runtime.GetBytesForString(username.ToUpper(), SmbConstants.UniEncoding
					));
				hmac.Update(Runtime.GetBytesForString(domain, SmbConstants.UniEncoding));
				return hmac.Digest();
			}
			catch (UnsupportedEncodingException uee)
			{
				throw new RuntimeException(uee.Message);
			}
		}
Example #5
0
		/// <summary>Creates a Type-3 message in response to the given Type-2 message.</summary>
		/// <remarks>Creates a Type-3 message in response to the given Type-2 message.</remarks>
		/// <param name="type2">The Type-2 message which this represents a response to.</param>
		/// <param name="password">The password to use when constructing the response.</param>
		/// <param name="domain">The domain in which the user has an account.</param>
		/// <param name="user">The username for the authenticating user.</param>
		/// <param name="workstation">
		/// The workstation from which authentication is
		/// taking place.
		/// </param>
		public Type3Message(Type2Message type2, string password, string domain, string user
			, string workstation, int flags)
		{
			SetFlags(flags | GetDefaultFlags(type2));
			if (workstation == null)
			{
				workstation = GetDefaultWorkstation();
			}
			SetWorkstation(workstation);
			SetDomain(domain);
			SetUser(user);
			switch (LmCompatibility)
			{
				case 0:
				case 1:
				{
					if ((GetFlags() & NtlmsspNegotiateNtlm2) == 0)
					{
						SetLmResponse(GetLMResponse(type2, password));
						SetNtResponse(GetNTResponse(type2, password));
					}
					else
					{
						// NTLM2 Session Response
						byte[] clientChallenge = new byte[24];
						//RANDOM.NextBytes(clientChallenge);
						Arrays.Fill(clientChallenge, 8, 24, unchecked((byte)unchecked(0x00)));
						// NTLMv1 w/ NTLM2 session sec and key exch all been verified with a debug build of smbclient
						byte[] responseKeyNt = NtlmPasswordAuthentication.NtowFv1(password);
						byte[] ntlm2Response = NtlmPasswordAuthentication.GetNtlm2Response(responseKeyNt, 
							type2.GetChallenge(), clientChallenge);
						SetLmResponse(clientChallenge);
						SetNtResponse(ntlm2Response);
						if ((GetFlags() & NtlmsspNegotiateSign) == NtlmsspNegotiateSign)
						{
							byte[] sessionNonce = new byte[16];
							Array.Copy(type2.GetChallenge(), 0, sessionNonce, 0, 8);
							Array.Copy(clientChallenge, 0, sessionNonce, 8, 8);
							Md4 md4 = new Md4();
							md4.Update(responseKeyNt);
							byte[] userSessionKey = md4.Digest();
							Hmact64 hmac = new Hmact64(userSessionKey);
							hmac.Update(sessionNonce);
							byte[] ntlm2SessionKey = hmac.Digest();
							if ((GetFlags() & NtlmsspNegotiateKeyExch) != 0)
							{
								_masterKey = new byte[16];
								//RANDOM.NextBytes(masterKey);
								byte[] exchangedKey = new byte[16];
								Rc4 rc4 = new Rc4(ntlm2SessionKey);
								rc4.Update(_masterKey, 0, 16, exchangedKey, 0);
								SetSessionKey(exchangedKey);
							}
							else
							{
								_masterKey = ntlm2SessionKey;
								SetSessionKey(_masterKey);
							}
						}
					}
					break;
				}

				case 2:
				{
					byte[] nt = GetNTResponse(type2, password);
					SetLmResponse(nt);
					SetNtResponse(nt);
					break;
				}

				case 3:
				case 4:
				case 5:
				{
					byte[] responseKeyNt1 = NtlmPasswordAuthentication.NtowFv2(domain, user, password
						);
					byte[] clientChallenge1 = new byte[8];
					//RANDOM.NextBytes(clientChallenge_1);
					SetLmResponse(GetLMv2Response(type2, domain, user, password, clientChallenge1));
					byte[] clientChallenge2 = new byte[8];
					//RANDOM.NextBytes(clientChallenge2);
					SetNtResponse(GetNtlMv2Response(type2, responseKeyNt1, clientChallenge2));
					if ((GetFlags() & NtlmsspNegotiateSign) == NtlmsspNegotiateSign)
					{
						Hmact64 hmac = new Hmact64(responseKeyNt1);
						hmac.Update(_ntResponse, 0, 16);
						// only first 16 bytes of ntResponse
						byte[] userSessionKey = hmac.Digest();
						if ((GetFlags() & NtlmsspNegotiateKeyExch) != 0)
						{
							_masterKey = new byte[16];
							//RANDOM.NextBytes(masterKey);
							byte[] exchangedKey = new byte[16];
							Rc4 rc4 = new Rc4(userSessionKey);
							rc4.Update(_masterKey, 0, 16, exchangedKey, 0);
							SetSessionKey(exchangedKey);
						}
						else
						{
							_masterKey = userSessionKey;
							SetSessionKey(_masterKey);
						}
					}
					break;
				}

				default:
				{
					SetLmResponse(GetLMResponse(type2, password));
					SetNtResponse(GetNTResponse(type2, password));
					break;
				}
			}
		}