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
相关产品推荐
相关产品推荐

