C# NTLM 哈希计算器

标签 c# hash ntlm

我最近开始学习 C#。我试图用这种语言生成一个 NTLM 散列,但找不到为我执行此操作的函数。在 python 3.x 中,我将导入 hashlib 并使用 hashlib.new("md4", "Hello, World!".encode("utf-16le")) 计算它>。

我在 C# 中搜索对象浏览器但没有找到任何东西,最接近的是 Windows NTLM 身份验证类。我还搜索了 Microsoft 的文档并找到了哈希计算器,但仅适用于 sha1 和 md5。

有没有办法在 C# 中计算 NTLM 哈希?你能告诉我一个如何做的例子吗,我更喜欢一个简短的方法来保持简单。

谢谢。

最佳答案

您可以使用反射为现有的加密提供程序创建一个扩展,为 MD4 调用 CNG(这可能是 .Net 应该做的,或者更容易):

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);
}

关于C# NTLM 哈希计算器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46819638/

相关文章:

arrays - ruby 散列作为数组的第一个元素

ruby - 最简洁的方法,采用单级散列参数并返回具有 nil 值的副本

Python:通过 NTLM 从嵌入式 ZIP 文件安装 PIP

c# - 如何修复 'The the message received was unexpected or badly formatted'

c# - 正则表达式:在仍捕获数据的同时进行向后查找的性能?

go - 哈希反射类型

c# - 使用 HTTP Web 请求发送 HTTP header 以进行 NTLM 身份验证

http - Go HTTP NTLM 请求中的 Windows 系统凭据

c# - C# : The type or namespace 'SmptMailMessage' could not be found 错误

c# - 在 Swagger UI 中指示复杂输入参数对象的必需属性