在C#中实现Java的RSA解密方法

问题描述 投票:0回答:1

我有一个用Java编写的解密方法。 Java 方法使用

new RSAPrivateKeySpec(BigInteger modulus, BigInteger privateExponent)
从十六进制字符串创建私钥,然后使用
Security.getProvider("BC"); Cipher instance = Cipher.getInstance("RSA/ECB/PKCS1Padding");
进行解密。

现在我正在尝试用 C# 实现相同的方法。为什么我的代码在

Key does not exist
中抛出
Decrypt
异常?另外我不确定 Java 十六进制字符串是否需要
SwapBytes
?我的 C# 代码是:

byte[] dataToDecrypt = Convert.FromBase64String("AJqdug3s19c6bi8FaQrz0Q+qLnX/7mFmaNL2ztFeZyx0yeg9+lI48qFBRoS000JHaljlhVJpjACLr/qYk4ZdZjJHD0ENJmv+lf4TmTGQZpv3uiUQpG7QbVP7c56yWK4MgyMd8EdhJLcviobShkW3lI1a46C4vF+37WzH6qvgMuuUvtPi8mi9GvhPHHuocAh05s+c5YN2R78+tpkrs05EU6fiSn3iqRnrXv48O9kxQs9S/w4xaFLgfu2wbcgyI62s2Xbri1WdfSPUIYaLmv1EvVnzBPIty4Wclun25RmB8UtH5EZXpFOGF5ER8OztCcUeTAQYP9n9W2aQOqfpIjcNMA==");

RSAParameters rsaparam = new RSAParameters();
rsaparam.Modulus  =
    XUtils.SwapBytes(
        XUtils.HexStringToByteArray(
            "E86763F6B409ECCA94818F7438385D6C12237B5458974C5FD8573A62383DF55B7A39F73F27D5069981FB045042374A123828016AAD4BA94A77609624E44BD83D6F8CD4751D9F3E546D9E56BC55D8554ACFDF28FE9F97B01E53F9A4CE6DADFACC9D4499C186D41B65426206AC55DCBEC7F658104405E911D11034B462B3279E731B1D3E44244D3C60300261A82A5B28F01AD58F4A2D3B230501B00528956D820E1AA27FB25DC483376390A3C26C97AD84B744BDBB8F9C65E6CDA2A66AD12AE660D6CE26DC44F0AB055E6A7F7A19161F1ACFA09A14E34A555F43AC00B5BFAA834CCDB00AE5953696E38003EBEF1CA2531DF354929047858BFB50409FFEC2A1BF33"));
rsaparam.D =
    XUtils.SwapBytes(
        XUtils.HexStringToByteArray(
            "7DF673DEE62C2EF489D3432E89BE3B1C752458171A413EFAFFE61F55D707F5F153E9111261037C253DA710EA7349465363AE833E0F995FB365CAAAF669EA95D48E9E7514D92E53792D44D1DC18673DAB63C99F8D8A708BDB94464DC638FA406220A76AF2D2A22A0B1314D06B1DCA9C7903132E15C06257EEC96AD78E5B6E10D967F480538FB9933E120750CDD31DC004BB94D0CD293C47EBC98D783B17C575DEC75751F99F82C026026773534B213446B14D4978EC44CD290908CBB3AF5FF35055A5698B096F66109B60C1A39D2A34FA791E421914E0137CCA3C95872FB39DD0586F2F4EFD6D1027596199F259D76FA3727B752EE76B4FE9C4A1BE18A6E67EC1"));
rsaparam.Exponent = new byte[] { 0x1, 0x0, 0x1 };
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSA.ImportParameters(rsaparam);
byte[] decryptedData = RSA.Decrypt(dataToDecrypt, false);
string s = Encoding.ASCII.GetString(decryptedData);
c# encryption rsa
1个回答
0
投票

据我所知,原生 C# 实现不仅需要私钥情况下的模数和私有指数 D,还需要其余参数 P、Q、DP、DQ 和 InverseQ(另请参阅here 和 for参数概述此处)。

但是你可以使用C#/BouncyCastle进行解密(在Java代码中BouncyCastle显然也适用,因为

Security.getProvider("BC")
):

using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using System;

...

