【问题标题】:Using Rijndael to encrypt/decrypt files使用 Rijndael 加密/解密文件
【发布时间】:2011-06-23 21:24:41
【问题描述】:

我需要传输 xml 文件并且它们需要被加密。我发现一些例子认为我很接近,但是当我解密文件时,我最终得到了尾随的垃圾字符。有一些关于这个的帖子,但我还没有看到任何可以帮助的帖子。这是加解密代码。

private void EncryptFile(string inputFile, string outputFile, string key) {
    try {
        byte[] keyBytes;
        keyBytes = Encoding.Unicode.GetBytes(key);

        Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(key, keyBytes);

        RijndaelManaged rijndaelCSP = new RijndaelManaged();
        rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
        rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);

        ICryptoTransform encryptor = rijndaelCSP.CreateEncryptor();

        FileStream inputFileStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read);

        byte[] inputFileData = new byte[(int)inputFileStream.Length];
        inputFileStream.Read(inputFileData, 0, (int)inputFileStream.Length);

        FileStream outputFileStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write);

        CryptoStream encryptStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write);
        encryptStream.Write(inputFileData, 0, (int)inputFileStream.Length);
        encryptStream.FlushFinalBlock();

        rijndaelCSP.Clear();
        encryptStream.Close();
        inputFileStream.Close();
        outputFileStream.Close();
    }
    catch (Exception ex) {
        MessageBox.Show(ex.Message, "Encryption Failed!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }

    MessageBox.Show("File Encryption Complete!");

}

private void DecryptFile(string inputFile, string outputFile, string key) {
    try {
        byte[] keyBytes = Encoding.Unicode.GetBytes(key);

        Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(key, keyBytes);

        RijndaelManaged rijndaelCSP = new RijndaelManaged();
        rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
        rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);
        ICryptoTransform decryptor = rijndaelCSP.CreateDecryptor();

        FileStream inputFileStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read);

        CryptoStream decryptStream = new CryptoStream(inputFileStream, decryptor, CryptoStreamMode.Read);

        byte[] inputFileData = new byte[(int)inputFileStream.Length];
        decryptStream.Read(inputFileData, 0, (int)inputFileStream.Length);

        FileStream outputFileStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
        outputFileStream.Write(inputFileData, 0, inputFileData.Length);
        outputFileStream.Flush();

        rijndaelCSP.Clear();

        decryptStream.Close();
        inputFileStream.Close();
        outputFileStream.Close();
    }
    catch (Exception ex) {
        MessageBox.Show(ex.Message, "Decryption Failed!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }

    MessageBox.Show("File Decryption Complete!");
}

我结束了

<?xml version="1.0" encoding="UTF-8"?>
<transaction>
  <header>
    <qOrderNumber></qOrderNumber>
    <qRequestDate></qRequestDate>
    <testOrder></testOrder>
    <qCustomerNumber></qCustomerNumber>
    <transactionStatus></transactionStatus>
  </header>
  <lines>
    <line>
      <productID></productID>
      <serialNumber></serialNumber>
    </line>
    <line> 
      <productID></productID>
      <serialNumber></serialNumber>
    </line>
  </lines>
</transaction>NULNULNULNULNULNUL

【问题讨论】:

    标签: c# encryption rijndaelmanaged


    【解决方案1】:

    解密时,请注意 CryptoStream.Read 调用的返回值。它告诉您字节数组中解密数据的长度(由于填充,通常与加密数据的长度不匹配)。尝试在您的解密函数中使用以下内容:

    int decrypt_length = decryptStream.Read(inputFileData, 0, (int)inputFileStream.Length);
    FileStream outputFileStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
    outputFileStream.Write(inputFileData, 0, decrypt_length);
    

    【讨论】:

      【解决方案2】:

      RijndaelManaged 对象上,将Padding 属性设置为PaddingMode.ANSIX923PaddingMode.ISO10126

      这些空字节被添加以填充最终的加密块。默认情况下用零填充,这意味着没有说明数据的实际长度。其他填充模式在最后一个字节中包含一个长度,以便解密后可以去除填充。

      将加密和解密例程中的填充属性设置为相同的值。

       rijndaelCSP.Padding = PaddingMode.ANSIX923;
      

      如果它知道会发生什么,那么解密流将自动删除填充,因此无需进一步更改。

      更新

      从您的代码来看,您写入输出文件的字节数似乎等于从输入文件中读取的字节数。

      byte[] inputFileData = new byte[(int)inputFileStream.Length];
      decryptStream.Read(inputFileData, 0, (int)inputFileStream.Length);
      

      由于输入中的填充,解密过程不会完全填满inputFileData 数组。

      然后输出流将写出缓冲区的整个长度,即使它没有完全填满。

      outputFileStream.Write(inputFileData, 0, inputFileData.Length);
      

      这是你的空值的来源。

      您可能希望更改进行加密和解密的方式,使其不再使用固定长度的缓冲区。或者,您可以在开头存储加密数据的长度,并且只写入与该长度相对应的字节数。

      【讨论】:

      • +1 我过去遇到过这种情况。我相信这是我用来修复它的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多