我正在尝试创建非常强大的Rijndael 256字符串加密方法,可以将其用于密码,但是在读取Padding is invalid and cannot be removed.
并获取解密的字符串时,出现错误消息CryptoStream
。这是我的加密和解密方法:
private string AES256EncryptString(string key, string plainText)
{
try
{
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.KeySize = 256;
rijndael.BlockSize = 128;
rijndael.Key = Encoding.UTF8.GetBytes(key);
rijndael.GenerateIV();
rijndael.Mode = CipherMode.CBC;
rijndael.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);
MemoryStream memoryStream = new MemoryStream();
memoryStream.Write(rijndael.IV, 0, rijndael.IV.Length);
CryptoStream crypoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
crypoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
crypoStream.FlushFinalBlock();
crypoStream.Close();
byte[] encryptedBytes = memoryStream.ToArray();
memoryStream.Close();
string encryptedText = Convert.ToBase64String(encryptedBytes);
return encryptedText;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return null;
}
}
private string AES256DecryptString(string key, string encryptedText)
{
try
{
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.KeySize = 256;
rijndael.BlockSize = 128;
rijndael.Key = Encoding.UTF8.GetBytes(key);
byte[] encryptedTextBytes = Encoding.UTF8.GetBytes(encryptedText);
byte[] iv = new byte[16];
Array.Copy(encryptedTextBytes, iv, iv.Length);
rijndael.IV = iv;
rijndael.Mode = CipherMode.CBC;
rijndael.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);
MemoryStream memoryStream = new MemoryStream();
byte[] encryptedTextWithoutIVBytes = new byte[encryptedTextBytes.Length - iv.Length];
Array.Copy(encryptedTextBytes, 16, encryptedTextWithoutIVBytes, 0, encryptedTextWithoutIVBytes.Length);
memoryStream.Write(encryptedTextWithoutIVBytes, 0, encryptedTextWithoutIVBytes.Length);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
StreamReader streamReader = new StreamReader(cryptoStream);
string decryptedText = streamReader.ReadToEnd();
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
memoryStream.Close();
return decryptedText;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return null;
}
}
您可以看到,在添加加密位之前,我在加密字符串之前添加了初始化向量,因为我知道IV应该是随机的,并且我已经看到这是一个很好的使用策略。我确保在解密之前先删除IV。
有没有一种方法可以解决此问题而无需更改填充模式(我已经知道PKCS7填充非常安全)?
答案 0 :(得分:1)
问题:
对于密码和类似的低熵密钥,应使用适当的基于密码的KDF。 .NET具有Rfc2898DeriveBytes
(PBKDF2)类,使此操作相对容易。
您不是在解密器中使用base64解码密文。代替
byte[] encryptedTextBytes = Encoding.UTF8.GetBytes(encryptedText);
您应该拥有
byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
用密文字节填充MemoryStream之后,需要重置MemoryStream的位置。之后
memoryStream.Write(encryptedTextWithoutIVBytes, 0, encryptedTextWithoutIVBytes.Length);
您需要插入
memoryStream.Seek(0, SeekOrigin.Begin);