目前,当使用Java解密在C#中创建的Base64编码的RSA加密字符串时,我收到以下错误:
javax.crypto.BadPaddingException:不是PKCS#1块类型2或零填充
.NET和Java交换之间的设置过程是通过在.NET密钥存储区中创建私钥来完成的,然后从提取的PEM文件中创建,使用keytool创建一个带私钥的JKS版本。 Java加载已创建的JKS并将Base64字符串解码为字节数组,然后使用私钥进行解密。
以下是我在C#中创建加密字符串的代码:
public string Encrypt(string value) {
byte[] baIn = null;
byte[] baRet = null;
string keyContainerName = "test";
CspParameters cp = new CspParameters();
cp.Flags = CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = keyContainerName;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
// Convert the input string to a byte array
baIn = UnicodeEncoding.Unicode.GetBytes(value);
// Encrypt
baRet = rsa.Encrypt(baIn, false);
// Convert the encrypted byte array to a base64 string
return Convert.ToBase64String(baRet);
}
以下是我在Java中解密输入字符串的代码:
public void decrypt(String base64String) {
String keyStorePath = "C:\Key.keystore";
String storepass = "1234";
String keypass = "abcd";
byte[] data = Base64.decode(base64String);
byte[] cipherData = null;
keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream(keyStorePath), storepass.toCharArray());
RSAPrivateKey privateRSAKey = (RSAPrivateKey) keystore.getKey(alias, keypass.toCharArray());
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateRSAKey);
cipherData = cipher.doFinal(data);
System.out.println(new String(cipherData));
}
是否有人看到缺少步骤或需要更改填充或项目?我已经在这个网站和其他网站上做了几个小时的阅读,但还没有找到具体的解决方案。
非常感谢你的帮助。
感谢。 -Matt
答案 0 :(得分:4)
我遇到了同样的问题,我终于找到了解决方案!
我使用PKCS1Padding很顽固,但我无法使其工作。
我在C#端使用“rsa.Encrypt(baIn,false)”并且在Java端使用“RSA / NONE / NoPadding”获得的最佳结果是这种字符串:“☻?o + _> ?? 5?l0Q * ??? *?R▲???♀7...”后跟我的解密字符串。所以在某种程度上它被解密但由于没有指定填充,数据被移位。所以我尝试了bouncycastle中提供的所有填充,但我总是会遇到诸如“阻止不正确的大小”或“数据哈希错误”之类的错误。
所以我决定开始尝试OAEP填充,我终于通过在C#端使用“rsa.Encrypt(baIn,true)”并且“RSA / NONE”设法使其工作java侧的/ OAEPWithSHA1AndMGF1Padding“!
它对我有用,我希望它也适合你!如果它不起作用,请确保使用正确的密钥,通常问题来自密钥。
答案 1 :(得分:2)
检查您是否正确更换了密钥。
尝试使用不正确的密钥解密与解密填充不当的数据无法区分。
答案 2 :(得分:2)
我正在解决在Objective-C中运行.Net和iPhone之间的类似问题,我认为答案在于RSACryptoServiceProvider文档中的这个小宝石:
与非托管CAPI中的RSA实现不同,RSACryptoServiceProvider类在加密后和解密之前反转加密字节数组的顺序。默认情况下,CAPAC CryptDecrypt函数无法解密由RSACryptoServiceProvider类加密的数据,并且RSACryptoServiceProvider类无法解密由CAPI CryptEncrypt方法加密的数据。
请点击此处了解详情:http://msdn.microsoft.com/en-us/library/s575f7e2(v=VS.90).aspx
答案 3 :(得分:0)
我的猜测是C#版本以小端格式发出字节,而Java版本正在导入期望它们采用大端格式的字节。尝试在将baRet转换为base 64之前从头到尾交换baRet中的字节,然后查看您的Java程序是否可以解密它们。
只是一个猜测。
答案 4 :(得分:0)
使用Bouncy Castle 1.48时遇到了同样的问题,但它与键无关。相反,我发现我必须设置以下系统属性:
-Dorg.bouncycastle.pkcs1.strict=false