敏感數據加密方案及實現

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在是大數據時代,需要收集大量的個人信息用於統計。一方面它給我們帶來了便利,另一方面一些個人信息數據在無意間被泄露,被非法分子用於推銷和黑色產業。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2018 年 5 月 25 日,歐盟已經強制執行《通用數據保護條例》(General Data Protection Regulation,縮寫作 GDPR)。該條例是歐盟法律中對所有歐盟個人關於數據保護和隱私的規範。這意味着個人數據必須使用假名化或匿名化進行存儲,並且默認使用盡可能最高的隱私設置,以避免數據泄露。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相信大家也都不想讓自己在外面“裸奔”。所以,作爲前端開發人員也應該儘量避免用戶個人數據的明文傳輸,儘可能的降低信息泄露的風險。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看到這裏可能有人會說現在都用 HTTPS 了,數據在傳輸過程中是加密的,前端就不需要加密了。其實不然,我可以在你發送 HTTPS 請求之前,通過谷歌插件來捕獲 HTTPS 請求中的個人信息,下面我會爲此演示。所以前端數據加密還是很有必要的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"數據泄露方式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"中間人攻擊"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"中間人攻擊是常見的攻擊方式。詳細過程可以參見這裏:https:\/\/zh.wikipedia.org\/wiki\/%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB。大概的過程是中間人通過 DNS 欺騙等手段劫持了客戶端與服務端的會話。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"客戶端、服務端之間的信息都會經過中間人,中間人可以獲取和轉發兩者的信息。在 HTTP 下,前端數據加密還是避免不了數據泄露,因爲中間人可以僞造密鑰。爲了避免中間人攻擊,我們一般採用 HTTPS 的形式傳輸。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"谷歌插件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"HTTPS 雖然可以防止數據在網絡傳輸過程中被劫持,但是在發送 HTTPS 之前,數據還是可以從谷歌插件中泄露出去。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲谷歌插件可以捕獲 Network 中的所有請求,所以如果某些插件中有惡意的代碼還是可以獲取到用戶信息的,下面爲大家演示。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/7e\/7eaeaf43768cc2398df6662797bd372e.gif","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以光采用 HTTPS,一些敏感信息如果還是以明文的形式傳輸的話,也是不安全的。如果在 HTTPS 的基礎上再進行數據的加密,那相對來說就更好了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"加密算法介紹"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對稱加密"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對稱加密算法,又稱爲共享密鑰加密算法。在對稱加密算法中,使用的密鑰只有一個,發送和接收雙方都使用這個密鑰對數據進行加密和解密。"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這就要求加密和解密方事先都必須知道加密的密鑰。其優點是算法公開、計算量小、加密速度快、加密效率高;缺點是密鑰泄露之後,數據就會被破解。一般不推薦單獨使用。根據實現機制的不同,常見的算法主要有 "},{"type":"text","marks":[{"type":"strong"}],"text":"AES"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86)、"},{"type":"text","marks":[{"type":"strong"}],"text":"ChaCha20"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/Salsa20#ChaCha20)、"},{"type":"text","marks":[{"type":"strong"}],"text":"3DES"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/3DES)等。"}]}]}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/cb\/cbb5d18b6e469a2edd2d35fb44f88cec.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"非對稱加密"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"非對稱加密算法,又稱爲公開密鑰加密算法。它需要兩個密鑰,一個稱爲公開密鑰 (public key),即公鑰;另一個稱爲私有密鑰 (private key),即私鑰。"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"他倆是配對生成的,就像鑰匙和鎖的關係。因爲加密和解密使用的是兩個不同的密鑰,所以這種算法稱爲非對稱加密算法。其優點是算法強度複雜、安全性高;缺點是加解密速度沒有對稱加密算法快。常見的算法主要有 "},{"type":"text","marks":[{"type":"strong"}],"text":"RSA"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95)、"},{"type":"text","marks":[{"type":"strong"}],"text":"Elgamal"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/ElGamal%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95)等。"}]}]}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0d\/0d1afa543ff2573f1b52f97e7772462c.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"散列算法"}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"散列算法又稱散列函數、哈希函數,是把消息或數據壓縮成摘要,使得數據量變小,將數據的格式固定成特定長度的值。一般用於校驗數據的完整性,平時我們下載文件就可以校驗 MD5 來判斷下載的數據是否完整。常見的算法主要有 "},{"type":"text","marks":[{"type":"strong"}],"text":"MD4"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/MD4)、"},{"type":"text","marks":[{"type":"strong"}],"text":"MD5"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/MD5)、"},{"type":"text","marks":[{"type":"strong"}],"text":"SHA"},{"type":"text","text":" (https:\/\/zh.wikipedia.org\/wiki\/SHA%E5%AE%B6%E6%97%8F) 等。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"實現方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方案一:如果用對稱加密,那麼服務端和客戶端都必須知道密鑰纔行。那服務端勢必要把密鑰發送給客戶端,這個過程中是不安全的,所以單單用對稱加密行不通。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方案二:如果用非對稱加密,客戶端的數據通過公鑰加密,服務端通過私鑰解密,客戶端發送數據實現加密沒問題。客戶端接受數據,需要服務端用公鑰加密,然後客戶端用私鑰解密。所以這個方案需要兩套公鑰和私鑰,需要在客戶端和服務端各自生成自己的密鑰。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0e\/0eaf75d6ae7c8ce5fce13ae58bf952cb.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方案三:如果把對稱加密和非對稱加密相結合。客戶端需要生成一個對稱加密的密鑰 1,傳輸內容與該密鑰 1進行對稱加密傳給服務端,並且把密鑰 1 和公鑰進行非對稱加密,然後也傳給服務端。服務端通過私鑰把對稱加密的密鑰 1 解密出來,然後通過該密鑰 1 解密出內容。以上是客戶端到服務端的過程。如果是服務端要發數據到客戶端,就需要把響應數據跟對稱加密的密鑰 1 進行加密,然後客戶端接收到密文,通過客戶端的密鑰 1 進行解密,從而完成加密傳輸。"}]}]}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/60\/605e3d7e40372f3c1ccf0ad5aae95242.webp","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結:以上只是列舉了常見的加密方案。總的來看,方案二比較簡單,但是需要維護兩套公鑰和私鑰,當公鑰變化的時候,必須通知對方,靈活性比較差。方案三相對方案二來說,密鑰 1 隨時可以變化,並且不需要通知服務端,相對來說靈活性、安全性好點並且方案三對內容是對稱加密,當數據量大時,對稱加密的速度會比非對稱加密快。所以本文采用方案三給予代碼實現。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"代碼實現"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面是具體的代碼實現(以登錄接口爲例),主要的目的就是要把明文的個人信息轉成密文傳輸。其中對稱加密庫使用的是 AES,非對稱加密庫使用的是RSA。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"客戶端:"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AES 庫(aes-js):https:\/\/github.com\/ricmoo\/aes-js"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RSA庫(jsencrypt):https:\/\/github.com\/travist\/jsencrypt"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"具體代碼實現登錄接口"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1、客戶端需要隨機生成一個 aesKey,在頁面加載完的時候需要從服務端請求 publicKey"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let aesKey = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; \/\/ 隨機產生\nlet publicKey = \"\"; \/\/ 公鑰會從服務端獲取\n\n\/\/ 頁面加載完之後,就去獲取公鑰\nwindow.onload = () => {\n axios({\n method: \"GET\",\n headers: { \"content-type\": \"application\/x-www-form-urlencoded\" },\n url: \"http:\/\/localhost:3000\/getPub\",\n })\n .then(function (result) {\n publicKey = result.data.data; \/\/ 獲取公鑰\n })\n .catch(function (error) {\n console.log(error);\n });\n};"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2、aes 加密和解密方法"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\/**\n * aes加密方法\n * @param {string} text 待加密的字符串\n * @param {array} key 加密key\n *\/\nfunction aesEncrypt(text, key) {\n const textBytes = aesjs.utils.utf8.toBytes(text); \/\/ 把字符串轉換成二進制數據\n\n \/\/ 這邊使用CTR-Counter加密模式,還有其他模式可以選擇,具體可以參考aes加密庫\n const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));\n\n const encryptedBytes = aesCtr.encrypt(textBytes); \/\/ 進行加密\n const encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes); \/\/ 把二進制數據轉成十六進制\n\n return encryptedHex;\n}\n\n\/**\n * aes解密方法\n * @param {string} encryptedHex 加密的字符串\n * @param {array} key 加密key\n *\/\nfunction aesDecrypt(encryptedHex, key) {\n const encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex); \/\/ 把十六進制數據轉成二進制\n const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));\n\n const decryptedBytes = aesCtr.decrypt(encryptedBytes); \/\/ 進行解密\n const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes); \/\/ 把二進制數據轉成utf-8字符串\n\n return decryptedText;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3、請求登錄"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\/**\n * 登陸接口\n *\/\nfunction submitFn() {\n const userName = document.querySelector(\"#userName\").value;\n const password = document.querySelector(\"#password\").value;\n const data = {\n userName,\n password,\n };\n\n const text = JSON.stringify(data);\n const sendData = aesEncrypt(text, aesKey); \/\/ 把要發送的數據轉成字符串進行加密\n console.log(\"發送數據\", text);\n\n const encrypt = new JSEncrypt();\n encrypt.setPublicKey(publicKey);\n const encrypted = encrypt.encrypt(aesKey.toString()); \/\/ 把aesKey進行非對稱加密\n\n const url = \"http:\/\/localhost:3000\/login\";\n const params = { id: 0, data: { param1: sendData, param2: encrypted } };\n\n axios({\n method: \"POST\",\n headers: { \"content-type\": \"application\/x-www-form-urlencoded\" },\n url: url,\n data: JSON.stringify(params),\n })\n .then(function (result) {\n const reciveData = aesDecrypt(result.data.data, aesKey); \/\/ 用aesKey進行解密\n console.log(\"接收數據\", reciveData);\n })\n .catch(function (error) {\n console.log(\"error\", error);\n });\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務端(Node):"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AES庫(aes-js):https:\/\/github.com\/ricmoo\/aes-js"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RSA 庫(node-rsa):https:\/\/github.com\/rzcoder\/node-rsa"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"具體代碼實現登錄接口"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1、引用加密庫"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const http = require(\"http\");\nconst aesjs = require(\"aes-js\");\nconst NodeRSA = require(\"node-rsa\");\nconst rsaKey = new NodeRSA({ b: 1024 }); \/\/ key的size爲1024位\nlet aesKey = null; \/\/ 用於保存客戶端的aesKey\nlet privateKey = \"\"; \/\/ 用於保存服務端的公鑰\n\nrsaKey.setOptions({ encryptionScheme: \"pkcs1\" }); \/\/ 設置加密模式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2、實現 login 接口"}]},{"type":"codeblock","attrs":{"lang":"typescript"},"content":[{"type":"text","text":"http\n .createServer((request, response) => {\n response.setHeader(\"Access-Control-Allow-Origin\", \"*\");\nresponse.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type\");\n response.setHeader(\"Content-Type\", \"application\/json\");\nswitch (request.method) {\n case \"GET\":\n if (request.url === \"\/getPub\") {\n const publicKey = rsaKey.exportKey(\"public\");\n privateKey = rsaKey.exportKey(\"private\");\n response.writeHead(200);\n response.end(JSON.stringify({ result: true, data: publicKey })); \/\/ 把公鑰發送給客戶端\n return;\n }\n break;\n case \"POST\":\n if (request.url === \"\/login\") {\n let str = \"\";\n request.on(\"data\", function (chunk) {\n str += chunk;\n });\n request.on(\"end\", function () {\n const params = JSON.parse(str);\n const reciveData = decrypt(params.data);\n console.log(\"reciveData\", reciveData);\n \/\/ 一系列處理之後\n\n response.writeHead(200);\n response.end(\n JSON.stringify({\n result: true,\n data: aesEncrypt(\n JSON.stringify({ userId: 123, address: \"杭州\" }), \/\/ 這個數據會被加密\n aesKey\n ),\n })\n );\n });\n return;\n }\n break;\n default:\n break;\n }\n response.writeHead(404);\n response.end();\n })\n .listen(3000);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3、加密和解密方法"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function decrypt({ param1, param2 }) {\n const decrypted = rsaKey.decrypt(param2, \"utf8\"); \/\/ 解密得到aesKey\n aesKey = decrypted.split(\",\").map((item) => {\nreturn +item;\n });\n\n return aesDecrypt(param1, aesKey);\n}\n\n\/**\n * aes解密方法\n * @param {string} encryptedHex 加密的字符串\n * @param {array} key 加密key\n *\/\nfunction aesDecrypt(encryptedHex, key) {\n const encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex); \/\/ 把十六進制轉成二進制數據\n const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5)); \/\/ 這邊使用CTR-Counter加密模式,還有其他模式可以選擇,具體可以參考aes加密庫\n\n const decryptedBytes = aesCtr.decrypt(encryptedBytes); \/\/ 進行解密\n const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes); \/\/ 把二進制數據轉成字符串\n\n return decryptedText;\n}\n\n\/**\n * aes加密方法\n * @param {string} text 待加密的字符串\n * @param {array} key 加密key\n *\/\nfunction aesEncrypt(text, key) {\n const textBytes = aesjs.utils.utf8.toBytes(text); \/\/ 把字符串轉成二進制數據\n const aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));\n\n const encryptedBytes = aesCtr.encrypt(textBytes); \/\/ 加密\n const encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes); \/\/ 把二進制數據轉成十六進制\n\n return encryptedHex;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"完整的示例代碼:https:\/\/github.com\/Pulset\/FrontDataEncrypt"}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"演示效果"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/51\/5158f843a710b00a3c42d8c145486f2a.gif","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文主要介紹了一些前端安全方面的知識和具體加密方案的實現。爲了保護客戶的隱私數據,不管是 HTTP 還是 HTTPS,都建議密文傳輸信息,讓破解者增加一點攻擊難度吧。當然數據加解密也會帶來一定性能上的消耗,這個需要各位開發者各自衡量了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頭圖:Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:浮雲"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:https:\/\/mp.weixin.qq.com\/s\/yzJt4y2WRXdI4zoCalYd2Q"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:敏感數據加密方案及實現"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來源:政採雲前端團隊 - 微信公衆號 [ID:Zoo-Team]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"轉載:著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章