1. 前言javascript
本問是根據網上不少文章的總結獲得的。html
2. 介紹前端
RSA加密算法是一種非對稱加密算法。java
對極大整數作因數分解的難度決定了RSA算法的可靠性。換言之,對一極大整數作因數分解愈困難,RSA算法愈可靠。假若有人找到一種快速因數分解的算法的話,那麼用RSA加密的信息的可靠性就確定會極度降低。但找到這樣的算法的可能性是很是小的。今天只有短的RSA鑰匙纔可能被強力方式解破。到2016年爲止,世界上尚未任何可靠的攻擊RSA算法的方式。只要其鑰匙的長度足夠長,用RSA加密的信息其實是不能被解破的。jquery
1983年麻省理工學院在美國爲RSA算法申請了專利。這個專利2000年9月21日失效。因爲該算法在申請專利前就已經被髮表了,在世界上大多數其它地區這個專利權不被認可。web
3. 開始ajax
1)在線RSA加密,請選用PKCS#1來生成公鑰與私鑰算法
http://web.chacuo.net/netrsakeypairjson
點擊【生成祕鑰對RSA】就能夠生成對應的非對稱加密公鑰與非對稱加密似鑰後端
2)前端JS框架
http://travistidwell.com/jsencrypt/
3)流程圖
從上圖能夠看到,先從網站上生成publicKey與privateKey。
第一步返回publicKey前端,用來對password等敏感字段的加密。
第二步,前端進行password敏感字段的加密。
第三步post數據給後端。
第四步用publicKey與privateKey進行解密。
4.代碼
這裏的代碼是簡單的直接從前端訪問後臺,後臺進行解密。邏輯根據讀者的愛好編寫。
前端代碼
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script src="http://code.jquery.com/jquery-1.8.3.min.js"></script> <script src="http://passport.cnblogs.com/scripts/jsencrypt.min.js"></script> <script type="text/javascript"> // 使用jsencrypt類庫加密js方法, function encryptRequest(reqUrl, data, publicKey) { var encrypt = new JSEncrypt(); encrypt.setPublicKey(publicKey); // ajax請求發送的數據對象 var sendData = new Object(); // 將data數組賦給ajax對象 for (var key in data) { sendData[key] = encrypt.encrypt(data[key]); } $.ajax({ url: reqUrl, type: 'post', data: sendData, dataType: 'json', //contentType: 'application/json; charset=utf-8', success: function (data) { console.info(data); }, error: function (xhr) { //console.error('出錯了'); } }); } // Call this code when the page is done loading. $(function () { $('#testme').click(function () { var data = []; data['username'] = $('#username').val(); data['passwd'] = $('#passwd').val(); var pkey = $('#pubkey').val(); encryptRequest('/WebForm2.aspx', data, pkey); }); }); </script> </head> <body> <form id="form1" runat="server"> <div> <label for="pubkey">Public Key</label><br /> <textarea id="pubkey" rows="15" cols="65"> MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDbrIgHK8qkz5IfK/A7At4SVZQ 31TalDPsc4vzeDVjd5ao46hcf+eOEQNm8jmxxHTm6WPSTy7RDVXG/NI489L9okkd K++kVh2Z9GjBo5jw/n9EYojt8aYyEOc6cMHT2Fv+1smG+X/W2HeXXoJJjcFLSjBe CKx1SoCD4+B2ZiDQ8wIDAQAB </textarea><br /> <label for="input">Text to encrypt:</label><br /> name:<input id="username" name="username" type="text"></input><br /> password:<input id="passwd" name="passwd" type="password"></input><br /> <input id="testme" type="button" value="submit" /><br /> </div> </form> </body> </html>
後端代碼
解密
private RSACrypto rsaCrypto = new RSACrypto(PublicAttribute.PrivateKey, PublicAttribute.PublicKey); //獲取參數 string usernameEncode = Request["username"]; string pwdEncode = Request["pwd"]; //解密 RSA string username = rsaCrypto.Decrypt(usernameEncode); string pwd = rsaCrypto.Decrypt(pwdEncode);
類 RSACrypto
public class RSACrypto { private RSACryptoServiceProvider _privateKeyRsaProvider; private RSACryptoServiceProvider _publicKeyRsaProvider; public RSACrypto(string privateKey, string publicKey = null) { if (!string.IsNullOrEmpty(privateKey)) { _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey); } if (!string.IsNullOrEmpty(publicKey)) { _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey); } } public string Decrypt(string cipherText) { if (_privateKeyRsaProvider == null) { throw new Exception("_privateKeyRsaProvider is null"); } return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(System.Convert.FromBase64String(cipherText), false)); } public string Encrypt(string text) { if (_publicKeyRsaProvider == null) { throw new Exception("_publicKeyRsaProvider is null"); } return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), false)); } private RSACryptoServiceProvider CreateRsaProviderFromPrivateKey(string privateKey) { var privateKeyBits = System.Convert.FromBase64String(privateKey); var RSA = new RSACryptoServiceProvider(); var RSAparams = new RSAParameters(); using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits))) { byte bt = 0; ushort twobytes = 0; twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) binr.ReadByte(); else if (twobytes == 0x8230) binr.ReadInt16(); else throw new Exception("Unexpected value read binr.ReadUInt16()"); twobytes = binr.ReadUInt16(); if (twobytes != 0x0102) throw new Exception("Unexpected version"); bt = binr.ReadByte(); if (bt != 0x00) throw new Exception("Unexpected value read binr.ReadByte()"); RSAparams.Modulus = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.Exponent = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.D = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.P = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.Q = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.DP = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.DQ = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.InverseQ = binr.ReadBytes(GetIntegerSize(binr)); } RSA.ImportParameters(RSAparams); return RSA; } private int GetIntegerSize(BinaryReader binr) { byte bt = 0; byte lowbyte = 0x00; byte highbyte = 0x00; int count = 0; bt = binr.ReadByte(); if (bt != 0x02) return 0; bt = binr.ReadByte(); if (bt == 0x81) count = binr.ReadByte(); else if (bt == 0x82) { highbyte = binr.ReadByte(); lowbyte = binr.ReadByte(); byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; count = BitConverter.ToInt32(modint, 0); } else { count = bt; } while (binr.ReadByte() == 0x00) { count -= 1; } binr.BaseStream.Seek(-1, SeekOrigin.Current); return count; } private RSACryptoServiceProvider CreateRsaProviderFromPublicKey(string publicKeyString) { // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1" byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; byte[] x509key; byte[] seq = new byte[15]; int x509size; x509key = Convert.FromBase64String(publicKeyString); x509size = x509key.Length; // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------ using (MemoryStream mem = new MemoryStream(x509key)) { using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading { byte bt = 0; ushort twobytes = 0; twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) binr.ReadByte(); //advance 1 byte else if (twobytes == 0x8230) binr.ReadInt16(); //advance 2 bytes else return null; seq = binr.ReadBytes(15); //read the Sequence OID if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct return null; twobytes = binr.ReadUInt16(); if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81) binr.ReadByte(); //advance 1 byte else if (twobytes == 0x8203) binr.ReadInt16(); //advance 2 bytes else return null; bt = binr.ReadByte(); if (bt != 0x00) //expect null byte next return null; twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) binr.ReadByte(); //advance 1 byte else if (twobytes == 0x8230) binr.ReadInt16(); //advance 2 bytes else return null; twobytes = binr.ReadUInt16(); byte lowbyte = 0x00; byte highbyte = 0x00; if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81) lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus else if (twobytes == 0x8202) { highbyte = binr.ReadByte(); //advance 2 bytes lowbyte = binr.ReadByte(); } else return null; byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order int modsize = BitConverter.ToInt32(modint, 0); int firstbyte = binr.PeekChar(); if (firstbyte == 0x00) { //if first byte (highest order) of modulus is zero, don't include it binr.ReadByte(); //skip this null byte modsize -= 1; //reduce modulus buffer size by 1 } byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data return null; int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values) byte[] exponent = binr.ReadBytes(expbytes); // ------- create RSACryptoServiceProvider instance and initialize with public key ----- RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSAParameters RSAKeyInfo = new RSAParameters(); RSAKeyInfo.Modulus = modulus; RSAKeyInfo.Exponent = exponent; RSA.ImportParameters(RSAKeyInfo); return RSA; } } } private bool CompareBytearrays(byte[] a, byte[] b) { if (a.Length != b.Length) return false; int i = 0; foreach (byte c in a) { if (c != b[i]) return false; i++; } return true; } }
到此結束了。
能夠關注本人的公衆號,多年經驗的原創文章共享給你們。