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