首先上资源
jsencrypt.js下载地址:https://github.com/travist/jsencrypt
第三方Rsa密钥生成工具:BouncyCastle.Crypto.dll,直接可以在NuGet中查找。
至于为什么用第三方工具生成密钥,是为了和jsencrypt配合。c#本身RSACryptoServiceProvider类生成的工具不能再jsencrypt中使用。
并且:(信息来源:https://www.jianshu.com/p/f22b4e565ec1)文中的生成RSAParameters方法来源于此。
-
RSACryptoServiceProvider
在Windows 环境下依然可以使用RSACryptoServiceProvider
, 但在Linux 环境下编译不过. 参考 dudu 的文章 .net core中使用openssl的公钥私钥进行加解密 -
FromXmlString方法和ToXmlString
由于不在使用RSACryptoServiceProvider
这两个方法不在提供,我们可以通过扩展方法来添加这两个方法,以处理C#生成的密钥.
这边引用BouncyCastle.Crypto.dll会在NuGet里有个警告提示,如图:
我在Centos7,和windows10 里测试过,可以使用,其他就不懂了。
这是BouncyCastle.Crypto.dll在NuGet相关信息:
好了开始上代码。
使用BouncyCastle.Crypto.dll生成PEM密钥
1 public struct RSAKey 2 { 3 public string privateKey { get; set; } 4 5 public string publicKey { get; set; } 6 } 7 8 public static RSAKey GetKey() 9 { 10 var key = new RSAKey(); 11 Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator g = new Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator(); 12 g.Init(new Org.BouncyCastle.Crypto.KeyGenerationParameters(new SecureRandom(), 1024)); 13 var pair = g.GenerateKeyPair(); 14 PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private); 15 byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetDerEncoded(); 16 key.privateKey = Convert.ToBase64String(serializedPrivateBytes);//PEM秘钥 17 18 SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pair.Public); 19 byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded(); 20 key.publicKey = Convert.ToBase64String(serializedPublicBytes);//PEM公钥 21 22 return key; 23 }
然后是将Pem密钥转换为Xml数据
1 public static string RSAXmlPrivateKey(string privateKey) 2 { 3 RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)); 4 5 return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>", 6 Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()), 7 Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()), 8 Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()), 9 Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()), 10 Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()), 11 Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()), 12 Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()), 13 Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())); 14 } 15 16 public static string RSAXmlPublicKey(string publicKey) 17 { 18 RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); 19 return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>", 20 Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), 21 Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); 22 }
一个通用生成RSAParameters方法
public static RSAParameters FromXmlString( string xmlString) { RSAParameters parameters = new RSAParameters(); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlString); if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")) { foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) { switch (node.Name) { case "Modulus": parameters.Modulus = Convert.FromBase64String(node.InnerText); break; case "Exponent": parameters.Exponent = Convert.FromBase64String(node.InnerText); break; case "P": parameters.P = Convert.FromBase64String(node.InnerText); break; case "Q": parameters.Q = Convert.FromBase64String(node.InnerText); break; case "DP": parameters.DP = Convert.FromBase64String(node.InnerText); break; case "DQ": parameters.DQ = Convert.FromBase64String(node.InnerText); break; case "InverseQ": parameters.InverseQ = Convert.FromBase64String(node.InnerText); break; case "D": parameters.D = Convert.FromBase64String(node.InnerText); break; } } } else { throw new Exception("Invalid XML RSA key."); } return parameters; }
C#后端加密解密方法
//加密
public static string RSA_Encrypt(string context, RSAKey key) { UnicodeEncoding ByteConverter = new UnicodeEncoding(); byte[] DataToEncrypt = ByteConverter.GetBytes(context); try { RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSA.ImportParameters(FromXmlString(RSAXmlPublicKey( key.publicKey)));//OAEP padding is only available on Microsoft Windows XP or later. byte[] bytes_Cypher_Text = RSA.Encrypt(DataToEncrypt, false); string str_Cypher_Text = Convert.ToBase64String(bytes_Cypher_Text); return str_Cypher_Text; } catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } }
//RSA解密 public static string RSA_Decrypt(string context, string str_Private_Key) { byte[] DataToDecrypt = Convert.FromBase64String(context); try { RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSA.ImportParameters(FromXmlString(RSAPrivateKeyJava2DotNet(str_Private_Key)));//OAEP padding is only available on Microsoft Windows XP or later. byte[] bytes_Plain_Text = RSA.Decrypt(DataToDecrypt, false); UnicodeEncoding ByteConverter = new UnicodeEncoding(); string str_Plain_Text = ByteConverter.GetString(bytes_Plain_Text); return str_Plain_Text; } catch (CryptographicException e) { Console.WriteLine(e.ToString()); return null; } }
ok以上就是后端代码;
前段代码就简单了,这个是jsencrypt官方的demo。
<!doctype html> <html> <head> <title>JavaScript RSA Encryption</title> <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script> <script src="bin/jsencrypt.min.js"></script> <script type="text/javascript"> // Call this code when the page is done loading. $(function() { // Run a quick encryption/decryption when they click. $(‘#testme‘).click(function() { // Encrypt with the public key... var encrypt = new JSEncrypt(); encrypt.setPublicKey($(‘#pubkey‘).val()); var encrypted = encrypt.encrypt($(‘#input‘).val()); // Decrypt with the private key... var decrypt = new JSEncrypt(); decrypt.setPrivateKey($(‘#privkey‘).val()); var uncrypted = decrypt.decrypt(encrypted); // Now a simple check to see if the round-trip worked. if (uncrypted == $(‘#input‘).val()) { alert(‘It works!!!‘); } else { alert(‘Something went wrong....‘); } }); }); </script> </head> <body> <label for="privkey">Private Key</label><br/> <textarea id="privkey" rows="15" cols="65">-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQ WMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNR aY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQAB AoGAfY9LpnuWK5Bs50UVep5c93SJdUi82u7yMx4iHFMc/Z2hfenfYEzu+57fI4fv xTQ//5DbzRR/XKb8ulNv6+CHyPF31xk7YOBfkGI8qjLoq06V+FyBfDSwL8KbLyeH m7KUZnLNQbk8yGLzB3iYKkRHlmUanQGaNMIJziWOkN+N9dECQQD0ONYRNZeuM8zd 8XJTSdcIX4a3gy3GGCJxOzv16XHxD03GW6UNLmfPwenKu+cdrQeaqEixrCejXdAF z/7+BSMpAkEA8EaSOeP5Xr3ZrbiKzi6TGMwHMvC7HdJxaBJbVRfApFrE0/mPwmP5 rN7QwjrMY+0+AbXcm8mRQyQ1+IGEembsdwJBAN6az8Rv7QnD/YBvi52POIlRSSIM V7SwWvSK4WSMnGb1ZBbhgdg57DXaspcwHsFV7hByQ5BvMtIduHcT14ECfcECQATe aTgjFnqE/lQ22Rk0eGaYO80cc643BXVGafNfd9fcvwBMnk0iGX0XRsOozVt5Azil psLBYuApa66NcVHJpCECQQDTjI2AQhFc1yRnCU/YgDnSpJVm1nASoRUnU8Jfm3Oz uku7JUXcVpt08DFSceCEX9unCuMcT72rAQlLpdZir876 -----END RSA PRIVATE KEY-----</textarea><br/> <label for="pubkey">Public Key</label><br/> <textarea id="pubkey" rows="15" cols="65">-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtN FOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76 xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4 gwQco1KRMDSmXSMkDwIDAQAB -----END PUBLIC KEY-----</textarea><br/> <label for="input">Text to encrypt:</label><br/> <textarea id="input" name="input" type="text" rows=4 cols=70>This is a test!</textarea><br/> <input id="testme" type="button" value="Test Me!!!" /><br/> </body> </html>
打完,收功,希望能给大家带来一点用处^_^