简体   繁体   English

使用C#进行AES解密

[英]AES Decryption Using C#

I am using a Java based configuration management tool called Zuul which supports encrypting sensitive configuration information using various encryption schemes. 我正在使用一个名为Zuul的基于Java的配置管理工具,它支持使用各种加密方案加密敏感配置信息。

I have configured it to use below scheme for my data 我已将其配置为使用以下方案来获取我的数据

AES (Bouncy Castle) AES(Bouncy Castle)

  • Name: PBEWITHSHA256AND128BITAES-CBC-BC 名称:PBEWITHSHA256AND128BITAES-CBC-BC
  • Requirements: Bouncy Castle API and JCE Unlimited Strength Policy Files 要求:Bouncy Castle API和JCE Unlimited Strength Policy Files
  • Hashing Algorithm: SHA256 哈希算法:SHA256
  • Hashing Iterations: 1000 哈希迭代:1000

Now when reading my configuration data back, I need to decrypt the information before I can use it and the documentation provides below information around this topic. 现在,在回读我的配置数据时,我需要在使用之前解密信息,文档提供了有关此主题的以下信息。

The encrypted values produced by Jasypt (and thus Zuul) are are prefixed with the salt (usually 8 or 16 bytes depending on the algorithm requirements). Jasypt(以及Zuul)生成的加密值以盐为前缀(通常为8或16字节,具体取决于算法要求)。 They are then Base64 encoded. 然后它们是Base64编码的。 Decrypting the results goes something like this: 解密结果是这样的:

  • Convert the Base64 string to bytes 将Base64字符串转换为字节
  • Strip off the first 8 or 16 bytes as the salt 剥去前8或16个字节作为盐
  • Keep the remaining bytes for the encrypted payload 保留加密有效负载的剩余字节数
  • Invoke the KDF function with the salt, iteration count and the password to create the secret key. 使用salt,迭代计数和密码调用KDF函数以创建密钥。
  • Use the secret key to decrypt the encrypted payload 使用密钥解密加密的有效负载

More details here: Zull Encryption wiki 更多细节: Zull加密维基

Based on above details, I have written below code (and my knowledge around security is very limited) 基于以上细节,我写了下面的代码(我对安全性的了解非常有限)

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();
}

I configured Zuul to use below password for the encryption 我将Zuul配置为使用以下密码进行加密

SimplePassword SimplePassword

And now I have an encrypted string given to me by Zuul and I need to decrypt it 现在我有一个Zuul给我的加密字符串,我需要解密它

p8C9hAHaoo0F25rMueT0+u0O6xYVpGIkjHmWqFJmTOvpV8+cipoDFIUnaOFF5ElQ p8C9hAHaoo0F25rMueT0 + u0O6xYVpGIkjHmWqFJmTOvpV8 + cipoDFIUnaOFF5ElQ

When I try to decrypt this string using above code, I get below exception 当我尝试使用上面的代码解密此字符串时,我得到以下异常

System.Security.Cryptography.CryptographicException : Padding is invalid and cannot be removed. System.Security.Cryptography.CryptographicException:填充无效,无法删除。

As I mentioned earlier, my knowledge around this topic is limited and I am not able to figure out if the information provided in the documentation is not enough, if I am doing something wrong while writing the decryption routine or should I be using bouncy castle for decryption as well. 正如我之前提到的,我对这个主题的了解是有限的,我无法弄清楚文档中提供的信息是否不够,如果我在编写解密例程时做错了什么,或者我应该使用充气城堡解密也是如此。

Any help with this will be much appreciated. 任何帮助都将非常感激。

According to Zuul documentation they are deriving both key and iv from the password/salt. 根据Zuul文档,他们从密码/盐中获取密钥和iv。 So you should derive 256+128 bits (ie 48 bytes), and use first 32 bytes as the key, and next 16 bytes as IV. 因此,您应该派生256 + 128位(即48字节),并使用前32个字节作为密钥,接下来的16个字节作为IV。 And this should be done in one operation, not as consequent calls to key.DeriveBytes. 这应该在一个操作中完成,而不是随后调用key.DeriveBytes。

I resorted to Bouncy Castle for decryption instead since that is used by Zuul as well. 我使用Bouncy Castle进行解密,因为Zuul也使用了它。

Here is the code that works 这是有效的代码

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