Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 用C语言实现AES解密#_C#_Security_Cryptography_Aes_Bouncycastle - Fatal编程技术网

C# 用C语言实现AES解密#

C# 用C语言实现AES解密#,c#,security,cryptography,aes,bouncycastle,C#,Security,Cryptography,Aes,Bouncycastle,我正在使用一个名为的基于Java的配置管理工具,它支持使用各种加密方案加密敏感的配置信息 我已将其配置为对我的数据使用以下方案 AES(弹跳城堡) 名称:PBEWITHSA256和128位AES-CBC-BC 要求:Bouncy Castle API和JCE无限强度策略文件 哈希算法:SHA256 散列迭代次数:1000 现在,当读回我的配置数据时,我需要先解密信息,然后才能使用它,文档提供了以下有关此主题的信息 Jasypt(以及Zuul)生成的加密值以salt作为前缀(通常为8或16字节

我正在使用一个名为的基于Java的配置管理工具,它支持使用各种加密方案加密敏感的配置信息

我已将其配置为对我的数据使用以下方案

AES(弹跳城堡)

  • 名称:PBEWITHSA256和128位AES-CBC-BC
  • 要求:Bouncy Castle API和JCE无限强度策略文件
  • 哈希算法:SHA256
  • 散列迭代次数:1000
现在,当读回我的配置数据时,我需要先解密信息,然后才能使用它,文档提供了以下有关此主题的信息

Jasypt(以及Zuul)生成的加密值以salt作为前缀(通常为8或16字节,具体取决于算法要求)。然后对它们进行Base64编码。解密结果的过程如下所示:

  • 将Base64字符串转换为字节
  • 去掉前8或16个字节作为salt
  • 保留加密负载的剩余字节
  • 使用salt、迭代计数和密码调用KDF函数以创建密钥
  • 使用密钥对加密的有效负载进行解密
详情如下:

基于以上细节,我编写了以下代码(我对安全性的了解非常有限)

我将Zuul配置为使用以下密码进行加密

简单密码

现在我有一个Zuul给我的加密字符串,我需要解密它

p8C9hAHaoo0F25rMueT0+u0O6xYVpGIkjHmWqFJmTOvpV8+cipoDFIUnaOFF5ElQ

当我试图用上面的代码解密这个字符串时,我得到了下面的异常

System.Security.Cryptography.CryptographyException:填充无效,无法删除

正如我前面提到的,我对这个主题的了解有限,我无法确定文档中提供的信息是否不够,我是否在编写解密例程时出错,或者我是否应该使用bouncy castle进行解密


如果有任何帮助,我们将不胜感激。

根据Zuul文档,他们正在从密码/salt中获取密钥和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);
}

感谢您的回复Nickolay,现在我了解了键和块大小的重要性。我根据你的建议更新了代码,但仍然得到相同的错误。下面突出显示的是我更改Rfc2898DeriveBytes key=new Rfc2898DeriveBytes(密码、saltBytes、迭代)的行;byte[]keyBytes=key.GetBytes(48);AESChryptoServiceProvider aesAlg=新的AESChryptoServiceProvider();aesAlg.KeySize=256;aesAlg.BlockSize=128;aesAlg.Key=keyBytes.Take(aesAlg.KeySize/8).ToArray();aesAlg.IV=keyBytes.Skip(aesAlg.KeySize/8).ToArray();下一步要尝试的是将padding设置为None,并查看解密是否生成看起来像正确数据的内容。感谢您的帮助,Nickolay,我已通过添加以下行将padding设置为None:aesAlg.padding=PaddingMode.None;这不会再导致我的代码失败,但解密的值是一些随机字符:(好的,我现在发现的下一件事是Rfc2898DeriveBytes使用SHA1,而您显然需要SHA256。如果AESCryptServiceProvider中的加密模式默认为CBC,请检查加密模式。你是对的,Nickolay,但是我无法找到使用SHA256派生密钥的方法。我已将代码改为使用Bouncy Castle这一切都很完美。我会发布代码供大家参考。谢谢所有的帮助和建议。
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);
}