网站建设需求材料,wordpress 4.8 php版本,网站建设公司找哪里,珠海停车app前言有网友在交流群中询问#xff0c;文件 MD5 是全部读取到内存后计算出来的#xff0c;还是拿到流就可以计算出来了#xff1a;原理上来说#xff0c;MD5 需要对全部内容做运算#xff0c;所以应该是获取所有内容后再计算的。但是#xff0c;如果全部读取到内存后再计算… 前言有网友在交流群中询问文件 MD5 是全部读取到内存后计算出来的还是拿到流就可以计算出来了原理上来说MD5 需要对全部内容做运算所以应该是获取所有内容后再计算的。但是如果全部读取到内存后再计算又不太现实比如读取一个 1T 大小的文件。Talk Is Cheap. Show Me The Code.让我们来看看 .NET 中具体是如何实现的。分析代码.NET 下计算哈希的方法是ComputeHash:public byte[] ComputeHash(Stream inputStream)
{if (_disposed)throw new ObjectDisposedException(null);// Use ArrayPool.Shared instead of CryptoPool because the array is passed out.byte[] buffer ArrayPoolbyte.Shared.Rent(4096);int bytesRead;int clearLimit 0;while ((bytesRead inputStream.Read(buffer, 0, buffer.Length)) 0){if (bytesRead clearLimit){clearLimit bytesRead;}HashCore(buffer, 0, bytesRead);}CryptographicOperations.ZeroMemory(buffer.AsSpan(0, clearLimit));ArrayPoolbyte.Shared.Return(buffer, clearArray: false);return CaptureHashCodeAndReinitialize();
}通过while ((bytesRead inputStream.Read(buffer, 0, buffer.Length)) 0)可以判断出确实是获取了所有内容。但是是分段获取的每次最多只读取 4096 字节byte[] buffer ArrayPoolbyte.Shared.Rent(4096);。关键是分段读取出的字节会合并放到内存中去计算哈希吗HashCore分段读取出的字节是交由HashCore方法处理的。它的具体实现代码在LiteHash结构中public void Append(ReadOnlySpanbyte data)
{if (data.IsEmpty){return;}Check(Interop.Crypto.EvpDigestUpdate(_ctx, data, data.Length));
}而调用的 EvpDigestUpdate 是底层 API看不到源码internal const string CryptoNative libSystem.Security.Cryptography.Native.OpenSsl;[LibraryImport(Libraries.CryptoNative, EntryPoint CryptoNative_EvpDigestUpdate)]
private static partial int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ref byte d, int cnt);在 OpenSSL 官网上找到了这个 API 的描述将d处的数据字节哈希到摘要上下文ctx中。可以在同一ctx上多次调用此函数以对增加的数据进行哈希处理。也就是说计算文件哈希实际经过了多次处理。那如何得到最后的哈希值呢CaptureHashCodeAndReinitializeComputeHash最后调用 CaptureHashCodeAndReinitialize 方法返回哈希值。它的具体实现代码也在LiteHash结构中调用了EvpDigestFinalEx APIpublic int Finalize(Spanbyte destination)
{Debug.Assert(destination.Length _hashSizeInBytes);uint length (uint)destination.Length;Check(Interop.Crypto.EvpDigestFinalEx(_ctx, ref MemoryMarshal.GetReference(destination), ref length));Debug.Assert(length _hashSizeInBytes);return _hashSizeInBytes;
}[LibraryImport(Libraries.CryptoNative, EntryPoint CryptoNative_EvpDigestFinalEx)]
internal static partial int EvpDigestFinalEx(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s);从ctx中检索摘要值并将其放在md中。如果s参数不是 NULL则写入的数据字节数即摘要的长度将写入s处。结论通过以上分析可以得出文件 MD5 哈希计算流程如下不过群里又有网友说不要用 MD5这又是为什么呢我们下回分解添加微信号【MyIO666】邀你加入技术交流群