Rijndael填充或长度无效 [英] Rijndael padding or length is invalid
问题描述
我正在尝试使用Rijndael或Aes和下面的代码对字符串进行加密/解密。
I am trying to encrypt/decrypt a string using eith Rijndael or Aes and the code below.
public class Crypto
{
private const string defaultVector = "asdfg123456789";
private const CipherMode cipherMode = CipherMode.CBC;
//Have tried PaddingMode.ISO10126, PaddingMode.None, and PaddingMode.PKCS7
private const PaddingMode paddingMode = PaddingMode.ISO10126;
private const int iterations = 2;
private static Rijndael GetCrypto(string passphrase)
{
var crypt = Rijndael.Create();
crypt.Mode = cipherMode;
crypt.Padding = paddingMode;
crypt.BlockSize = 256;
crypt.KeySize = 256;
crypt.Key =
new Rfc2898DeriveBytes(passphrase, Encoding.Unicode.GetBytes(defaultVector), iterations).GetBytes(32);
crypt.IV = new Rfc2898DeriveBytes(passphrase, Encoding.Unicode.GetBytes(defaultVector), iterations).GetBytes(32);
return crypt;
}
public static string Encrypt(string plainText, string passphrase)
{
byte[] clearData = Encoding.Unicode.GetBytes(plainText);
byte[] encryptedData;
var crypt = GetCrypto(passphrase);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, crypt.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearData, 0, clearData.Length);
//cs.FlushFinalBlock(); //Have tried this active and commented with no change.
}
encryptedData = ms.ToArray();
}
//Changed per Xint0's answer.
return Convert.ToBase64String(encryptedData);
}
public static string Decrypt(string cipherText, string passphrase)
{
//Changed per Xint0's answer.
byte[] encryptedData = Convert.FromBase64String(cipherText);
byte[] clearData;
var crypt = GetCrypto(passphrase);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, crypt.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(encryptedData, 0, encryptedData.Length);
//I have tried adding a cs.FlushFinalBlock(); here as well.
}
clearData = ms.ToArray();
}
return Encoding.Unicode.GetString(clearData);
}
}
//编辑:我已经对Unicode调用进行了更改根据下面的Xint0的答案转换为Convert.ToBase64String。
//Edits: I have changed over the Unicode calls to Convert.ToBase64String per Xint0's answer below.
在cs.Write in Decrypt方法上,我收到以下错误:填充无效,无法删除。
On the cs.Write in Decrypt method, I am getting the error that "Padding is invalid and cannot be removed."
我尝试将填充设置为PaddingMode.None,但得到要加密的数据长度无效。
I have tried setting the padding to PaddingMode.None but I get "Length of the data to encrypt is invalid." on the cs.Write in the Encrypt method.
我已经看过这些了,但是他们说的什么似乎都不起作用。
I've looked at these and nothing they've said seems to work.
堆栈跟踪显示System.Security.CryptographicException来自RijndaelManagedTransform.DecryptData(Byte [] inputBuffer,Int32 inputOffset,Int32 inputCount,Byte []& outputBuffer,Int32 outputOffset,PaddingMode paddingMode,布尔值fLast)。
Stack trace shows System.Security.CryptographicException is coming from RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast).
推荐答案
我看到两个问题:
-
在调用
ms.ToArray()
之前,您并没有刷新和关闭流。更改为:
You are not flushing and closing the streams before calling
ms.ToArray()
. Change it to:
...
using (var cs = new CryptoStream(ms, crypt.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearData, 0, clearData.Length);
cs.FlushFinalBlock();
cs.Close();
}
ms.Close();
encryptedData = ms.ToArray();
...
在加密
得到的字节数组 encryptedData
是否一个Unicode字符串,但是您正在使用Unicode编码器从字节数组中获取字符串。而不是使用 Encrypt
和 System.Convert中的
。 System.Convert.ToBase64String()
。 解密
中的FromBase64String()
In Encrypt
the resulting byte array encryptedData
is NOT a Unicode string, yet you are using a Unicode encoder to get a string from the byte array. Instead of that use System.Convert.ToBase64String()
in Encrypt
and System.Convert.FromBase64String()
in Decrypt
.
在加密
中执行
return System.Convert.ToBase64String(encryptedData);
在解密
中执行:
byte[] encryptedData = System.Convert.FromBase64String(cipherText);
编辑
最大的问题是 Encrypt
的返回值。加密Unicode字符串的字节表示形式的结果是 NOT 的Unicode字符串的字节表示形式。您不应将 encryptedData
的值与 Encoding.Unicode.GetString()
一起使用,以获取加密后的字符串表示形式数据。使用 System.Convert.ToBase64String()
获取加密数据的字符串表示形式。请参阅编码类 MSDN文档中的备注部分。
The biggest problem is the return value of Encrypt
. The result of encrypting the byte representation of a Unicode string is NOT a byte representation of a Unicode string. You should not use the value of encryptedData
with Encoding.Unicode.GetString()
to get a string representation of the encrypted data. Use System.Convert.ToBase64String()
to get a string representation of the encrypted data. Please see the Remarks section in the Encoding Class MSDN Documentation.
编辑2
请注意,如果您要与AES互操作,Rijndael并非完全是AES块大小应始终为128位,与密钥大小无关。有关详细信息,您可以阅读此处。
Note that Rijndael is not exactly AES, if you are interoperating with AES the block size should always be 128-bits, independent of the key size. For details you can read about it here.
这篇关于Rijndael填充或长度无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!