有一個需求,前端web使用的是JsEncrypt把後端給的公鑰對密碼進行加密,而後後端對其進行解密;前端
使用的類庫以下:git
首先,由後端生成公鑰,將公鑰傳回前端,接口保存私鑰;github
/// <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拿到公鑰後進行加密:web
//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); } }
在這裏有一個坑,看關鍵代碼:
dom
var rsaDecrypt = new Pkcs1Encoding(new RsaEngine())
與前端JsEncrypt交互必定要按照上面的方法使用Pkcs1Encoding;若是按照下面這樣寫解密出來的字符串會亂碼:加密
var rsaDecrypt = new RsaEngine();
最後附上加密方法:spa
/// <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); } }