简体   繁体   English

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

[英]Padding error when using RSA Encryption in C# and Decryption in Java

Currently I am receiving the following error when using Java to decrypt a Base64 encoded RSA encrypted string that was made in C#: 目前,当使用Java解密在C#中创建的Base64编码的RSA加密字符串时,我收到以下错误:

javax.crypto.BadPaddingException: Not PKCS#1 block type 2 or Zero padding javax.crypto.BadPaddingException:不是PKCS#1块类型2或零填充

The setup process between the exchange from .NET and Java is done by creating a private key in the .NET key store then from the PEM file extracted, created use keytool to create a JKS version with the private key. .NET和Java交换之间的设置过程是通过在.NET密钥库中创建私钥然后从提取的PEM文件完成的,使用keytool创建一个带私钥的JKS版本。 Java loads the already created JKS and decodes the Base64 string into a byte array and then uses the private key to decrypt. Java加载已创建的JKS并将Base64字符串解码为字节数组,然后使用私钥进行解密。

Here is the code that I have in C# that creates the encrypted string: 这是我在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);
}

Here is the code that I have in Java that decrypts the inputted string: 这是我在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));
}

Does anyone see a step missing or where the padding or item needs to be changed? 有没有人看到缺少步骤或填充或项目需要更改? I have done hours of reading on this site and others but haven't really found a concrete solution. 我在这个网站和其他网站上做了几个小时的阅读,但还没有找到具体的解决方案。

You're help is vastly appreciated. 非常感谢您的帮助。

Thanks. 谢谢。 -Matt -Matt

I had exactely the same problem and I finally find the solution! 我有同样的问题,我终于找到了解决方案!

I was stubborn using PKCS1Padding but I didn't manage to make it work. 我使用PKCS1Padding很顽固,但我没有设法让它工作。

The best result I got using "rsa.Encrypt(baIn, false)" on the C# side and "RSA/NONE/NoPadding" on the Java side was this kind of string : "☻?o+_>??5?l0Q*???*?R▲???♀7..." followed by my decrypted string. 我在C#端使用“rsa.Encrypt(baIn,false)”和Java端的“RSA / NONE / NoPadding”得到的最好结果就是这种字符串:“☻?o + _> ?? 5?l0Q * ??? *?R▲???♀7...“后跟我的解密字符串。 So in a way it got decrypted but since there is no padding specified, the data is shifted. 所以在某种程度上它被解密但由于没有指定填充,数据被移位。 So I tried all the paddings available in bouncycastle but I would alway get errors such as "block incorrect size" or "data hash wrong". 所以我尝试了bouncycastle中提供的所有填充,但我总是会遇到诸如“阻止不正确的大小”或“数据哈希错误”之类的错误。

So I decided to start trying OAEP paddings and I finally managed to get it working by using "rsa.Encrypt(baIn, true)" on the C# side and "RSA/NONE/OAEPWithSHA1AndMGF1Padding" on the java side! 所以我决定开始尝试OAEP填充,我终于设法通过在C#端使用“rsa.Encrypt(baIn,true)”和在java端使用“RSA / NONE / OAEPWithSHA1AndMGF1Padding”来实现它!

It worked for me, I hope it will work for you too! 它对我有用,我希望它也适合你! If it doesn't work make sure you're using the right key, very often the problem comes from the key. 如果它不起作用,请确保使用正确的密钥,通常问题来自密钥。

Check that you have correctly exchanged the key. 检查您是否正确更换了密钥。

Trying to decrypt with an incorrect key is indistinguishable from decrypting badly padded data. 尝试使用不正确的密钥进行解密与解密填充不当的数据无法区分。

I'm working through a similar problem operating between .Net and iPhone stuff in Objective - C, and I think the answer lies in this little gem from the RSACryptoServiceProvider documentation: 我正在解决在Objective-C中在.Net和iPhone之间运行的类似问题,我认为答案在于RSACryptoServiceProvider文档中的这个小宝石:

Unlike the RSA implementation in unmanaged CAPI, the RSACryptoServiceProvider class reverses the order of an encrypted array of bytes after encryption and before decryption. 与非托管CAPI中的RSA实现不同,RSACryptoServiceProvider类在加密后和解密之前反转加密字节数组的顺序。 By default, data encrypted by the RSACryptoServiceProvider class cannot be decrypted by the CAPI CryptDecrypt function and data encrypted by the CAPI CryptEncrypt method cannot be decrypted by the RSACryptoServiceProvider class. 默认情况下,CAPAC CryptDecrypt函数无法解密由RSACryptoServiceProvider类加密的数据,并且RSACryptoServiceProvider类无法解密由CAPI CryptEncrypt方法加密的数据。

See here for more details: http://msdn.microsoft.com/en-us/library/s575f7e2(v=VS.90).aspx 有关详细信息,请参阅此处: http//msdn.microsoft.com/en-us/library/s575f7e2(v = VS.90).aspx

My guess is that the C# version is emitting the bytes in little endian format, and the Java version is importing the bytes expecting them to be in big endian format. 我的猜测是C#版本以小端格式发出字节,而Java版本正在导入期望它们采用大端格式的字节。 Try swapping the bytes in baRet from end to end before you convert them to base 64, and see if your Java program can decrypt them then. 尝试在将baRet转换为base 64之前从头到尾交换baRet中的字节,然后查看您的Java程序是否可以解密它们。

Just a guess. 只是一个猜测。

I had the same problem when using Bouncy Castle 1.48 but it wasn't key-related. 使用Bouncy Castle 1.48时我遇到了同样的问题,但它与键无关。 Instead, I found that I had to set the following system property: 相反,我发现我必须设置以下系统属性:

-Dorg.bouncycastle.pkcs1.strict=false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM