C# 填充字符出现时的解密问题
我在文本框中输入存档的名称以获取此存档的消息 我把密码写在一个文本框里 我计算盐 按钮点击C# 填充字符出现时的解密问题,c#,encryption,aes,C#,Encryption,Aes,我在文本框中输入存档的名称以获取此存档的消息 我把密码写在一个文本框里 我计算盐 按钮点击 private void button1_Click_1(object sender, EventArgs e) { String message; String password; String result; String resultSalt; String nameResult; byt
private void button1_Click_1(object sender, EventArgs e)
{
String message;
String password;
String result;
String resultSalt;
String nameResult;
byte[] salt;
password = textBox2.Text;
nameResult = textBox3.Text;
new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);
resultSalt = Convert.ToBase64String(salt);
if (radioButton1.Checked == true)
{
message = readArchive();
result = Encrypt(message,password,resultSalt);
try
{
File.WriteAllText(nameResult, result);
MessageBox.Show("Encrypt Ok");
}
catch
{
MessageBox.Show("Error");
}
}
else
{
message = readArchive();
result = Decrypt(message,password,result);
try
{
File.WriteAllText(nameResult, resultSalt);
MessageBox.Show("Decrypt OK");
}
catch
{
MessageBox.Show("Error");
}
}
}
方法加密
public static string Encrypt(string message, string pass, string salt)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
DeriveBytes rgb = new Rfc2898DeriveBytes(pass, Encoding.Unicode.GetBytes(salt), 9);
byte[] key = rgb.GetBytes(aes.KeySize >> 3);
byte[] iv = rgb.GetBytes(aes.BlockSize >> 3);
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor();
byte[] data = Encoding.Unicode.GetBytes(message);
byte[] dataencrypt = encryptor.TransformFinalBlock(data, 0, data.Length);
return Convert.ToBase64String(dataencrypt);
}
方法解密
public static string Decrypt(string message, string pass, string salt)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
DeriveBytes rgb = new Rfc2898DeriveBytes(pass, Encoding.Unicode.GetBytes(salt), 9);
byte[] key = rgb.GetBytes(aes.KeySize >> 3);
byte[] iv = rgb.GetBytes(aes.BlockSize >> 3);
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
ICryptoTransform decryptor = aes.CreateDecryptor();
byte[] data = Convert.FromBase64String(message);
byte[] datadecrypt = decryptor.TransformFinalBlock(data, 0, data.Length);
return Encoding.Unicode.GetString(datadecrypt);
}
方法readArchive
private string readArchive()
{
String nameArchive = textBox1.Text;
String text = "";
try
{
text = File.ReadAllText(@nameArchive);
}
catch
{
MessageBox.Show("Error.");
}
return text;
}
误差线
byte[] datadecrypt = decryptor.TransformFinalBlock(data, 0, data.Length);
System.Core.dll中类型为“System.Security.Cryptography.CryptographyException”的未处理异常
其他信息:字符之间的填充无效,无法删除
在将salt传递给您的
加密(…)
之前,请使用以下命令对salt进行base64编码:resultSalt=Convert.ToBase64String(salt)
,然后使用encoding.Unicode.GetBytes(salt)
获取base64编码字符串的字节值。这可能不是您想要的,而是将其作为字节[]传递,或者在使用它之前执行正确的base64解码
但这不是主要问题。。主要问题是将
结果
传递给解密(…)
而不是resultSalt
。但是当您这样做时,您需要确保它与在加密(..)
上使用的相同。。当前,每次单击都会生成一个新的salt。需要更多信息。异常消息是什么?它有任何内部异常吗?它是什么?Unicode。GetBytes(salt)
很弱,但它必须匹配加密。写一个完整的密码,包含解密和加密代码。填充模式也应该匹配加密上的模式。但很可能您在线路的某个地方损坏了Base64。几乎没有例外,填充错误意味着由于输入不正确而导致解密失败。这解决了我的问题