我正在创建一个需要签名的加密文件格式。为此,我需要计算我写入流中的内容的哈希码。
在.Net框架中有许多可用的哈希算法,它们可以使用并且工作正常,但是这需要我对流进行三遍处理。
byte[] content = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
using (Stream fileStream = File.Open("myfile.bin", FileMode.Create))
{
//Write content
fileStream.Write(content, 0, content.Length);
}
byte[] hashValue = null;
using (Stream fileStream = File.Open("myfile.bin", FileMode.Open))
{
HashAlgorithm hash = SHA256.Create();
hashValue = hash.ComputeHash(fileStream);
}
using (Stream fileStream = File.Open("myfile.bin", FileMode.Append))
{
fileStream.Write(hashValue, 0, hashValue.Length);
}
如果加密到文件是可以的,但如果加密到网络目标,则字节将不再可用。
因此,基本上我只需要处理数据一次。在CodeProject上有一篇文章,实现了CRC32作为流,每当写入数据时都会计算CRC32码。
类似于:
byte[] content = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
using (FileStream fileStream = File.Create("myfile.bin"))
using (Stream crcStream = new CRCStream(fileStream)) //Takes a base stream
{
//Write content
crcStream.Write(content, 0, content.Length);
//Write checksum
fileStream.Write(crcStream.WriteCRC, 0, 4);
}
显然,CRC32并不是哈希算法,但是如果有像HashStream这样的东西,它接受一个HashAlgorithm,每次调用写入/读取时都会更新哈希值,那就太好了。
类似于:
byte[] content = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
HashAlgorithm hashAlgo = SHA256.Create();
using (FileStream fileStream = File.Create("myfile.bin"))
using (HashStream hashStream = new HashStream(hashAlgo, fileStream))
{
//Write content to HashStream
hashStream.Write(content, 0, content.Length);
//Write checksum
fileStream.Write(hashStream.HashValue, 0, hashAlgo.HashSize / 8);
}
阅读文件应该以相似的方式进行,因此当您读取文件时(不包括哈希),已经计算出已读内容的哈希值。
是否可以使用.net框架现有组件构建类似的东西?
编辑:
谢谢Peter!我不知道CryptoStream可以接受HashAlgorithm。因此,要同时加密和哈希,我可以像这样做:
byte[] content = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
SymmetricAlgorithm cryptoSymetric = Aes.Create();
HashAlgorithm cryptoHash = SHA256.Create();
using (FileStream file = new FileStream("Crypto.bin", FileMode.Create, FileAccess.Write))
using (CryptoStream hashStream = new CryptoStream(file, cryptoHash, CryptoStreamMode.Write))
using (CryptoStream cryptStream = new CryptoStream(hashStream, cryptoSymetric.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptStream.Write(content, 0, content.Length);
cryptStream.FlushFinalBlock();
byte[] hashValue = cryptoHash.Hash;
file.Write(hashValue, 0, hashValue.Length);
}
cryptStream.FlushFinalBlock()
之后调用hashStream.FlushFinalBlock()
。 - Peter TaylorFlushFinalBlock
。文档中指出:“调用Close
方法将调用FlushFinalBlock
。” 因此,在using
结束后,cryptoHash.Hash
将包含哈希值。 - Dave