我有以下代碼使用AesCryptoServiceProvider
進行加密和解密。所使用的iv
和key
對於加密和解密都是相同的。解密值仍然與源字符串不同。使用AesCryptoServiceProvider獲取不正確的解密值
- 什麼需要糾正以獲得解密後的原始值?
- 此代碼適用於
inputValue = valid128BitString
。但是當inputString = 「Test」
我得到以下例外Padding is invalid and cannot be removed.
。我們如何糾正它?
修訂問題
下面將基於@jbtule答案做的伎倆。
從加密結果改變IV
值。假設加密是在一個單獨的過程中完成的,我們如何知道解密的IV?有沒有辦法使其保持不變或已知?
答案:您的其他選項是通過IV加密並在開始加密轉換之前分配它,而不是讓aesProvider爲您生成一個隨機的加密轉換。 - @Scott Chamberlain
aesProvider.IV = Convert.FromBase64String("4uy34C9sqOC9rbV4GD8jrA==");
更新:請參閱How to apply padding for Base64。我們可以使用UTF8
來編碼源輸入和結果輸出。鑰匙和IV可能保留在Base64
。
使用的Base64源輸入會導致問題的一些的值,例如,「MyTest的」,其中的字符串的長度不是4
相關點的整數倍:
要解密的數據使用SymmetricAlgorithm類之一進行加密,必須將Key屬性和IV屬性設置爲用於加密的相同值。
SymmetricAlgorithm.IV屬性:來自前一個塊的信息混合到加密下一個塊的過程中。因此,兩個相同的純文本塊的輸出是不同的。由於該技術使用前一個塊來加密下一個塊,所以需要一個初始化向量來加密第一個數據塊。(正如每SymmetricAlgorithm.IV Property MSDN文章)
有效鍵尺寸爲: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; }
}
參考
- How many characters to create a byte array for my AES method?
- Specified key is not a valid size for this algorithm
- Encryption with AES-256 and the Initialization Vector
- Invalid length for a Base-64 char array
- What's the difference between UTF8/UTF16 and Base64 in terms of encoding
什麼是實際的異常類型,你得到解密或加密?想知道因爲'byte [] byteValForString = Convert.FromBase64String(「Test」);'對你的純文本無效。 – jbtule 2013-02-18 15:32:19
你可以在Encrypt()和Decrypt()中使用'aesProvider.Padding = PaddingMode.None'嗎?不知道爲什麼它使用相同的填充時出錯? – Amitd 2013-02-18 15:51:47
@jbtule我在Decrypt()方法中遇到異常 - decStream.FlushFinalBlock();聲明。填充無效,無法刪除。 – Lijo 2013-02-18 16:00:59