Implements the MD4 message digest algorithm in Java.
Implements the MD4 message digest algorithm in Java.

References:

  1. Ronald L. Rivest, " The MD4 Message-Digest Algorithm", IETF RFC-1320 (informational).

$Revision: 1.2 $

상속: SharpCifs.Util.Sharpen.MessageDigest
예제 #1
0
 /// <summary>This constructor is here to implement cloneability of this class.</summary>
 /// <remarks>This constructor is here to implement cloneability of this class.</remarks>
 private Md4(Md4 md) : this()
 {
     _context = (int[])md._context.Clone();
     _buffer  = (byte[])md._buffer.Clone();
     _count   = md._count;
 }
		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);
			}
		}
		/// <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);
			}
		}
		public static byte[] NtowFv1(string password)
		{
			if (password == null)
			{
				throw new RuntimeException("Password parameter is required");
			}
			try
			{
				Md4 md4 = new Md4();
				md4.Update(Runtime.GetBytesForString(password, SmbConstants.UniEncoding)
					);
				return md4.Digest();
			}
			catch (UnsupportedEncodingException uee)
			{
				throw new RuntimeException(uee.Message);
			}
		}
		/// <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;
			}
		}
		/// <summary>Generate the Unicode MD4 hash for the password associated with these credentials.
		/// 	</summary>
		/// <remarks>Generate the Unicode MD4 hash for the password associated with these credentials.
		/// 	</remarks>
		public static byte[] GetNtlmResponse(string password, byte[] challenge)
		{
			byte[] uni = null;
			byte[] p21 = new byte[21];
			byte[] p24 = new byte[24];
			try
			{
				uni = Runtime.GetBytesForString(password, SmbConstants.UniEncoding);
			}
			catch (UnsupportedEncodingException uee)
			{
				if (_log.Level > 0)
				{
					Runtime.PrintStackTrace(uee, _log);
				}
			}
			Md4 md4 = new Md4();
			md4.Update(uni);
			try
			{
				md4.Digest(p21, 0, 16);
			}
			catch (Exception ex)
			{
				if (_log.Level > 0)
				{
					Runtime.PrintStackTrace(ex, _log);
				}
			}
			E(p21, challenge, p24);
			return p24;
		}
예제 #7
0
		/// <summary>This constructor is here to implement cloneability of this class.</summary>
		/// <remarks>This constructor is here to implement cloneability of this class.</remarks>
		private Md4(Md4 md) : this()
		{
			_context = (int[])md._context.Clone();
			_buffer = (byte[])md._buffer.Clone();
			_count = md._count;
		}
예제 #8
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;
				}
			}
		}