diff --git a/SMBLibrary.Tests/NTLM/NTLMSigningTests.cs b/SMBLibrary.Tests/NTLM/NTLMSigningTests.cs index 1ab6d03..eaf37dd 100644 --- a/SMBLibrary.Tests/NTLM/NTLMSigningTests.cs +++ b/SMBLibrary.Tests/NTLM/NTLMSigningTests.cs @@ -4,8 +4,6 @@ * the GNU Lesser Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. */ -using System; -using System.Collections.Generic; using System.Security.Cryptography; using Microsoft.VisualStudio.TestTools.UnitTesting; using SMBLibrary.Authentication.NTLM; @@ -183,6 +181,34 @@ namespace SMBLibrary.Tests Assert.IsTrue(isMicValid); } + [TestMethod] + public void Test_ComputeClientSignKey() + { + // Arrange + byte[] exportedSessionKey = new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }; + byte[] expected = new byte[] { 0x47, 0x88, 0xdc, 0x86, 0x1b, 0x47, 0x82, 0xf3, 0x5d, 0x43, 0xfd, 0x98, 0xfe, 0x1a, 0x2d, 0x39 }; + + // Act + byte[] signKey = NTLMCryptography.ComputeClientSignKey(exportedSessionKey); + + // Assert + Assert.IsTrue(ByteUtils.AreByteArraysEqual(expected, signKey)); + } + + [TestMethod] + public void Test_ComputeClientSealKey() + { + // Arrange + byte[] exportedSessionKey = new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }; + byte[] expected = new byte[] { 0x59, 0xf6, 0x00, 0x97, 0x3c, 0xc4, 0x96, 0x0a, 0x25, 0x48, 0x0a, 0x7c, 0x19, 0x6e, 0x4c, 0x58 }; + + // Act + byte[] sealKey = NTLMCryptography.ComputeClientSealKey(exportedSessionKey); + + // Assert + Assert.IsTrue(ByteUtils.AreByteArraysEqual(expected, sealKey)); + } + private static byte[] GetExportedSessionKey(byte[] sessionBaseKey, AuthenticateMessage message, byte[] serverChallenge, byte[] lmowf) { byte[] keyExchangeKey; diff --git a/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs b/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs index ec7c8c8..d0da43f 100644 --- a/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs +++ b/SMBLibrary/Authentication/NTLM/Helpers/NTLMCryptography.cs @@ -273,5 +273,61 @@ namespace SMBLibrary.Authentication.NTLM return ByteUtils.AreByteArraysEqual(mic, expectedMic); } + + public static byte[] ComputeClientSignKey(byte[] exportedSessionKey) + { + return ComputeSignKey(exportedSessionKey, true); + } + + public static byte[] ComputeServerSignKey(byte[] exportedSessionKey) + { + return ComputeSignKey(exportedSessionKey, false); + } + + private static byte[] ComputeSignKey(byte[] exportedSessionKey, bool isClient) + { + // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/524cdccb-563e-4793-92b0-7bc321fce096 + string str; + if (isClient) + { + str = "session key to client-to-server signing key magic constant"; + } + else + { + str = "session key to server-to-client signing key magic constant"; + } + byte[] encodedString = Encoding.GetEncoding(28591).GetBytes(str); + byte[] nullTerminatedEncodedString = ByteUtils.Concatenate(encodedString, new byte[1]); + byte[] concatendated = ByteUtils.Concatenate(exportedSessionKey, nullTerminatedEncodedString); + return MD5.Create().ComputeHash(concatendated); + } + + public static byte[] ComputeClientSealKey(byte[] exportedSessionKey) + { + return ComputeSealKey(exportedSessionKey, true); + } + + public static byte[] ComputeServerSealKey(byte[] exportedSessionKey) + { + return ComputeSealKey(exportedSessionKey, false); + } + + private static byte[] ComputeSealKey(byte[] exportedSessionKey, bool isClient) + { + // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/524cdccb-563e-4793-92b0-7bc321fce096 + string str; + if (isClient) + { + str = "session key to client-to-server sealing key magic constant"; + } + else + { + str = "session key to server-to-client sealing key magic constant"; + } + byte[] encodedString = Encoding.GetEncoding(28591).GetBytes(str); + byte[] nullTerminatedEncodedString = ByteUtils.Concatenate(encodedString, new byte[1]); + byte[] concatendated = ByteUtils.Concatenate(exportedSessionKey, nullTerminatedEncodedString); + return MD5.Create().ComputeHash(concatendated); + } } }