// Import key
BigInteger n = new BigInteger("E86763F6B409ECCA94818F7438385D6C12237B5458974C5FD8573A62383DF55B7A39F73F27D5069981FB045042374A123828016AAD4BA94A77609624E44BD83D6F8CD4751D9F3E546D9E56BC55D8554ACFDF28FE9F97B01E53F9A4CE6DADFACC9D4499C186D41B65426206AC55DCBEC7F658104405E911D11034B462B3279E731B1D3E44244D3C60300261A82A5B28F01AD58F4A2D3B230501B00528956D820E1AA27FB25DC483376390A3C26C97AD84B744BDBB8F9C65E6CDA2A66AD12AE660D6CE26DC44F0AB055E6A7F7A19161F1ACFA09A14E34A555F43AC00B5BFAA834CCDB00AE5953696E38003EBEF1CA2531DF354929047858BFB50409FFEC2A1BF33", 16);// new BigInteger(1, nHex);
BigInteger d = new BigInteger("7DF673DEE62C2EF489D3432E89BE3B1C752458171A413EFAFFE61F55D707F5F153E9111261037C253DA710EA7349465363AE833E0F995FB365CAAAF669EA95D48E9E7514D92E53792D44D1DC18673DAB63C99F8D8A708BDB94464DC638FA406220A76AF2D2A22A0B1314D06B1DCA9C7903132E15C06257EEC96AD78E5B6E10D967F480538FB9933E120750CDD31DC004BB94D0CD293C47EBC98D783B17C575DEC75751F99F82C026026773534B213446B14D4978EC44CD290908CBB3AF5FF35055A5698B096F66109B60C1A39D2A34FA791E421914E0137CCA3C95872FB39DD0586F2F4EFD6D1027596199F259D76FA3727B752EE76B4FE9C4A1BE18A6E67EC1", 16);
RsaKeyParameters rsaKeyParameters = new RsaKeyParameters(true, n, d);

// Decrypt using BC
RsaEngine rsaEngine = new RsaEngine();
Pkcs1Encoding pkcs1Encoding = new Pkcs1Encoding(rsaEngine);
pkcs1Encoding.Init(false, rsaKeyParameters);
byte[] ciphertext = Convert.FromBase64String("AJqdug3s19c6bi8FaQrz0Q+qLnX/7mFmaNL2ztFeZyx0yeg9+lI48qFBRoS000JHaljlhVJpjACLr/qYk4ZdZjJHD0ENJmv+lf4TmTGQZpv3uiUQpG7QbVP7c56yWK4MgyMd8EdhJLcviobShkW3lI1a46C4vF+37WzH6qvgMuuUvtPi8mi9GvhPHHuocAh05s+c5YN2R78+tpkrs05EU6fiSn3iqRnrXv48O9kxQs9S/w4xaFLgfu2wbcgyI62s2Xbri1WdfSPUIYaLmv1EvVnzBPIty4Wclun25RmB8UtH5EZXpFOGF5ER8OztCcUeTAQYP9n9W2aQOqfpIjcNMA==");
byte[] decrypted = pkcs1Encoding.ProcessBlock(ciphertext, 0, ciphertext.Length);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(decrypted)); // aum5d6qxevl1psj4bgkfiynchtr3ozw2:099a515a5cba1b81

如果您想使用native C# 解密方法,您必须根据模数、私有和公共指数重建缺失值。 在这里你可以找到对应的Java实现,它可以很容易地转换为C#(但是,这个解决方案还需要BouncyCastle):

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;

...

private static BigInteger FindFactor(BigInteger e, BigInteger d, BigInteger n)
{
    BigInteger edMinus1 = e.Multiply(d).Subtract(BigInteger.One);
    int s = edMinus1.GetLowestSetBit();
    BigInteger t = edMinus1.ShiftRight(s);

    for (int aInt = 2; true; aInt++)
    {
        BigInteger aPow = BigInteger.ValueOf(aInt).ModPow(t, n);
        for (int i = 1; i <= s; i++)
        {
            if (aPow.Equals(BigInteger.One))
            {
                break;
            }
            if (aPow.Equals(n.Subtract(BigInteger.One)))
            {
                break;
            }
            BigInteger aPowSquared = aPow.Multiply(aPow).Mod(n);
            if (aPowSquared.Equals(BigInteger.One))
            {
                return aPow.Subtract(BigInteger.One).Gcd(n);
            }
            aPow = aPowSquared;
        }
    }
}

