在Java中使用RSA/ECB/OAEPWithSHA-256AndMGF1Padding进行加密,然后在C#中使用OAEPSHA256 Padding进行解密。

4

我有一个情况,即Java程序使用RSA/ECB/OAEPWithSHA-256AndMGF1Padding加密文本。

我需要在c#中对其进行解密。

在Java中,加密和解密工作得很好。

在Java中使用RSA/ECB/OAEPWithSHA-1AndMGF1Padding进行加密,在c#中使用OaepSHA256进行解密也能正常工作。

然而,当Java使用RSA/ECB/OAEPWithSHA-256AndMGF1Padding加密后,在c#中使用OaepSHA256进行解密时,会出现错误:参数不正确。

Java加密代码:

public static String encrypt(KeyPair keypair, String data) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        Cipher c = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        //Cipher c = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
        c.init(Cipher.ENCRYPT_MODE, keypair.getPublic());
        return Base64.getEncoder().encodeToString(c.doFinal(data.getBytes()));
    }

C#解密代码:

public string DecryptRsa(byte[] encryptedBytes, X509Certificate2 x509Certificate2, RSAEncryptionPadding rSAEncryptionPadding)
        {
            var text = string.Empty;

            using (RSACng csp = (RSACng)x509Certificate2.GetRSAPrivateKey())
            {

                byte[] bytesDecrypted = csp.Decrypt(encryptedBytes, rSAEncryptionPadding);
                text = Encoding.UTF8.GetString(bytesDecrypted);
            }
            return text;
        }

我做错了什么?请帮帮我。
1个回答

5

OAEP使用两个摘要算法,即OAEP摘要和MGF1摘要,详见RFC8017

SunJCE提供程序使用RSA/ECB/OAEPWithSHA-256AndMGF1Padding指定了SHA256作为OAEP摘要,而默认的MGF1摘要为SHA1,详见这里。另一方面,C#代码使用OaepSHA256指定了两个摘要算法都为SHA256。因此,两种代码不兼容。

解决方法是在Java中使用OAEPParameterSpec显式指定摘要算法(无论如何出于这个原因总是应该这样做)。在C#端,由于不支持分别指定两个摘要算法,因此无法使用内置手段进行修复。但可以使用支持此功能的BouncyCastle。


修复,Java代码方面(SHA256适用于两个摘要):

RSAPublicKey publicKey = ...
OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParameterSpec);
byte[] ciphertext = cipher.doFinal(plaintext);

使用BouncyCastle修复C#代码(OAEP摘要使用SHA256,MGF1摘要使用SHA1):
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Parameters;
...
RsaKeyParameters privateKey = ...
OaepEncoding oaepEncoding = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), null);
oaepEncoding.Init(false, privateKey);
byte[] decrypted = oaepEncoding.ProcessBlock(ciphertext, 0, ciphertext.Length);

非常感谢。不幸的是,我无法控制Java代码,因为它是第三方代码,使用我的公钥进行加密调用我的API。我尝试使用BouncyCastle,完全按照您上面建议的代码。但是它给我返回了一个非常晦涩的“数据错误”错误。 - MethodToChaos
很抱歉,当我说我使用了BouncyCastle时,我使用了Sha256Digest来初始化OaepEncoding的两个摘要。我会按照你建议的使用另一个哈希值进行尝试。非常感谢。 - MethodToChaos
这适用于我的Java/C#加密/解密(之前无法正常工作)。因此,我将把它标记为答案。但是第三方加密字符串在BouncyCastle C#中仍然会抛出“数据错误”错误。他们在加密方面肯定有问题。 - MethodToChaos
很棒的答案。我不得不实现一个.NET版本的RSA/ECB/OAEPWITHSHA-512ANDMGF1PADDING,最终变成了new OaepEncoding(new RsaEngine(), new Sha512Digest(), new Sha1Digest(), null); - rgvlee
太棒了!我不得不实现一个.NET版本的RSA/ECB/OAEPWITHSHA-512ANDMGF1PADDING,最终变成了new OaepEncoding(new RsaEngine(), new Sha512Digest(), new Sha1Digest(), null); - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接