在 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM