如何解密 .NET 中的 RSA 内容?

Dol*_*hin 4 c# encryption

我使用 OpenSSL 生成 RSA 私钥和公钥,将公钥发送到 HTML 页面以加密用户名和密码(使用JSEncrypt)。加密的内容发送到服务器以使用私钥解密。

这是我的解密函数:

public string RsaDecrypt(string xmlPrivateKey, string mStrDecryptString)
{
    string str2;
    try
    {
        RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
        provider.FromXmlString(xmlPrivateKey);
        byte[] rgb = Convert.FromBase64String(mStrDecryptString);
        byte[] buffer2 = provider.Decrypt(rgb, false);
        str2 = new UnicodeEncoding().GetString(buffer2);
    }
    catch (Exception exception)
    {
        throw exception;
    }
    
    return str2;
}
Run Code Online (Sandbox Code Playgroud)

xmlPrivateKey值为:

MIICWwIBAAKBgQCt8y+vx9Y3Iik9l/8r6x+wjcrgPskbjVpt7fSJqtpCA/XaYl/3O2uvrRUPzyqr1wA+ejsdhdm285nYSbSaHTPem1+N/JHynp+cLQiBV6a8PayOvtrSBaHLZDDhgvntk/BleplU406kiM ltnVDko33H+Y3yaNuY2TNDEMe5Z8OlUQIDAQABAoGAdYIChMyKeVQqZ+F2D0UWcz5V/oZrdKFYpUpKF3XDWzUxsAUkru8FH/fccoGQYeUr1QjdRmRVXrHRC7s+tZ1km68oiUFD6sbCYyPQy0Se95050F ncM3lEndGUJTiTelVqAYh+DPVnRURcfgA+HSvWek1/YnOZ8UNZJ36jiogSKcECQQDbRfn/UODXud7MKO7zfYOLvPhtFMgtA0Ac5w6tTJ/llZs0QtjMKCNHF9bGRxKdFvKTMA1DGBNN0chdWAc7UET/AkEAyxXUJAk1 +46fRhzTH4uXRX7SEMCwEjY79DHqE23pPx8Q8VC3j2aPETQerT4EHNzaMBg6hneJE2p7xB5Rm/SFrwJAIWasaT7psRLIJHNlyt1gr2WOthcHUwv+tShhLPbSGIfMh45zNc4baZXxCm0DIdjABLm6G3FMZ3t奥斯/ Ski9tAwJAMYWQJn1sgXwk0KcEwIN8jsC/HsCt7rL06bYmOzipEPBVZFLnf/tlVa+c72fY/uTH+8RcuR96+JYVuhwekGYPFwJAQXbsOkyVTvZGcqRk9+SF7AUsGchHYPrimH6iafYEBsVCorMJfjE ai0zmd/9A1j+NHFq31KPAQGV0zHmV2NXscDg==


mStrDecryptString 是:

fW9H+/Nz/yp6my/EwY0I+KP1CX/QPY8TL3bFDvfJYJDJ50LHEPfiR/RGhHl9rvViXOgD4IiXYF2/KbNPQNmno+Bioi3r8Xc5+PVNyFDJy+X4/YjX4O830g9vAhyRJ1RKbJOmJYWT4sdP0jfx waRL2+FAl6yIsrcsH/7bRZvjDTU=

在服务器端解密时,报错:

第 1 行语法无效。

我该如何做才能使它正确?

Dol*_*hin 5

OpenSSL生成的RSA格式与.NET不同,您应该将OpenSSL RSA转换xmlPrivateKey为XML格式,以便.NET可以识别它RSACryptoServiceProvider。

private static RSACryptoServiceProvider DecodeRsaPrivateKey(string priKey)
{
    var privkey = Convert.FromBase64String(priKey);
    byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;

    // ---------  Set up stream to decode the asn.1 encoded RSA private key  ------
    var mem = new MemoryStream(privkey);
    var binr = new BinaryReader(mem);   // wrap Memory Stream with BinaryReader for easy reading
    try
    {
        var twobytes = binr.ReadUInt16();
        if (twobytes == 0x8130)     // data read as little endian order (actual data order for Sequence is 30 81)
            binr.ReadByte();        // advance 1 byte
        else if (twobytes == 0x8230)
            binr.ReadInt16();       // advance 2 bytes
        else
            return null;
        
        twobytes = binr.ReadUInt16();
        if (twobytes != 0x0102)     // version number
            return null;
            
        var bt = binr.ReadByte();
        if (bt != 0x00)
            return null;

        //------  all private key components are Integer sequences ----
        var elems = GetIntegerSize(binr);
        MODULUS = binr.ReadBytes(elems);

        elems = GetIntegerSize(binr);
        E = binr.ReadBytes(elems);

        elems = GetIntegerSize(binr);
        D = binr.ReadBytes(elems);

        elems = GetIntegerSize(binr);
        P = binr.ReadBytes(elems);

        elems = GetIntegerSize(binr);
        Q = binr.ReadBytes(elems);

        elems = GetIntegerSize(binr);
        DP = binr.ReadBytes(elems);

        elems = GetIntegerSize(binr);
        DQ = binr.ReadBytes(elems);

        elems = GetIntegerSize(binr);
        IQ = binr.ReadBytes(elems);

        // ------- create RSACryptoServiceProvider instance and initialize with public key -----
        var rsa = new RSACryptoServiceProvider();
        var rsAparams = new RSAParameters
        {
            Modulus = MODULUS,
            Exponent = E,
            D = D,
            P = P,
            Q = Q,
            DP = DP,
            DQ = DQ,
            InverseQ = IQ
        };
        rsa.ImportParameters(rsAparams);
        
        return rsa;
    }
    catch (Exception e)
    {
        LogHelper.Logger.Error("DecodeRsaPrivateKey failed", e);
        return null;
    }
    finally
    {
        binr.Close();
    }
}


private static int GetIntegerSize(BinaryReader binary)
{
    byte binaryReadByte = 0;
    var count = 0;
    
    binaryReadByte = binary.ReadByte();
    if (binaryReadByte != 0x02)      // expect integer
        return 0;
        
    binaryReadByte = binary.ReadByte();
    if (binaryReadByte == 0x81)
    {
        count = binary.ReadByte();   // data size in next byte
    }
    else
    {
        if (binaryReadByte == 0x82)
        {
            var highbyte = binary.ReadByte();
            var lowbyte = binary.ReadByte();
            byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
            count = BitConverter.ToInt32(modint, 0);
        }
        else
        {
            count = binaryReadByte; // we already have the data size
        }
    }
    
    while (binary.ReadByte() == 0x00)
    {    //remove high order zeros in data
        count -= 1;
    }
    binary.BaseStream.Seek(-1, SeekOrigin.Current);   // last ReadByte wasn't a removed zero, so back up a byte
    
    return count;
}
Run Code Online (Sandbox Code Playgroud)

所以RSACryptoServiceProvider可以解密原始上下文。