2017-10-18 9 views
3

최근에 C#을 배우기 시작했습니다. 이 언어로 NTLM 해시를 만들려고했지만 나에게이 작업을 수행 할 수있는 기능을 찾을 수 없습니다. 파이썬 3.x에서는 hashlib을 가져오고 hashlib.new("md4", "Hello, World!".encode("utf-16le"))으로 계산합니다.C# NTLM 해시 계산기

C#의 개체 브라우저를 통해 검색했지만 아무 것도 찾지 못했습니다. 가장 가까운 것이 Windows NTLM 인증 클래스입니다. 또한 Microsoft의 문서를 검색하여 해시 계산기를 찾았지만 sha1 및 md5 만 찾았습니다.

C#에서 NTLM 해시를 계산하는 방법이 있습니까? 나에게 그것을하는 방법의 예를 보여 주시겠습니까? 나는 그것을 간단하게 유지하는 짧은 방법을 선호합니다.

감사합니다.

답변

2

: 여기

와는 NTLM 해시를 계산하기 위해 모든 단계입니다)을 훨씬 쉽게 :

namespace System.Security.Cryptography { 
    [System.Runtime.InteropServices.ComVisible(true)] 
    public abstract class MD4 : HashAlgorithm { 
     static MD4() { 
      CryptoConfig.AddAlgorithm(typeof(MD4CryptoServiceProvider), "System.Security.Cryptography.MD4"); 
     } 

     protected MD4() { 
      HashSizeValue = 128; 
     } 

     new static public MD4 Create() { 
      return Create("System.Security.Cryptography.MD4"); 
     } 

     new static public MD4 Create(string algName) { 
      return (MD4)CryptoConfig.CreateFromName(algName); 
     } 
    } 

    [System.Runtime.InteropServices.ComVisible(true)] 
    public sealed class MD4CryptoServiceProvider : MD4 { 
     internal static class Utils { 
      internal static Type UtilsType = Type.GetType("System.Security.Cryptography.Utils"); 

      public static T InvokeInternalMethodOfType<T>(object o, object pType, string methodName, params object[] args) { 
       var internalType = (pType is string internalTypeName) ? Type.GetType(internalTypeName) : (Type)pType; 
       var internalMethods = internalType.GetMethods(BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | (o == null ? BindingFlags.Static : 0)); 
       var internalMethod = internalMethods.Where(m => m.Name == methodName && m.GetParameters().Length == args.Length).Single(); 
       return (T)internalMethod?.Invoke(o, args); 
      } 

      public static T GetInternalPropertyValueOfInternalType<T>(object o, object pType, string propertyName) { 
       var internalType = (pType is string internalTypeName) ? Type.GetType(internalTypeName) : (Type)pType; 
       var internalProperty = internalType.GetProperty(propertyName, BindingFlags.NonPublic | (o == null ? BindingFlags.Static : 0)); 
       return (T)internalProperty.GetValue(o); 
      } 

      internal static SafeHandle CreateHash(int algid) { 
       return InvokeInternalMethodOfType<SafeHandle>(null, UtilsType, "CreateHash", GetInternalPropertyValueOfInternalType<object>(null, UtilsType, "StaticProvHandle"), algid); 
      } 

      internal static void HashData(SafeHandle h, byte[] data, int ibStart, int cbSize) { 
       InvokeInternalMethodOfType<object>(null, UtilsType, "HashData", h, data, ibStart, cbSize); 
      } 

      internal static byte[] EndHash(SafeHandle h) { 
       return InvokeInternalMethodOfType<byte[]>(null, UtilsType, "EndHash", h); 
      } 
     } 

     internal const int ALG_CLASS_HASH = (4 << 13); 
     internal const int ALG_TYPE_ANY = (0); 
     internal const int ALG_SID_MD4 = 2; 
     internal const int CALG_MD4 = (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD4); 

     [System.Security.SecurityCritical] 
     private SafeHandle _safeHashHandle = null; 

     [System.Security.SecuritySafeCritical] 
     public MD4CryptoServiceProvider() { 
      if (CryptoConfig.AllowOnlyFipsAlgorithms) 
       throw new InvalidOperationException("Cryptography_NonCompliantFIPSAlgorithm"); 
      Contract.EndContractBlock(); 
      // cheat with Reflection 
      _safeHashHandle = Utils.CreateHash(CALG_MD4); 
     } 

     protected override void Dispose(bool disposing) { 
      if (_safeHashHandle != null && !_safeHashHandle.IsClosed) 
       _safeHashHandle.Dispose(); 
      base.Dispose(disposing); 
     } 

     public override void Initialize() { 
      if (_safeHashHandle != null && !_safeHashHandle.IsClosed) 
       _safeHashHandle.Dispose(); 

      _safeHashHandle = Utils.CreateHash(CALG_MD4); 
     } 

     protected override void HashCore(byte[] rgb, int ibStart, int cbSize) { 
      Utils.HashData(_safeHashHandle, rgb, ibStart, cbSize); 
     } 

     protected override byte[] HashFinal() { 
      return Utils.EndHash(_safeHashHandle); 
     } 
    } 
} 

당신은 도우미 확장의 몇 당신은 (나는 /이 반영의 작업을 할 필요가 없도록 싱글을 만들려면이 수정 쉽게 사용할 수 있도록 할 것을 수행하면 당신이 그것을 사용할 때마다 생성) :

static class Ext { 
    public static HashAlgorithm MD4Singleton; 

    static Ext() { 
     MD4Singleton = System.Security.Cryptography.MD4.Create(); 
    } 

    public static byte[] MD4(this string s) { 
     return MD4Singleton.ComputeHash(System.Text.Encoding.Unicode.GetBytes(s)); 
    } 

    public static string AsHexString(this byte[] bytes) { 
     return String.Join("", bytes.Select(h => h.ToString("X2"))); 
    } 
} 

지금 당신은 몇 가지 샘플 데이터에 대한 확장 메서드를 호출

void Main() { 
    var input = "testing"; 

    var hash = input.MD4(); 
    var hashStr = hash.AsHexString(); 
    Console.WriteLine(hashStr); 
} 
+0

NTLM 해시는 UTF-16LE,하지 ASCII를 사용합니다. ('Encoding.Unicode'는 UTF-16LE의 내장 인스턴스입니다.) –

+0

좋은 캐치 - 고마워요! – NetMage

+0

온라인으로 만든 해시를 확인한 결과 완벽하게 정상적으로 작동했습니다. 감사합니다. –

1

난 당신이 해시를 계산하는 BouncyCastle 사용해야 할 것 같아요, 꽤 잘 작동합니다. NET 포팅이 있습니다. 당신은 (MD4에 대한 CNG를 호출하거나 할 아마 닷넷해야 뭔가를 반사를 사용하여 기존의 암호화 공급자에 대한 확장을 만들거나 할 수 https://asecuritysite.com/encryption/lmhash

1

코드는 여기에 게시물의 끝에서 찾을 수 있습니다. 대부분의 MD4 구현은 약한 키를 열 수있는 방법이 있으므로 MD4에는 BC가 사용됩니다. NTLM은 취약한 키를 고려하지 않으므로 발생하는 경우이를 사용할 수 있어야합니다.

https://markgamache.blogspot.com/2013/01/ntlm-challenge-response-is-100-broken.html

+0

BC 버전이 약 두 배 빠름에도 불구하고 120,000 단어의 사전을 테스트했으며 두 가지 방법 모두 동일한 해시를 만들었습니다. (0.9 초 vs 1.8 초) –