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