C# 用C语言实现AES解密#
我正在使用一个名为的基于Java的配置管理工具,它支持使用各种加密方案加密敏感的配置信息 我已将其配置为对我的数据使用以下方案 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字节
- 名称:PBEWITHSA256和128位AES-CBC-BC
- 要求:Bouncy Castle API和JCE无限强度策略文件
- 哈希算法:SHA256
- 散列迭代次数:1000
- 将Base64字符串转换为字节
- 去掉前8或16个字节作为salt
- 保留加密负载的剩余字节
- 使用salt、迭代计数和密码调用KDF函数以创建密钥
- 使用密钥对加密的有效负载进行解密
如果有任何帮助,我们将不胜感激。根据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);
}