【发布时间】:2020-04-30 22:51:59
【问题描述】:
我正在尝试编写一种加密/解密方法来进行练习,在初步运行正常后,我决定加强它并通过将 IV 加密到数据中来降低它的脆弱性。我得到了这个工作,并决定通过在数据中为 IV 的位置引入一个偏移量,通过在 IV 的左侧添加一些随机数据来再次加强它。到目前为止,一切正常,但现在我收到一个解密错误:
输入的数据不是一个完整的块。
由于我对加密和解密的了解有限,这对我调试问题毫无用处。我搜索了高低,但我发现这个问题的答案似乎都没有解决我的问题。答案通常是这样的:开发人员不是在解密 byte[],而是在解密一个 base 64 字符串。
private static Guid TestGuid = Guid.NewGuid();
private static DateTime Timestamp = DateTime.Now;
private static string key = "PPPQmyuzqKtjzYlWM3mP0aDxaxCzlsACajIkTVN4IjI=";
public static void Main()
{
string data = TestGuid + "|" + Timestamp;
Console.WriteLine("Request Parameter: " + data);
string encryptedData = AESEncrypt(key, data, 1);
Console.WriteLine("Encrypted: " + encryptedData);
string decryptedData = AESDecrypt(key, encryptedData, 1);
Console.WriteLine("Decrypted: " + decryptedData);
}
public static string AESEncrypt(string key, string data, int offset)
{
if (string.IsNullOrWhiteSpace(data))
throw new ArgumentException("Data");
byte[] encryptedData;
byte[] keyData = Convert.FromBase64String(key);
using (Aes algo = Aes.Create())
{
algo.Key = keyData;
algo.GenerateIV();
algo.Padding = PaddingMode.PKCS7;
byte[] iv = new byte[offset + 16];
Random r = new Random();
using (MemoryStream ms = new MemoryStream())
{
for (int i = 0; i < offset; i++)
iv[i] = (byte)r.Next(1, 200);
for (int i = 0; i < algo.IV.Length; i++)
iv[offset + i - 1] = algo.IV[i];
ICryptoTransform encryptor = algo.CreateEncryptor(algo.Key, algo.IV);
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (BinaryWriter bw = new BinaryWriter(cs))
{
bw.Write(iv, 0, offset);
ms.Write(iv, offset, algo.IV.Length);
bw.Write(data);
cs.FlushFinalBlock();
}
encryptedData = ms.ToArray();
}
}
}
if (encryptedData != null)
return Convert.ToBase64String(encryptedData);
throw new Exception("An unxpected error occurred and the provided data was not encrypted.");
}
public static string AESDecrypt(string key, string data, int offset)
{
if (string.IsNullOrWhiteSpace(data))
throw new ArgumentException("Data");
string decryptedData;
byte[] keyData = Convert.FromBase64String(key);
using (Aes algo = Aes.Create())
{
algo.Key = keyData;
algo.Padding = PaddingMode.PKCS7;
byte[] decodedData = Convert.FromBase64String(data);
using (MemoryStream ms = new MemoryStream(decodedData))
{
byte[] ivData = new byte[offset + 16];
ms.Read(ivData, 0, offset + 16);
List<byte> iv = new List<byte>();
for (int i = offset - 1; i < ivData.Length - 1; i++)
iv.Add(ivData[i]);
algo.IV = iv.ToArray();
ICryptoTransform decryptor = algo.CreateDecryptor(algo.Key, algo.IV);
List<byte> dataToDecrypt = new List<byte>();
for (int i = 0; i + offset < decodedData.Length; i++)
dataToDecrypt.Add(decodedData[i + offset]);
using (MemoryStream ds = new MemoryStream(dataToDecrypt.ToArray()))
{
using (CryptoStream cs = new CryptoStream(ds, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
decryptedData = sr.ReadToEnd();
}
}
}
}
}
if (!string.IsNullOrWhiteSpace(decryptedData))
return decryptedData;
throw new Exception("An unxpected error occurred and the provided data was not decrypted.");
}
是什么导致了这个错误,为什么会导致这个错误,我该如何解决这个错误,为什么这个解决方案有效?
【问题讨论】:
-
在 CryptoStream 中间调用 ms.Write 不是一个好主意,结果可能是随机的。 aes 使用一定大小的字节块。所以解密器还假设输入数据至少与块大小对齐。
-
你可以在代码审查codereview.stackexchange.com/questions/78434/c-aes-encryption找到一些aes示例
-
IV 在 CBC 中并不是要保密的,因此“加密”它不能提高安全性,也不能隐藏它,或者隐藏它,或者你能想到的任何其他东西。既然你需要IV来解密,如果你已经加密了,我怎么能得到它?
标签: c# encryption aes