在使用块中使用PasswordDeriveBytes类(因为它实现了Idisposable,它会处理它)会在第二次使用该类时产生问题.这是代码:
public class AES { protected static CryptoData localCryptoData; static AES() { localCryptoData = new CryptoData(); } public static string Encrypt(CryptoData cryptoData) { using (PasswordDeriveBytes pass = new PasswordDeriveBytes(cryptoData.Password,cryptoData.Salt,"SHA1",2)) using (RijndaelManaged symmetricKey = new RijndaelManaged()) { byte[] keyBytes = pass.GetBytes(cryptoData.KeySize / 8); symmetricKey.Padding = PaddingMode.PKCS7; symmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes,cryptoData.InitVector)) using (MemoryStream memoryStream = new MemoryStream()) using (CryptoStream cryptoStream = new CryptoStream(memoryStream,encryptor,CryptoStreamMode.Write)) { cryptoStream.Write(cryptoData.ByteText,cryptoData.ByteText.Length); cryptoStream.FlushFinalBlock(); return Convert.ToBase64String(memoryStream.ToArray()); } } } public static string Decrypt(CryptoData cryptoData) { using (PasswordDeriveBytes pass = new PasswordDeriveBytes(cryptoData.Password,2)) using (RijndaelManaged symmetricKey = new RijndaelManaged()) { byte[] cipherTextBytes = Convert.FromBase64String(cryptoData.Text); byte[] keyBytes = pass.GetBytes(cryptoData.KeySize / 8); symmetricKey.Padding = PaddingMode.PKCS7; symmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes,cryptoData.InitVector)) using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) using (CryptoStream cryptoStream = new CryptoStream(memoryStream,decryptor,CryptoStreamMode.Read)) { byte[] textBytes = new byte[cipherTextBytes.Length]; int count = cryptoStream.Read(textBytes,textBytes.Length); //throws CryptographicException - Padding is invalid and cannot be removed. return Encoding.UTF8.GetString(textBytes,count); } } }
如果以这种方式使用此类:
AES.Encrypt(cryptoData);
AES.Decrypt(cryptoData);
首次使用会为您提供正确的AES加密字符串,但如果在尝试解密相同的字符串时失败并出现异常.问题在于,当通过字节数组给出此密码时,从PasswordDeriveBytes类中分配第一个参数(用于从中派生密钥的密码).如果它是一个字符串(由于过载),它可以正常工作.
助手CryptoData类:
public class CryptoData { private string text; public string Text { get { return text; } set { text = value; if (value != null) { ByteText = Encoding.ASCII.GetBytes(value); } else { ByteText = null; } } } public byte[] ByteText { get; private set; } public byte[] Password { get; set; } public int KeySize { get; set; } public byte[] InitVector { get; set; } public byte[] Salt { get; set; } }
如果您只是在方法中更改此行:
using (PasswordDeriveBytes pass = new PasswordDeriveBytes(cryptoData.Password,2))
成
using (PasswordDeriveBytes pass = new PasswordDeriveBytes("somePassword",2))
一切正常.问题是,由于using语句,PasswordDeriveBytes的实例在第二次使用时没有得到密码的字节数组.如果传递了一个字符串,而不是一个字节数组,它就可以工作.
编辑:仔细检查后,似乎密码参数的默认属性设置器中存在问题.它获取数组的指针,这就是它处理它的原因.它应该创建数组的value.clone(),就像salt数组的情况一样.这是一个明确的错误.
我是对的,还是我做错了什么?
编辑:
*使用此更改AES.Encrypt()和AES.Decrypt方法中的第一行,它可以工作:*
using (PasswordDeriveBytes pass = new PasswordDeriveBytes( (byte[])cryptoData.Password.Clone(),2))
解决方法
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。