【RSA】在 ASP.NET Core中结合web前端JsEncrypt.JS使用公钥加密,.NET Core使用私钥解密;
有一个需求,前端web使用的是JsEncrypt把后端给的公钥对密码进行加密,然后后端对其进行解密;
使用的类库如下:
- 后端使用第三方开源类库Bouncy Castle进行RSA的加解密和生成PEM格式密钥对操作;
- 前端web使用JsEncrypt.js进行RSA的加解密和生成密钥对操作。
首先,由后端生成公钥,将公钥传回前端,接口保存私钥;
/// <summary> /// 生成PEM格式的公钥和密钥 /// </summary> /// <param name="strength">长度</param> /// <returns>Item2:公钥;Item1:私钥;</returns> public static (string, string) CreateKeyPair(int strength = 1024) { RsaKeyPairGenerator r = new RsaKeyPairGenerator(); r.Init(new KeyGenerationParameters(new SecureRandom(), strength)); AsymmetricCipherKeyPair keys = r.GenerateKeyPair(); TextWriter privateTextWriter = new StringWriter(); PemWriter privatePemWriter = new PemWriter(privateTextWriter); privatePemWriter.WriteObject(keys.Private); privatePemWriter.Writer.Flush(); TextWriter publicTextWriter = new StringWriter(); PemWriter publicPemWriter = new PemWriter(publicTextWriter); publicPemWriter.WriteObject(keys.Public); publicPemWriter.Writer.Flush(); return (publicTextWriter.ToString(), privateTextWriter.ToString()); }
然后前端JsEncrypt拿到公钥后进行加密:
//rsa加密随机密钥 var rsa = new JsEncrypt(); //设置后端接口传回的公钥(无需对公钥字符串做任何处理) rsa.setPublicKey("<你的公钥>"); //注意:RSA加解密有大小限制(最多117 bytes) var rsaEncrypted = rsa.encrypt("<待加密的字符串>"); //已加密的字符串(Base64) console.log('rsaEncrypted:' + rsaEncrypted);
后端接口拿到已加密的Base64进行解密:
/// <summary> /// RSA解密 /// </summary> /// <param name="privateKey">私钥</param> /// <param name="decryptstring">待解密的字符串(Base64)</param> /// <returns>解密后的字符串</returns> public static string Decrypt(string privateKey, string decryptstring) { using (TextReader reader = new StringReader(privateKey)) { dynamic key = new PemReader(reader).ReadObject(); var rsaDecrypt = new Pkcs1Encoding(new RsaEngine()); if (key is AsymmetricKeyParameter) { key = (AsymmetricKeyParameter)key; } else if (key is AsymmetricCipherKeyPair) { key = ((AsymmetricCipherKeyPair)key).Private; } rsaDecrypt.Init(false, key); //这里加密是true;解密是false byte[] entData = Convert.FromBase64String(decryptstring); entData = rsaDecrypt.ProcessBlock(entData, 0, entData.Length); return Encoding.UTF8.GetString(entData); } }
在这里有一个坑,看关键代码:
var rsaDecrypt = new Pkcs1Encoding(new RsaEngine())
与前端JsEncrypt交互一定要按照上面的方法使用Pkcs1Encoding;如果按照下面这样写解密出来的字符串会乱码:
var rsaDecrypt = new RsaEngine();
最后附上加密方法:
/// <summary> /// 加密 /// </summary> /// <param name="publicKey">公钥</param> /// <param name="encryptstring">待加密的字符串</param> /// <returns>加密后的Base64</returns> public static string Encrypt(string publicKey, string encryptstring) { using (TextReader reader = new StringReader(publicKey)) { AsymmetricKeyParameter key = new PemReader(reader).ReadObject() as AsymmetricKeyParameter; Pkcs1Encoding pkcs1 = new Pkcs1Encoding(new RsaEngine()); pkcs1.Init(true, key);//加密是true;解密是false; byte[] entData = Encoding.UTF8.GetBytes(encryptstring); entData = pkcs1.ProcessBlock(entData, 0, entData.Length); return Convert.ToBase64String(entData); } }