使用 AES 加密和二进制文件流,读取 + 写入
本文关键字:读取 写入 二进制文件 AES 加密 使用 | 更新日期: 2023-09-27 18:31:17
由于SO,我破解了一些其他代码。 将加密数据写入磁盘时没有收到任何错误,但是在读回数据时,RijndaelManaged 类中出现"边界索引"错误。
这是我用来创建用 AES 加密包装的读写流的类(这是我的实际盐,但我一定会在发布前更改它):
public class Crypto
{
private static byte[] _salt = Encoding.ASCII.GetBytes("42kb$2fs$@#GE$^%gdhf;!M807c5o666");
public static Stream CreateCryptoStreamAESWrite(string sharedSecret, Stream stream)
{
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);
// Create a RijndaelManaged object
RijndaelManaged aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
// Create a decryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// prepend the IV
stream.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
stream.Write(aesAlg.IV, 0, aesAlg.IV.Length);
CryptoStream csEncrypt = new CryptoStream(stream, encryptor, CryptoStreamMode.Write);
return csEncrypt;
}
public static Stream CreateCryptoStreamAESRead(string sharedSecret, Stream stream)
{
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);
// Create a RijndaelManaged object
// with the specified key and IV.
RijndaelManaged aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
// Get the initialization vector from the encrypted stream
aesAlg.IV = ReadByteArray(stream);
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
CryptoStream csDecrypt = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);
return csDecrypt;
}
private static byte[] ReadByteArray(Stream s)
{
byte[] rawLength = new byte[sizeof(int)];
if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length)
throw new SystemException("Stream did not contain properly formatted byte array");
byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
if (s.Read(buffer, 0, buffer.Length) != buffer.Length)
throw new SystemException("Did not read byte array properly");
return buffer;
}
}
这是我编写的一些测试使用代码:
FileStream fs = new FileStream("c:''temp''test.dat", FileMode.Create, FileAccess.ReadWrite, FileShare.None);
Stream cs = Crypto.CreateCryptoStreamAESWrite("test", fs);
BinaryWriter bw = new BinaryWriter(cs);
bw.Write("test");
cs.Flush();
fs.Close();
fs = new FileStream("c:''temp''test.dat", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
cs = Crypto.CreateCryptoStreamAESRead("test", fs);
BinaryReader br = new BinaryReader(cs);
string test = br.ReadString();
if (test != "test")
throw new Exception("Your Kungfu is not good!");
fs.Close();
这是我在 br 上遇到的错误。ReadString() 行:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 out
putOffset, PaddingMode paddingMode, Boolean fLast)
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(
Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Stream.ReadByte()
at System.IO.BinaryReader.ReadByte()
看起来我需要在我的加密流上调用Close
。 我打电话给Flush
,但不是关闭。 我替换了cs。Flush() with cs.关闭(),现在它正在工作。
希望有人至少可以从我问题中的示例代码中学习,尽管我想有一种更简单的方法来读取/写入 AES 加密流(到/从文件或其他方式)。