之前我问question有关SHA1 + MD5的组合,但之后我理解计算SHA1,然后延迟文件的MD5并不比SHA256快。 在我的情况下,一个4.6 GB的文件大约需要10分钟,在Linux系统中使用默认的实现SHA256和(C#MONO)。
public static string GetChecksum(string file)
{
using (FileStream stream = File.OpenRead(file))
{
var sha = new SHA256Managed();
byte[] checksum = sha.ComputeHash(stream);
return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}
然后我读了this topic并以某种方式改变我的代码:
public static string GetChecksumBuffered(Stream stream)
{
using (var bufferedStream = new BufferedStream(stream, 1024 * 32))
{
var sha = new SHA256Managed();
byte[] checksum = sha.ComputeHash(bufferedStream);
return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}
但它并没有这样的感情,需要大约9分钟。
然后我尝试在Linux中通过sha256sum
命令测试我的文件到同一个文件,它需要大约28秒,上面的代码和Linux命令都给出相同的结果!
有人建议我阅读Hash Code和Checksum之间的差异,然后我到this topic来解释差异。
我的问题是:
上述代码与Linux sha256sum
之间的差异是什么原因?
上面的代码是做什么的? (我的意思是它是哈希码计算还是校验和计算?因为如果你搜索一下文件的哈希码和C#中文件的校验和,它们都会达到上面的代码。)
即使SHA256是抗冲突的,是否还有针对sha256sum
的动机攻击?
如何在C#中以sha256sum
的速度实现我的实施?
答案 0 :(得分:4)
最好的猜测是在File.Read操作的单声道实现中有一些额外的缓冲。最近看了一个大文件的校验和,似乎在一个不错的规格windows机器上,如果一切顺利运行,你应该期望每Gb大约6秒。奇怪的是,在多个基准测试中已经报道SHA-512明显比SHA-256快(见下面的3)。另一种可能性是问题不在于分配数据,而是在读取时处理字节。您可以在单个数组上使用TransformBlock(和TransformFinalBlock),而不是一次性读取流 - 我不知道这是否有效,但需要进行调查。
哈希码和校验和之间的区别是(几乎)语义。他们都计算出一个较短的魔法'数字对于输入中的数据来说是相当独特的,但如果你有4.6GB的输入和64B的输出,那么相当'有点受限。校验和是不安全的,通过一些工作,你可以从足够的输出中找出输入,从输出到输入的后退工作以及各种不安全的东西。加密哈希需要更长的时间来计算,但是改变输入中的一个位将从根本上改变输出,并且对于良好的哈希(例如SHA-512),没有已知的方法从输出返回到输入。
MD5是易碎的,如果需要,您可以在PC上制作输入以产生任何给定的输出。 SHA256(可能)仍然安全,但不会在几年内完成 - 如果你的项目有几十年的寿命,那么假设你需要改变它。 SHA512没有已知的攻击,可能已经持续了很长一段时间,而且由于它比SHA256更快,我还是推荐它。基准测试显示,计算SHA512所需的时间比MD5大3倍,因此如果您的速度问题可以解决,那么就可以了。
不知道,除了上面提到的那些,你做得对。
稍微阅读https://crypto.stackexchange.com/questions/26336/sha512-faster-than-sha256
编辑以回复评论中的问题
校验和的目的是允许您检查文件在您最初编写文件之间是否已更改,以及您使用文件的时间。它通过在SHA512的情况下产生512位的小值来实现这一点,其中原始文件的每个位至少对输出值有贡献。哈希码的目的是相同的,并且通过对文件进行仔细管理的更改,其他人真的很难获得相同的输出值。前提是如果校验和在开始时是相同的,当你检查它时,文件是相同的,如果它们不同,那么文件肯定会改变。你上面所做的就是通过一个algorthm来提供整个文件,这个算法可以滚动,折叠和旋转它读取的位以产生小值。
例如,在我正在编写的应用程序中,我需要知道任何大小的文件的部分是否已经改变,所以我将文件拆分为16K块,取每个块的SHA-512哈希并将其存储在另一个驱动器上的单独数据库中。当我来看看文件是否已经改变时,我重现每个块的哈希并将其与原始块进行比较。由于我使用SHA-512文件更改的机会但是散列保持不变是不可想象的小,所以我可以自信地检测100 GB数据的变化,同时只存储几MB的哈希值数据库。我在获取哈希的同时复制文件,并且该过程完全是磁盘绑定的;将文件传输到USB驱动器大约需要5分钟,其中10秒可能与散列有关。
缺少存储哈希的磁盘空间是我无法在帖子中解决的问题...买一个usb棒?
答案 1 :(得分:3)
晚会晚了,但是由于没有答案,我想指出:
SHA256Managed
是System.Security.Cryptography.HashAlgorithm
类的实现,与读取操作有关的所有功能都在继承的代码中处理。
HashAlgorithm.ComputeHash(Stream)
使用固定的4096字节缓冲区从流中读取数据。结果,使用BufferedStream
进行此调用不会带来太大的区别。
HashAlgorithm.ComputeHash(byte[])
在整个字节数组上运行,但是每次调用后都会重置内部状态,因此不能用于对缓冲的流进行增量哈希。
您最好的选择是使用针对您的用例进行了优化的第三方实现。
答案 2 :(得分:2)
public string SHA256CheckSum(string filePath)
{
using (SHA256 SHA256 = SHA256Managed.Create())
{
using (FileStream fileStream = File.OpenRead(filePath))
return Convert.ToBase64String(SHA256.ComputeHash(fileStream));
}
}