C#中对应于Java RSA/ECB/OAEPWithSHA-256AndMGF1Padding的加密算法

4
我正在尝试在Java中加密字符串,并在C#中解密。我首先尝试了RSA / ECB / PKCS1PADDING,效果非常好,但现在我想切换到OAEP填充,但是我无法使其工作。加密运作良好,但解密则不行。我仅更改了Java中的算法名称,在C#中将rsa.Decrypt(data,true)从false更改为true。是否需要进行更多更改?
我得到的异常是“解码OAEP填充时发生错误”。
我的Java加密方法:
public byte[] rsaEncrypt(byte[] data) {

    byte[] cipherData;

    try {

        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(pubMod, pubExp);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(keySpec);

        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        cipherData = cipher.doFinal(data);
        return cipherData;

    } catch (NoSuchAlgorithmException | IllegalBlockSizeException | InvalidKeyException | InvalidKeySpecException | NoSuchPaddingException | BadPaddingException e) {
        e.printStackTrace();
    }

    return null;
}

我的C#解密方法:

private string RSADecrypt(byte[] data)
    {
        const string PrivateKey = *the key*;

        const int PROVIDER_RSA_FULL = 1;
        const string CONTAINER_NAME = "Tracker";

        CspParameters cspParams;
        cspParams = new CspParameters(PROVIDER_RSA_FULL);
        cspParams.KeyContainerName = CONTAINER_NAME;

        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams);

        rsa.FromXmlString(PrivateKey);

        byte[] decrypted = rsa.Decrypt(data, true);

        String decryptedString = System.Text.Encoding.UTF8.GetString(decrypted);

        return decryptedString;
    }
2个回答

3
RSACryptoServiceProvider不支持OAEP-SHA2。
.NET 4.6添加了RSACng,它能够支持OAEP-SHA2(256、384、512)。.NET 4.6还稍微改变了加密/解密和签名/验证的签名,使其比布尔更具可扩展性,并将它们移到RSA基类中:
using (RSA rsa = new RSACng())
{
    rsa.FromXmlString(privateKeyXml);
    byte[] decrypted = rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA256);
    return Encoding.UTF8.GetString(decrypted);
}

如果您的私钥来自于X509Certificate2实例,新的GetRSAPrivateKey方法(也在4.6中)将优先选择RSACng实例;虽然返回类型故意不保证...因此,如果必须进行强制转换,则应使用as而不是硬转换。

rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA256) 的输出结果与 RSA/ECB/OAEPWithSHA-1AndMGF1Padding 有所不同吗? 我想在 C# 中使用 RSA/ECB/OAEPWithSHA-1AndMGF1Padding 算法。 - hamid reza Heydari
@hamidrezaHeydari 是的,它们是不同的,因为SHA-1和SHA256是不同的算法。如果它们都使用相同的哈希算法,那么它们将是等效的... - bartonjs
谢谢,那么在C#中如何使用RSA.Decrypt(data, RSAEncryptionPadding.OaepSHA256)呢?而在Java中则是使用RSA/ECB/OAEPWithSHA-256和MGF1Padding。但是在C#中我找不到MGF1。谢谢。 - hamid reza Heydari
1
@hamidrezaHeydari 那些是一样的。MGF1在.NET中是隐含的。 - bartonjs
如何将 Pem 转换为 XML 字符串?对于 rsa.FromXmlString(privateKeyXml); 代码中的 privateKeyXml,我的密钥是 Pem。 - hamid reza Heydari
@hamidrezaHeydari,如果您有新的问题,请提出新的问题,而不是在现有问题的半相关答案上进行评论。同时,请考虑搜索ImportFromPem。 - bartonjs

2

看起来是SHA-256在C#中不能正常工作。我把算法名更改为"RSA/ECB/OAEPWithSHA-1AndMGF1Padding",这样它就可以工作了!


如果有人知道这是为什么,请随意发表评论! - Evv
1
SHA-1是OAEP的默认选项。在MGF1中使用SHA-1的安全性并不成问题,因此没有太多升级的理由。 - Maarten Bodewes
感谢您的回答。对于使用rsa.FromXmlString(privateKeyXml),我有一个'pem'密钥,如何将其转换为xmlstring或者您知道其他计划吗? - hamid reza Heydari

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