如何更改现有加密/解密代码上的填充选项
本文关键字:代码 填充 选项 解密 何更改 加密 | 更新日期: 2023-09-27 18:17:25
我有以下代码,它工作了近两年。但是现在我们开始看到填充的随机问题。当我说随机时,我的意思是同样的事情在某一天起作用,但在另一天不起作用。有一天,它决定随机工作。
现在,如果我像上面的答案中提到的那样将填充添加到none,我可能会弄乱所有先前加密的文件。我正在考虑在catch块中使用GOTO语句创建不同的方法,就像我在更改加密密钥时所做的那样。或者是否有更好的方法将填充更改为None?
/// <summary>
///
/// </summary>
[Serializable]
public static class EncryptDecrypt
{
private static string EncryptionKey_old = "MAKV2SPBNI99212";
private static string EncryptionKey = "Yi9BpGG1cXR01gBwGPZRTOznoJHpkGBOzisBg5jl3iRu48yhcFGdZu76fDpa5FUu";
/// <summary>
///
/// </summary>
/// <param name="clearText"></param>
/// <returns></returns>
public static string Encrypt(string clearText)
{
byte[] whitebs = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
encryptor.Mode = CipherMode.ECB;
encryptor.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(whitebs, 0, whitebs.Length);
cs.FlushFinalBlock();
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText.EndsWith("==") ? clearText.Remove(clearText.Length - 2) : clearText;
}
/// <summary>
///
/// </summary>
/// <param name="cipherText"></param>
/// <returns></returns>
public static string Decrypt(string cipherText)
{
int attempts = 0;
string exception = string.Empty;
StartHere:
cipherText = cipherText.Replace(" ", "+");
byte[] cipherBytes;
try { cipherBytes = Convert.FromBase64String(cipherText); }
catch { cipherBytes = Convert.FromBase64String(cipherText + "=="); }
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
encryptor.Mode = CipherMode.ECB;
encryptor.Padding = PaddingMode.PKCS7;
try
{
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.FlushFinalBlock();
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
catch
{
if (attempts == 2) throw;
EncryptionKey = EncryptionKey_old;
attempts++;
goto StartHere;
}
}
return cipherText;
}
'
现在更改这个不是一个好主意,我也不知道我该怎么做,因为我们用这个代码加密了成千上万的文件
看起来像填充错误被用来确定解密是否成功,这是错误的,不会工作!您需要另一种方法来确定是否成功解密,在本例中,如果使用了正确的密钥。
见pkcs# 7 padding.
如果用错误的密钥解密,结果将基本上是随机数据,并且有1/256的概率,最后一个字节将是0x01,这是正确的填充,并且不会报告填充错误。在较小程度上,其他有效的填充将随机出现。
需要另一种方法来确定是否获得了正确的解密,通常使用MAC来验证加密。但它可以是数据中已知的东西,这通常被称为摇篮,成功率取决于它的唯一性。
Re: padding:除非要加密的数据长度始终是块大小的精确倍数(AES为16字节),否则需要填充,pkcs# 7填充是正确的填充