• 在 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


    输了你,赢了世界又如何...
  • 相关阅读:
    时间处理得到UTC时间
    java数据同步陷阱
    360公司2016笔试题
    YTU 1439: 2.4.5 Fractions to Decimals 分数化小数
    YTU 2422: C语言习题 n个数逆序
    YTU 2421: C语言习题 矩形法求定积分
    YTU 2427: C语言习题 整数排序
    YTU 2832: 使用指针访问数组元素--程序填空
    YTU 1050: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换
    HDU 1069:Monkey and Banana
  • 原文地址:https://www.cnblogs.com/xwgli/p/15659454.html
Copyright © 2020-2023  润新知