在C#中使用RSA加密和在Java中使用解密时出现填充错误

时间:2009-08-19 23:43:57

标签: c# java rsa encryption

目前,当使用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

5 个答案:

答案 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