【发布时间】:2013-02-02 23:11:54
【问题描述】:
我有以下代码使用AesCryptoServiceProvider 进行加密和解密。加密和解密使用的iv 和key 相同。解密后的值仍然与源字符串不同。
- 解密后需要修正什么才能得到原值?
- 此代码在
inputValue = valid128BitString时有效。但是当inputString = “Test”我得到以下异常Padding is invalid and cannot be removed.。我们该如何纠正它?
更新问题
以下将根据@jbtule 的回答来解决问题。
encyptedValue.IV = result.IV;
加密结果中的IV 值发生变化。假设加密是在一个单独的过程中完成的,我们如何知道解密的 IV?有没有办法让它保持不变或为人所知?
回答:您的另一种选择是将 IV 传递给 Encrypt 并在开始加密转换之前分配它,而不是让 aesProvider 为您生成一个随机的。 ——@斯科特·张伯伦
aesProvider.IV = Convert.FromBase64String("4uy34C9sqOC9rbV4GD8jrA==");
更新:请参阅How to apply padding for Base64。我们可以使用UTF8 对源输入和结果输出进行编码。密钥和 IV 可能保留在 Base64 中。
使用 Base64 进行源输入会导致某些值出现问题,例如“MyTest”,其中字符串长度不是 4 的倍数
相关要点:
要解密使用 SymmetricAlgorithm 类之一加密的数据,您必须将 Key 属性和 IV 属性设置为用于加密的相同值。
SymmetricAlgorithm.IV 属性:来自前一个块的信息被混合到加密下一个块的过程中。因此,两个相同的纯文本块的输出是不同的。因为这种技术使用前一个块来加密下一个块,所以需要一个初始化向量来加密第一个数据块。 (根据SymmetricAlgorithm.IV PropertyMSDN 文章)
有效的密钥大小为:128、192、256 位(根据How many characters to create a byte array for my AES method?)
主程序
class Program
{
static void Main(string[] args)
{
string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
string inputValue = valid128BitString;
string keyValue = valid128BitString;
string iv = valid128BitString;
byte[] byteValForString = Convert.FromBase64String(inputValue);
EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
EncryptResult encyptedValue = new EncryptResult();
encyptedValue.IV = iv;
encyptedValue.EncryptedMsg = result.EncryptedMsg;
string finalResult = Convert.ToBase64String(Aes128Utility.DecryptData(encyptedValue, keyValue));
Console.WriteLine(finalResult);
if (String.Equals(inputValue, finalResult))
{
Console.WriteLine("Match");
}
else
{
Console.WriteLine("Differ");
}
Console.ReadLine();
}
}
AES 实用程序
public static class Aes128Utility
{
private static byte[] key;
public static EncryptResult EncryptData(byte[] rawData, string strKey)
{
EncryptResult result = null;
if (key == null)
{
if (!String.IsNullOrEmpty(strKey))
{
key = Convert.FromBase64String((strKey));
result = Encrypt(rawData);
}
}
else
{
result = Encrypt(rawData);
}
return result;
}
public static byte[] DecryptData(EncryptResult encryptResult, string strKey)
{
byte[] origData = null;
if (key == null)
{
if (!String.IsNullOrEmpty(strKey))
{
key = Convert.FromBase64String(strKey);
origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
}
}
else
{
origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
}
return origData;
}
private static EncryptResult Encrypt(byte[] rawData)
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = key;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream encStream = new CryptoStream(memStream, aesProvider.CreateEncryptor(), CryptoStreamMode.Write);
encStream.Write(rawData, 0, rawData.Length);
encStream.FlushFinalBlock();
EncryptResult encResult = new EncryptResult();
encResult.EncryptedMsg = Convert.ToBase64String(memStream.ToArray());
encResult.IV = Convert.ToBase64String(aesProvider.IV);
return encResult;
}
}
}
private static byte[] Decrypt(byte[] encryptedMsg, byte[] iv)
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = key;
aesProvider.IV = iv;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream decStream = new CryptoStream(memStream, aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
decStream.Write(encryptedMsg, 0, encryptedMsg.Length);
decStream.FlushFinalBlock();
return memStream.ToArray();
}
}
}
}
DTO 类
public class EncryptResult
{
public string EncryptedMsg { get; set; }
public string IV { get; set; }
}
参考文献
【问题讨论】:
-
实际的异常类型是什么,你是在解密还是加密时得到这个?想知道,因为
byte[] byteValForString = Convert.FromBase64String("Test");对您的纯文本无效。 -
你能在 Encrypt() 和 Decrypt() 中尝试
aesProvider.Padding = PaddingMode.None吗?如果它有效吗?想知道如果使用相同的填充,为什么会出错? -
@jbtule 我在 Decrypt() 方法中遇到异常 - decStream.FlushFinalBlock();陈述。填充无效,无法移除。
-
参考stackoverflow.com/questions/14954248/…作为Key和IV的字符串长度
标签: c# .net encryption cryptography