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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1303220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 16:02:39  来源:igfitidea点击:

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

c#javarsaencryption

提问by Matt Shaver

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. Java loads the already created JKS and decodes the Base64 string into a byte array and then uses the private key to decrypt.

.NET 和 Java 交换之间的设置过程是通过在 .NET 密钥库中创建一个私钥,然后从提取的 PEM 文件中创建的,使用 keytool 创建一个带有私钥的 JKS 版本来完成的。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

谢谢。-马特

采纳答案by Rasmus Faber

Check that you have correctly exchanged the key.

检查您是否正确交换了密钥。

Trying to decrypt with an incorrect key is indistinguishable from decrypting badly padded data.

尝试使用不正确的密钥解密与解密填充不当的数据没有区别。

回答by Migs

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. 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".

我在 C# 端使用“rsa.Encrypt(baIn, false)”和在 Java 端使用“RSA/NONE/NoPadding”得到的最好结果是这种字符串:“??o+_>??5?l0Q *???*?R▲???♀7...”后跟我解密的字符串。所以在某种程度上它被解密了,但由于没有指定填充,数据被移位。所以我尝试了 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.

它对我有用,我希望它也对你有用!如果它不起作用,请确保您使用的是正确的密钥,通常问题出在密钥上。

回答by DJBHiney

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. 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.

与非托管 CAPI 中的 RSA 实现不同,RSACryptoServiceProvider 类在加密之后和解密之前反转加密字节数组的顺序。默认情况下,RSACryptoServiceProvider 类加密的数据不能被CAPI CryptDecrypt 函数解密,CAPI CryptEncrypt 方法加密的数据不能被RSACryptoServiceProvider 类解密。

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

回答by Nathan

I had the same problem when using Bouncy Castle 1.48 but it wasn't key-related. Instead, I found that I had to set the following system property:

我在使用 Bouncy Castle 1.48 时遇到了同样的问题,但它与键无关。相反,我发现我必须设置以下系统属性:

-Dorg.bouncycastle.pkcs1.strict=false