java - Java 中的 Bouncy Castle 加密 .Net 中的解密
问题描述
我使用以下内容使用密码加密字符串
static String algorithm = "PBEWITHSHA256AND128BITAES-CBC-BC";
static byte[] salt = "b9v4n38s".getBytes(StandardCharsets.UTF_8);
static int derivedKeyLength = 128;
static int iterations = 20000;
public static byte[] encrypt(String plainText, String password) throws NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, NoSuchAlgorithmException {
Security.addProvider(new BouncyCastleProvider());
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength);
SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm);
SecretKey key = f.generateSecret(spec);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] text = plainText.getBytes(StandardCharsets.UTF_8);
byte[] encrypted = cipher.doFinal(text);
return encrypted;
}
其结果是 base64 编码并作为 arg[0] 发送到 .Net(arg[1] 是相同的密码)。现在我正在尝试使用此代码在.Net中解密该字符串
private static string Decrypt(string[] args)
{
int derivedKeyLength = 128;
int iterations = 20000;
string algorithm = "PBEWITHSHA256AND128BITAES-CBC-BC";
byte[] salt = Encoding.UTF8.GetBytes("b9v4n38s");
PbeParametersGenerator pGen = new Pkcs12ParametersGenerator(new Sha256Digest());
pGen.Init(Encoding.UTF8.GetBytes(args[1]), salt, iterations);
ICipherParameters par = pGen.GenerateDerivedParameters("AES256", derivedKeyLength);
IBufferedCipher c = CipherUtilities.GetCipher(algorithm);
c.Init(false, par);
var input = Convert.FromBase64String(args[0]);
byte[] enc = c.DoFinal(input);
var decoded = Encoding.UTF8.GetString(enc);
return decoded;
}
不幸的是,它在 DoFinal 上失败并显示消息Org.BouncyCastle.Crypto.InvalidCipherTextException: 'pad block corrupted'
SecretKeyFactory.getInstance(algorithm)
Cipher.getInstance(algorithm)
使用与java中相同的算法字符串,但如果我pGen.GenerateDerivedParameters(algorithm, derivedKeyLength);
在 .Net 中尝试,它会抛出Org.BouncyCastle.Security.SecurityUtilityException: 'Algorithm PBEWITHSHA256AND128BITAES-CBC-BC not recognised.'
我没有设置这个算法,只是寻找一种在Java中加密字符串并在.Net中解密它的方法。
解决方案
用于解密使用发布的 Java 代码生成的密文的可能 C#/BC 代码是:
using System;
using System.Text;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
...
private static string algorithm = "PBEWITHSHA256AND128BITAES-CBC-BC";
private static byte[] salt = Encoding.UTF8.GetBytes("b9v4n38s");
private static int iterations = 20000;
public static string Decrypt(string ciphertextB64, string password)
{
IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(algorithm, salt, iterations);
ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(algorithm, password.ToCharArray(), algParams);
cipher.Init(false, cipherParams);
byte[] cipherBytes = Convert.FromBase64String(ciphertextB64);
byte[] decrypted = cipher.DoFinal(cipherBytes);
return Encoding.UTF8.GetString(decrypted);
}
测试:
string decrypted = Decrypt("mBy4YwAvUpvoSJhzBnpOCJw2kCayvdYfLJ/12x0BgUKh5m5bvArSheMMs2U5rYyE", "MyPassword");
Console.WriteLine(decrypted); // The quick brown fox jumps over the lazy dog
其中密文是使用密码MyPassword使用 Java 代码生成的。
请注意,静态盐通常是不安全的(当然测试目的除外)。
推荐阅读
- arrays - 来自另一个数组的键的字典值
- flutter - 如何在 Flutter 中设置用于 graph-ql 集成的演示客户端
- windows-community-toolkit - 尝试使用 WebView (Microsoft.Toolkit.Wpf.UI.Controls) 使用自签名证书导航到站点时,CertificateIsInvalid
- python - Python:d = _ 是什么意思?
- arrays - PostgreSQL 将多个结果添加到数组中
- android - 如何更改 RecyclerView 的褪色边缘颜色?
- c# - 如何继承c# windows forms应用程序中的设计部分?
- java - NumberPicker 与数据库中的数组
- r - 当我申请 quanteda.corpora 的英国政党宣言语料库时,为什么 quanteda 的 textmodel_wordfish 会无限运行?
- c# - 从 :this() 继承是什么意思?