You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何实现从文本文件内容生成MD4哈希值

C# 实现文件MD4哈希计算方案

.NET 官方的System.Security.Cryptography命名空间没有内置MD4算法实现,原因是MD4存在严重的安全缺陷,早已被官方标记为不安全算法不再提供支持。如果确实有兼容旧系统的MD4计算需求,可以参考以下方案实现:


方案1:自定义MD4类(兼容原有MD5调用逻辑)

可以按照MD4标准算法规范封装和内置MD5用法完全一致的工具类,原有代码只需要极小改动即可复用:

自定义MD4类实现代码

using System.Security.Cryptography;

public abstract class MD4 : HashAlgorithm
{
    protected MD4()
    {
        HashSizeValue = 128;
    }

    public static new MD4 Create()
    {
        return new MD4Implementation();
    }

    private class MD4Implementation : MD4
    {
        private uint[] _state;
        private byte[] _buffer;
        private long _count;
        private const int BlockSize = 64;

        public MD4Implementation()
        {
            Initialize();
        }

        public override void Initialize()
        {
            _state = new uint[] { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
            _buffer = new byte[BlockSize];
            _count = 0;
        }

        protected override void HashCore(byte[] array, int ibStart, int cbSize)
        {
            int bufferIndex = (int)(_count & 0x3F);
            _count += cbSize;
            int partLength = BlockSize - bufferIndex;
            int i = 0;

            if (cbSize >= partLength)
            {
                Buffer.BlockCopy(array, ibStart, _buffer, bufferIndex, partLength);
                TransformBlock(_buffer, 0);
                for (i = partLength; i + BlockSize <= cbSize; i += BlockSize)
                {
                    TransformBlock(array, ibStart + i);
                }
                bufferIndex = 0;
            }

            Buffer.BlockCopy(array, ibStart + i, _buffer, bufferIndex, cbSize - i);
        }

        protected override byte[] HashFinal()
        {
            byte[] padding = GetPadding();
            HashCore(padding, 0, padding.Length);

            byte[] hash = new byte[16];
            for (int i = 0; i < 4; i++)
            {
                BitConverter.GetBytes(_state[i]).CopyTo(hash, i * 4);
            }
            return hash;
        }

        private void TransformBlock(byte[] block, int offset = 0)
        {
            uint a = _state[0], b = _state[1], c = _state[2], d = _state[3];
            uint[] x = new uint[16];

            for (int i = 0; i < 16; i++)
            {
                x[i] = BitConverter.ToUInt32(block, offset + i * 4);
            }

            // 第一轮计算
            a = RotateLeft(a + F(b, c, d) + x[0], 3);
            d = RotateLeft(d + F(a, b, c) + x[1], 7);
            c = RotateLeft(c + F(d, a, b) + x[2], 11);
            b = RotateLeft(b + F(c, d, a) + x[3], 19);

            a = RotateLeft(a + F(b, c, d) + x[4], 3);
            d = RotateLeft(d + F(a, b, c) + x[5], 7);
            c = RotateLeft(c + F(d, a, b) + x[6], 11);
            b = RotateLeft(b + F(c, d, a) + x[7], 19);

            a = RotateLeft(a + F(b, c, d) + x[8], 3);
            d = RotateLeft(d + F(a, b, c) + x[9], 7);
            c = RotateLeft(c + F(d, a, b) + x[10], 11);
            b = RotateLeft(b + F(c, d, a) + x[11], 19);

            a = RotateLeft(a + F(b, c, d) + x[12], 3);
            d = RotateLeft(d + F(a, b, c) + x[13], 7);
            c = RotateLeft(c + F(d, a, b) + x[14], 11);
            b = RotateLeft(b + F(c, d, a) + x[15], 19);

            // 第二轮计算
            a = RotateLeft(a + G(b, c, d) + x[0] + 0x5A827999, 3);
            d = RotateLeft(d + G(a, b, c) + x[4] + 0x5A827999, 5);
            c = RotateLeft(c + G(d, a, b) + x[8] + 0x5A827999, 9);
            b = RotateLeft(b + G(c, d, a) + x[12] + 0x5A827999, 13);

            a = RotateLeft(a + G(b, c, d) + x[1] + 0x5A827999, 3);
            d = RotateLeft(d + G(a, b, c) + x[5] + 0x5A827999, 5);
            c = RotateLeft(c + G(d, a, b) + x[9] + 0x5A827999, 9);
            b = RotateLeft(b + G(c, d, a) + x[13] + 0x5A827999, 13);

            a = RotateLeft(a + G(b, c, d) + x[2] + 0x5A827999, 3);
            d = RotateLeft(d + G(a, b, c) + x[6] + 0x5A827999, 5);
            c = RotateLeft(c + G(d, a, b) + x[10] + 0x5A827999, 9);
            b = RotateLeft(b + G(c, d, a) + x[14] + 0x5A827999, 13);

            a = RotateLeft(a + G(b, c, d) + x[3] + 0x5A827999, 3);
            d = RotateLeft(d + G(a, b, c) + x[7] + 0x5A827999, 5);
            c = RotateLeft(c + G(d, a, b) + x[11] + 0x5A827999, 9);
            b = RotateLeft(b + G(c, d, a) + x[15] + 0x5A827999, 13);

            // 第三轮计算
            a = RotateLeft(a + H(b, c, d) + x[0] + 0x6ED9EBA1, 3);
            d = RotateLeft(d + H(a, b, c) + x[8] + 0x6ED9EBA1, 9);
            c = RotateLeft(c + H(d, a, b) + x[4] + 0x6ED9EBA1, 11);
            b = RotateLeft(b + H(c, d, a) + x[12] + 0x6ED9EBA1, 15);

            a = RotateLeft(a + H(b, c, d) + x[2] + 0x6ED9EBA1, 3);
            d = RotateLeft(d + H(a, b, c) + x[10] + 0x6ED9EBA1, 9);
            c = RotateLeft(c + H(d, a, b) + x[6] + 0x6ED9EBA1, 11);
            b = RotateLeft(b + H(c, d, a) + x[14] + 0x6ED9EBA1, 15);

            a = RotateLeft(a + H(b, c, d) + x[1] + 0x6ED9EBA1, 3);
            d = RotateLeft(d + H(a, b, c) + x[9] + 0x6ED9EBA1, 9);
            c = RotateLeft(c + H(d, a, b) + x[5] + 0x6ED9EBA1, 11);
            b = RotateLeft(b + H(c, d, a) + x[13] + 0x6ED9EBA1, 15);

            a = RotateLeft(a + H(b, c, d) + x[3] + 0x6ED9EBA1, 3);
            d = RotateLeft(d + H(a, b, c) + x[11] + 0x6ED9EBA1, 9);
            c = RotateLeft(c + H(d, a, b) + x[7] + 0x6ED9EBA1, 11);
            b = RotateLeft(b + H(c, d, a) + x[15] + 0x6ED9EBA1, 15);

            _state[0] += a;
            _state[1] += b;
            _state[2] += c;
            _state[3] += d;
        }

        private byte[] GetPadding()
        {
            int bufferIndex = (int)(_count & 0x3F);
            int paddingLength = bufferIndex < 56 ? 56 - bufferIndex : 120 - bufferIndex;

            byte[] padding = new byte[paddingLength + 8];
            padding[0] = 0x80;

            long bitLength = _count * 8;
            BitConverter.GetBytes(bitLength).CopyTo(padding, paddingLength);

            return padding;
        }

        private static uint F(uint x, uint y, uint z) => (x & y) | (~x & z);
        private static uint G(uint x, uint y, uint z) => (x & y) | (x & z) | (y & z);
        private static uint H(uint x, uint y, uint z) => x ^ y ^ z;
        private static uint RotateLeft(uint x, int n) => (x << n) | (x >> (32 - n));
    }
}

调用代码(和原有MD5逻辑完全兼容)

using (var md4 = MD4.Create())
{
    using (var stream = File.OpenRead(fileName))
    {
        return BitConverter.ToString(md4.ComputeHash(stream)).Replace("-", string.Empty);
    }
}

该实现支持跨平台运行,适配.NET Framework、.NET Core、.NET 5+所有主流版本。


方案2:Windows平台调用系统API实现

如果仅需要在Windows环境运行,可以直接调用Windows内置的BCrypt加密接口实现MD4,不需要自行维护算法代码,稳定性更高。


注意:MD4算法在1995年就被发现存在碰撞漏洞,目前已经完全不适合用于密码存储、数据完整性校验等安全相关场景,仅可用于对旧系统的兼容需求。

内容的提问来源于stack exchange,提问作者user15519784

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 17:48:01