private static RsaPrivateCrtKeyParameters GetRsaPrivateCrtKeyParameters(BigInteger e, BigInteger d, BigInteger n)
{
    BigInteger p = FindFactor(e, d, n);
    BigInteger q = n.Divide(p);
    if (p.CompareTo(q) > 0)
    {
        BigInteger t = p;
        p = q;
        q = t;
    }
    BigInteger exp1 = d.Mod(p.Subtract(BigInteger.One));
    BigInteger exp2 = d.Mod(q.Subtract(BigInteger.One));
    BigInteger coeff = q.ModInverse(p);
    RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters = new RsaPrivateCrtKeyParameters(n, e, d, p, q, exp1, exp2, coeff);
    return rsaPrivateCrtKeyParameters;
}

这样,就可以使用本机 C# 方法进行解密,如下所示:

using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using System;
using System.Security.Cryptography;

...

// Import key
BigInteger n = new BigInteger("E86763F6B409ECCA94818F7438385D6C12237B5458974C5FD8573A62383DF55B7A39F73F27D5069981FB045042374A123828016AAD4BA94A77609624E44BD83D6F8CD4751D9F3E546D9E56BC55D8554ACFDF28FE9F97B01E53F9A4CE6DADFACC9D4499C186D41B65426206AC55DCBEC7F658104405E911D11034B462B3279E731B1D3E44244D3C60300261A82A5B28F01AD58F4A2D3B230501B00528956D820E1AA27FB25DC483376390A3C26C97AD84B744BDBB8F9C65E6CDA2A66AD12AE660D6CE26DC44F0AB055E6A7F7A19161F1ACFA09A14E34A555F43AC00B5BFAA834CCDB00AE5953696E38003EBEF1CA2531DF354929047858BFB50409FFEC2A1BF33", 16);// new BigInteger(1, nHex);
BigInteger d = new BigInteger("7DF673DEE62C2EF489D3432E89BE3B1C752458171A413EFAFFE61F55D707F5F153E9111261037C253DA710EA7349465363AE833E0F995FB365CAAAF669EA95D48E9E7514D92E53792D44D1DC18673DAB63C99F8D8A708BDB94464DC638FA406220A76AF2D2A22A0B1314D06B1DCA9C7903132E15C06257EEC96AD78E5B6E10D967F480538FB9933E120750CDD31DC004BB94D0CD293C47EBC98D783B17C575DEC75751F99F82C026026773534B213446B14D4978EC44CD290908CBB3AF5FF35055A5698B096F66109B60C1A39D2A34FA791E421914E0137CCA3C95872FB39DD0586F2F4EFD6D1027596199F259D76FA3727B752EE76B4FE9C4A1BE18A6E67EC1", 16);
BigInteger e = new BigInteger("010001", 16);
RsaPrivateCrtKeyParameters rsaPrivateCrtKeyParameters = GetRsaPrivateCrtKeyParameters(e, d, n);

// convert to .net native types
RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(rsaPrivateCrtKeyParameters);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);

// Decrypt using MS
byte[] ciphertext = Convert.FromBase64String("AJqdug3s19c6bi8FaQrz0Q+qLnX/7mFmaNL2ztFeZyx0yeg9+lI48qFBRoS000JHaljlhVJpjACLr/qYk4ZdZjJHD0ENJmv+lf4TmTGQZpv3uiUQpG7QbVP7c56yWK4MgyMd8EdhJLcviobShkW3lI1a46C4vF+37WzH6qvgMuuUvtPi8mi9GvhPHHuocAh05s+c5YN2R78+tpkrs05EU6fiSn3iqRnrXv48O9kxQs9S/w4xaFLgfu2wbcgyI62s2Xbri1WdfSPUIYaLmv1EvVnzBPIty4Wclun25RmB8UtH5EZXpFOGF5ER8OztCcUeTAQYP9n9W2aQOqfpIjcNMA==");
byte[] decrypted = rsa.Decrypt(ciphertext, false);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(decrypted)); // aum5d6qxevl1psj4bgkfiynchtr3ozw2:099a515a5cba1b81
© www.soinside.com 2019 - 2024. All rights reserved.