簡體   English   中英

使用C#進行AES解密

[英]AES Decryption Using C#

我正在使用一個名為Zuul的基於Java的配置管理工具,它支持使用各種加密方案加密敏感配置信息。

我已將其配置為使用以下方案來獲取我的數據

AES(Bouncy Castle)

  • 名稱:PBEWITHSHA256AND128BITAES-CBC-BC
  • 要求:Bouncy Castle API和JCE Unlimited Strength Policy Files
  • 哈希算法:SHA256
  • 哈希迭代:1000

現在,在回讀我的配置數據時,我需要在使用之前解密信息,文檔提供了有關此主題的以下信息。

Jasypt(以及Zuul)生成的加密值以鹽為前綴(通常為8或16字節,具體取決於算法要求)。 然后它們是Base64編碼的。 解密結果是這樣的:

  • 將Base64字符串轉換為字節
  • 剝去前8或16個字節作為鹽
  • 保留加密有效負載的剩余字節數
  • 使用salt,迭代計數和密碼調用KDF函數以創建密鑰。
  • 使用密鑰解密加密的有效負載

更多細節: Zull加密維基

基於以上細節,我寫了下面的代碼(我對安全性的了解非常有限)

public static string Decrypt(string cipher, string password)
{
   const int saltLength = 16;
   const int iterations = 1000;

   byte[] cipherBytes = Convert.FromBase64String(cipher);
   byte[] saltBytes = cipherBytes.Take(saltLength).ToArray();
   byte[] encryptedBytes = cipherBytes.Skip(saltLength).ToArray();

   Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, saltBytes, iterations);
   byte[] keyBytes = key.GetBytes(16);

   AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider();
   aesAlg.KeySize = 256;
   aesAlg.BlockSize = 128;

   aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
   aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);

   ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
   MemoryStream msDecrypt = new MemoryStream(encryptedBytes);
   CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
   StreamReader srDecrypt = new StreamReader(csDecrypt);

   return srDecrypt.ReadToEnd();
}

我將Zuul配置為使用以下密碼進行加密

SimplePassword

現在我有一個Zuul給我的加密字符串,我需要解密它

p8C9hAHaoo0F25rMueT0 + u0O6xYVpGIkjHmWqFJmTOvpV8 + cipoDFIUnaOFF5ElQ

當我嘗試使用上面的代碼解密此字符串時,我得到以下異常

System.Security.Cryptography.CryptographicException:填充無效,無法刪除。

正如我之前提到的,我對這個主題的了解是有限的,我無法弄清楚文檔中提供的信息是否不夠,如果我在編寫解密例程時做錯了什么,或者我應該使用充氣城堡解密也是如此。

任何幫助都將非常感激。

根據Zuul文檔,他們從密碼/鹽中獲取密鑰和iv。 因此,您應該派生256 + 128位(即48字節),並使用前32個字節作為密鑰,接下來的16個字節作為IV。 這應該在一個操作中完成,而不是隨后調用key.DeriveBytes。

我使用Bouncy Castle進行解密,因為Zuul也使用了它。

這是有效的代碼

public static string Decrypt(string cipher, string password)
{
   const int saltLength = 16;
   const int iterations = 1000;
   const string algSpec = "AES/CBC/NoPadding";
   const string algName = "PBEWITHSHA256AND128BITAES-CBC-BC";

   byte[] cipherBytes = Convert.FromBase64String(cipher);
   byte[] saltBytes = cipherBytes.Take(saltLength).ToArray();
   byte[] encryptedBytes = cipherBytes.Skip(saltLength).ToArray();
   char[] passwordChars = password.ToCharArray();

   Asn1Encodable defParams = PbeUtilities.GenerateAlgorithmParameters(algName, saltBytes, iterations);
   IWrapper wrapper = WrapperUtilities.GetWrapper(algSpec);
   ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(algName, passwordChars, defParams);
   wrapper.Init(false, parameters);

   byte[] keyText = wrapper.Unwrap(encryptedBytes, 0, encryptedBytes.Length);

   return Encoding.Default.GetString(keyText);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM