聊一聊,前端常見的加密算法
在信息安全越來越受重視的今天,前端的各種加密也變得更加重要。通常跟服務器的交互中,為保障數(shù)據(jù)傳輸?shù)陌踩?,避免被人抓包篡改?shù)據(jù),除了 https 的應用,還需要對傳輸數(shù)據(jù)進行加解密。
目前常見的加密算法可以分成三類
- 對稱加密算法:AES、…
- 非對稱加密算法:RSA、…
- Hash 算法:MD5、…
二、對稱加密算法
對稱加密(也叫私鑰加密)指加密和解密使用相同密鑰的加密算法。它要求發(fā)送方和接收方在安全通信之前,商定一個密鑰。對稱算法的安全性依賴于密鑰,泄漏密鑰就意味著任何人都可以對他們發(fā)送或接收的消息解密,所以密鑰的保密性對通信的安全性至關重要。
特點
- 優(yōu)點:算法公開、計算量小、加密速度快、加密效率高。
- 缺點:在數(shù)據(jù)傳送前,發(fā)送方和接收方必須商定好密鑰,然后雙方保存好密鑰。如果一方的密鑰被泄露,那么加密信息也就不安全了
- 使用場景:本地數(shù)據(jù)加密、https 通信、網絡傳輸?shù)?/li>
AES
AES:高級加密標準(Advanced Encryption Standard)為最常見的對稱加密算法(微信小程序加密傳輸就是用這個加密算法的)。
密鑰:用來加密明文的密碼。密鑰為接收方與發(fā)送方協(xié)商產生,但不可以直接在網絡上傳輸,否則會導致密鑰泄漏,通常是通過非對稱加密算法加密密鑰,然后再通過網絡傳輸給對方,或者直接面對面商量密鑰。密鑰是絕對不可以泄漏的,否則會被攻擊者還原密文,竊取數(shù)據(jù)。
在項目中需要用到 AES 加密時,可以使用開源的 js 庫:crypto-js
- var CryptoJS = require('crypto-js');
- var data = { id: 1, text: 'Hello World' };
- // 加密生成密文
- var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret_key_123').toString();
- // 解密得到明文
- var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret_key_123');
- var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
三、非對稱加密算法
非對稱加密算法需要兩個密鑰:公開密鑰(publickey:簡稱公鑰)和私有密鑰(privatekey:簡稱私鑰)。公鑰與私鑰是一對,如果用公鑰對數(shù)據(jù)進行加密,只有用對應的私鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。
特點
- 優(yōu)點:非對稱加密與對稱加密相比其安全性更好
- 缺點:加密和解密花費時間長、速度慢,只適合對少量數(shù)據(jù)進行加密。
- 使用場景:https 會話前期、CA 數(shù)字證書、信息加密、登錄認證等
RSA
RSA 加密算法是非對稱加密算法最常見的一種。RSA 是 1977 年由 Ron Rivest、Adi Shamir 和 Leonard Adleman 一起提出的。RSA 就是他們三人姓氏開頭字母拼在一起組成的。
在項目中需要用到 RSA 加密時,可以使用開源的 js 庫:jsencrypt
- // 使用公鑰加密
- var publicKey = 'public_key_123';
- var encrypt = new JSEncrypt();
- encrypt.setPublicKey(publicKey);
- var encrypted = encrypt.encrypt('Hello World');
- // 使用私鑰解密
- var privateKey = 'private_key_123';
- var decrypt = new JSEncrypt();
- decrypt.setPrivateKey(privateKey);
- var uncrypted = decrypt.decrypt(encrypted);
四、Hash 算法
Hash,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長度的輸入(又叫做預映射, pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。
簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。
特點
- 優(yōu)點:不可逆、易計算、特征化
- 缺點:可能存在散列沖突
- 使用場景:文件或字符串一致性校驗、數(shù)字簽名、鑒權協(xié)議
MD5
MD5 是比較常見的 Hash 算法,對于 MD5 而言,有兩個特性是很重要的,第一:明文數(shù)據(jù)經過散列以后的值是定長的;第二:是任意一段明文數(shù)據(jù),經過散列以后,其結果必須永遠是不變的。前者的意思是可能存在有兩段明文散列以后得到相同的結果,后者的意思是如果我們散列特定的數(shù)據(jù),得到的結果一定是相同的。
比如在登錄時將密碼進行 md5 加密再傳輸給服務器,服務器中的密碼也是用 md5 加密后存儲的,那么只要驗證加密后的密文是否一致則可。
在項目中需要用到 MD5 加密時,可以使用開源的 js 庫:JavaScript-MD5
- var hash = md5('Hello World');
- // b10a8db164e0754105b7a99be72e3fe5
五、Base64 編碼
Base64 編碼只是一種編碼格式并不是加密算法,它可用于在 HTTP 環(huán)境下傳遞較長的標識信息。
特點
- 可以將任意的二進制數(shù)據(jù)進行 Base64 編碼
- 數(shù)據(jù)加密之后,數(shù)據(jù)量會變大,變大 1/3 左右
- 編碼后有個非常顯著的特點,末尾有個=號
- 可進行反向解碼
- Base64 編碼具有不可讀性
現(xiàn)代瀏覽器都提供了 Base64 編碼、解碼方法,btoa() 和 atob()
- var enc = window.btoa('Hello World');
- // SGVsbG8gV29ybGQ=
- var str = window.atob(enc);
- // Hello World
六、總結
在業(yè)務 http 請求中,AES 的密鑰在前端隨機生成,從服務器獲取 RSA 的公鑰,對 AES 的密鑰進行非對稱加密,把加密后的密鑰在請求頭中傳給服務器,用 AES 對 body 進行加密。服務器收到請求頭中的加密后的密鑰,用 RSA 的密鑰進行解密,得到明文的 AES 密鑰,即可對 body 進行解密。md5 有校驗字符串一致性的特性,為避免請求被攔截后篡改 body,可在發(fā)請求時,將 body 字符串進行一個 md5 加密后在請求頭傳輸,服務器收到請求后,解密 body 后再 md5 與請求頭的進行校驗,可驗證是否請求被篡改。