【问题标题】:Using AES encryption with binary FileStream, read + write使用带有二进制 FileStream 的 AES 加密,读 + 写
【发布时间】:2013-09-15 02:32:19
【问题描述】:

感谢 SO,我已经破解了一些我发现的其他代码。将加密数据写入磁盘时,我没有收到任何错误,但在读取数据时,我在 RijndaelManaged 类中收到“边界索引”错误。

这是我用来创建使用 AES 加密封装的读写流的类(这是我的实际 salt,但我一定会在发布前更改它):

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()

【问题讨论】:

    标签: c# .net encryption cryptoapi


    【解决方案1】:

    看来我需要在我的 Crypto 流上调用 Close。我打电话给Flush,但不是Close。我用 cs.Close() 替换了 cs.Flush(),现在它可以工作了。

    希望有人至少可以从我的问题中的示例代码中学习,尽管我想有一种更简单的方法来读取/写入 AES 加密流(到/从文件或其他方式)。

    【讨论】:

    • 您不必关闭 CryptoStream。 CryptoStream 具有加密时需要的 FlushFinalBlock 方法。这是通过 CryptoStream 发送完所有明文后调用的方法。当您调用 Close 时,CryptoStream 会自动调用 FlushFinalBlock。如果你可以安排你的工作发生在 using() 块内,这会自动发生。
    猜你喜欢
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 1970-01-01
    相关资源
    最近更新 更多