В настоящее время я создаю зашифрованный формат файла, который должен быть подписан. Для этого мне нужно рассчитать хэш-код содержимого, которое я написал в поток.
В рамках .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. HashStream будет обновлять значение хэша каждый раз, когда вызывается запись/чтение.
Что-то вроде:
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 framework?
Edit:
Спасибо, Питер! Я не знал, что 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);
}