在 javascript 中使用 jsencrypt 与 在 .net(framework 和 core 均支持)中使用 BouncyCastle,进行 rsa 的加密解密

jsencrypt 是 Javascript 下的 RSA 加解密插件:https://github.com/travist/jsencrypt

BouncyCastle 是 .NET 中的 RSA 加解密插件:https://www.bouncycastle.org/csharp/index.html

密钥对使用的是 jsencrypt 支持的 openssl pem 格式,BouncyCastle 各种其实都支持,且支持进行转换

但直接使用 jsencrypt 公钥加密后,使用 BouncyCastle 的 RsaEngine 类私钥解密会发现解密虽然成功,但在有效数据前,有一堆乱码字符

这是因为对加解密数据的格式定义不同导致的

BouncyCastle 也支持不同的数据格式,通过 XXXEncoding 来提供支持,初始化时直接传入 RsaEngine 作为算法即可,这里使用的是 PKCS1Encoding。

jsencrypt 示例代码:

function rsaEncrypt(dataString) {

    // 加密
    var encrypt = new JSEncrypt();
    encrypt.setPublicKey(rsaPubKey);
    var encrypted = encrypt.encrypt(dataString);

    return encrypted;
}

BouncyCastle 示例代码:

/// <summary>
/// 使用 BouncyCastle 进行 RSA 运算
/// </summary>
public class BouncyCastleHelper
{
    /// <summary>
    /// 生成 PEM 格式字符串的 RSA 密钥对
    /// </summary>
    /// <returns></returns>
    public static (string publicKey, string privateKey) GenerateRsaKeyPairInPem()
    {
        // 生成密钥对
        RsaKeyPairGenerator generator = new RsaKeyPairGenerator();
        generator.Init(new KeyGenerationParameters(new SecureRandom(), 1024));
        AsymmetricCipherKeyPair keys = generator.GenerateKeyPair();

        // 输出私钥
        TextWriter textWriter = new StringWriter();
        PemWriter pemWriter = new PemWriter(textWriter);
        pemWriter.WriteObject(keys.Private);
        pemWriter.Writer.Flush();

        // 输出公钥
        TextWriter textpubWriter = new StringWriter();
        PemWriter pempubWriter = new PemWriter(textpubWriter);
        pempubWriter.WriteObject(keys.Public);
        pempubWriter.Writer.Flush();

        // 返回字符串
        var privateKey = textWriter.ToString();
        var publicKey = textpubWriter.ToString();
        return (publicKey, privateKey);
    }

    /// <summary>
    /// 使用 PEM 格式私钥解密 PKCS1 格式封装的 RSA 加密数据,返回字符串(UTF8 格式编码)
    /// </summary>
    /// <param name="privateKeyInPem">PEM 格式私钥</param>
    /// <param name="encryptedDataInBase64">使用 Base64 存储的加密数据</param>
    /// <returns></returns>
    public static string DecryptUtf8StringByRsaPkcs1FromBase64StringUsingPrivateKeyInPem(string privateKeyInPem, string encryptedDataInBase64)
    {
        using (TextReader reader = new StringReader(privateKeyInPem))
        {
            // 因私钥中包含了公钥,故此处为获取密钥对
            var keyPair = new PemReader(reader).ReadObject() as AsymmetricCipherKeyPair;

            // 加密数据使用 PKCS1 格式封装
            var pkcs1 = new Pkcs1Encoding(new RsaEngine());

            // 此处 false 为解密,且标明使用私钥
            pkcs1.Init(false, keyPair.Private);

            // 从 base64 字符串中获取数据
            byte[] encryptedData = Convert.FromBase64String(encryptedDataInBase64);

            // 此处需注意一次性处理的数据长度不能大于密钥
            var decryptedData = pkcs1.ProcessBlock(encryptedData, 0, encryptedData.Length);

            // 此处若有非英文字符,需注意加密解密保持相同的字符编码,否则结果可能为乱码
            var decryptedString = Encoding.UTF8.GetString(decryptedData);

            // 返回结果
            return decryptedString;
        }
    }
}

生成的 RSA 密钥对(PEM 格式)示例:

公钥:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDbS+6FK25ikjJjPEIDFU26xZrP27PjiHwnh2d/wHAOLrtDRqJu
Ky9t0yPFc7eT4ZAhEXVPE9CLGXCEgMqTyXqfht7DY4qR1s1yKz+WeC1jw73yXGFI
AakrqLrtrXPk+DnW9e/QcM2ksmVJDSGrlP/NkB7btINIlaCQ+NOJin69HwIDAQAB
AoGAbxUGbER0tM+TYHsMgR1Qc1RXOAT1GUNwiGFpRugGmtiHGOv1qVKMwtfZ3dHg
4rK2XFnIj1bdIyiuux+1/ahoSOhJWkz2W8+WLZsifI3uaPcCZ1djcqZGZ899VIN0
Hn8zdCp66ubVaBCBLzbLbF/ng7vxaqxAJWpffziVDEza2pkCQQD1nMYFIVnjDjmS
52aop1XOnJ+CAzmMLPYORP0GRmfW8rxlen9U1WyquAmXdozvHLx2ZMfXymtICVWK
e7ndms97AkEA5JI9O7wejvcFMf0N3nIc/+CRL93r1hRbf6l5640Q5WPrQSby/+G9
kkg0q94xI0MWAlwXoMQsEo1HmWb1JX9lrQJBAKc7srzlg32NPvhepNCq90rx682r
gnCGYJdAtAOkxqldp5d0++P4WcA4BRfjOXzJ1SzL3CJ7CecHq/3Z1qkj8qcCQQDZ
PkkmylC9DvkIHv0cjJcVeApmVWW+blDc0GaJw+ToMYS6wts46wRz0V8Gb0OCwVNc
4MywR2OgKll/6sRbZG9tAkANU1eQ1Lprlz6lhO9lq0N4whq7b87Ip06Q4Ol0TU58
3+HNcqLrzdt67V/gVZcpkND9UiDOjWrs7NPkxaP2P45e
-----END RSA PRIVATE KEY-----

私钥:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbS+6FK25ikjJjPEIDFU26xZrP
27PjiHwnh2d/wHAOLrtDRqJuKy9t0yPFc7eT4ZAhEXVPE9CLGXCEgMqTyXqfht7D
Y4qR1s1yKz+WeC1jw73yXGFIAakrqLrtrXPk+DnW9e/QcM2ksmVJDSGrlP/NkB7b
tINIlaCQ+NOJin69HwIDAQAB
-----END PUBLIC KEY-----

参考:https://www.cnblogs.com/runliuv/p/5965951.html

https://blog.csdn.net/mingtiannihao0522/article/details/117474208

https://stackoverflow.com/questions/56489992/how-do-i-use-bouncy-castle-in-net-to-encrypt-using-rsa-ecb-oaepwithsha256andmgf

https://stackoverflow.com/questions/39372280/how-to-decrypt-rsa-encrypted-string-from-jsencrypt-using-c-sharp-bouncycastle

https://stackoverflow.com/a/27743892


输了你,赢了世界又如何...
原文地址:https://www.cnblogs.com/xwgli/p/15659454.html