前端該知道些密碼學(xué)和安全上的事兒
今年至少有六個(gè)月的時(shí)間在和密碼學(xué),安全,隱私上的事情打交道,很有必要為今年總結(jié)一篇收官之作,整篇文章會(huì)描述一些基礎(chǔ)概念,以及我力所能及的一些理解,這份知識(shí)很有可能不準(zhǔn)確,主要讓前端的同學(xué)們有一些概念,知道有這么回事,大佬輕拍;
密碼學(xué)淺識(shí)
在密碼學(xué)的世界里加密之前的消息被稱為明文 plaintext,加密之后的消息被稱為密文ciphertext,如果一段密文需要被解密再閱讀,這個(gè)過程被稱之為 decrypt,反之一段plaintext 需要被加密,這個(gè)過程被稱之為 encrypt。那么在處理這些問題的過程(解決加密/解密的步驟)通常被稱之為 算法,加密算法和解密算法被組合起來叫 密碼算法。
目前我個(gè)人所接觸到的主要是:
- 對稱密碼
- 單向散列函數(shù)
- 非對稱密碼
- Web Crypto API
其中對于公鑰證書的數(shù)字簽名等等。別著急,這些概念性的內(nèi)容可能會(huì)非常的枯燥,因此我并不會(huì)描述很多,反而從實(shí)際性的問題出發(fā),舉例在前端的領(lǐng)域中,上述三個(gè)方向上著重解決什么問題。
- https://code.google.com/archive/p/crypto-js/
- https://github.com/brix/crypto-js
- https://github.com/PeculiarVentures/PKI.js
- https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Crypto_API
對稱密碼
比較典型的如 AES ,它是指在加密和解密的過程中使用同一個(gè) 密鑰 的處理這個(gè)過程。我們知道,目前在中國大陸的Web世界中(不僅是Web也包括App),二維碼的流行程度幾乎很多場景里都有使用,這種不經(jīng)過網(wǎng)絡(luò)的直接獲取數(shù)據(jù),非常適合使用這種對稱加密/解密的方式來傳輸數(shù)據(jù),前端這邊會(huì)使用 crypto-js 來處理 AES,這個(gè) Google 開源的庫支持 AES-128,AES-192,AES-256:
- import * as CryptoJS from "crypto-js";
- export function aesDecrypt(text, originKey){
- const bytes = CryptoJS.AES.decrypt(text, originKey);
- return bytes.toString(CryptoJS.enc.Utf8);
- }
- export function aesEncrypt(text, originKey){
- const c = CryptoJS.AES.encrypt(text, originKey);
- return c.toString();
- }
單向散列函數(shù)
這個(gè)函數(shù)如果要舉例的話比較典型的有我們下載任何軟件包時(shí)同時(shí)會(huì)校驗(yàn)一下MD5值來防止下載的軟件包是一個(gè)被篡改的軟件包。單向散列函數(shù)就是為了計(jì)算散列值而準(zhǔn)備的函數(shù),crypto-js包中不僅提供了 md5,hmac 也有 sha256 。如果有一天前端和服務(wù)端約定要對數(shù)據(jù)進(jìn)行校驗(yàn),當(dāng)然最簡單的方式是 md5 ,但這已經(jīng)是一種不安全的計(jì)算了,最好使用 sha256:
- import * as CryptoJS from "crypto-js";
- const sha256 = CryptoJS.algo.SHA256.create();
- sha256.update("Message Part 1");
- sha256.update("Message Part 2");
- sha256.update("Message Part 3");
- const hash = sha256.finalize();
非對稱密碼
密碼學(xué)的那本書里講了很多密鑰分配的問題,這種思考確實(shí)...很燒腦,不過這種前輩經(jīng)歷過的思考,在我們的實(shí)際應(yīng)用中其實(shí)會(huì)有一個(gè)很有趣的過程。非對稱密碼,就是將密鑰分了兩個(gè)部分:加密密鑰和解密密鑰,發(fā)送者使用加密密鑰對消息進(jìn)行加密,接收者使用解密密鑰進(jìn)行解密。在這里加密密鑰是可以被公開的,只有解密密鑰是絕對不能被公開的。那么這其中使用了什么樣的算法來生成密鑰對(說實(shí)話,我也不是很清楚,因?yàn)闆]看懂),但前端的同學(xué)們了解到非對稱密碼還是很有必要。對于加密密鑰它被稱之為 `public key`,對應(yīng)的解密密鑰被稱之為 `private key`,目前被廣泛使用的公鑰密碼算法叫做 `RSA`。
除了加密之外,非對稱密碼還可以解決身份認(rèn)證的問題,想一想如果有人偽裝了一個(gè)和你一樣的微信,同樣的頭像和昵稱,同樣的說話語氣,詐騙集團(tuán)極有可能因此從你處獲取到真正的經(jīng)濟(jì)利益。因?yàn)榉菍ΨQ密碼的公鑰是可以公開的,一個(gè)人對應(yīng)一個(gè)公鑰,在密碼的世界里,根本無法偽裝,因?yàn)闊o法解密也無法得到認(rèn)證。
我想如果你會(huì)寫 Web 版的區(qū)塊鏈錢包或者錢包,非對稱密碼的使用頻率還是相當(dāng)高的,除此之外它所在的場景會(huì)特別的特殊(前端而言),不過如果在其他的領(lǐng)域,會(huì)比較常見。
Web Crypto API
Web Crypto API 為腳本提供加密了一套關(guān)于密碼(學(xué))的接口,以便用于構(gòu)建需要使用密碼的系統(tǒng)。這套API的基礎(chǔ)特性是允許在腳本中使用和維護(hù)密鑰的存儲(chǔ),但是不允許使用JavaScript訪問這些密鑰本身。
Web Crypto API 必須在 HTTPS 網(wǎng)頁中才能被使用(Chrome)
這套接口允許腳本使用以下功能:
- digest, 摘要,即計(jì)算數(shù)據(jù)塊hash的能力,用于檢測數(shù)據(jù)的變動(dòng)。
- mac, 計(jì)算消息驗(yàn)證碼的能力。
- sign and verify, 對文檔進(jìn)行數(shù)字簽名和驗(yàn)證的能力。
- encrypt and decrypt, 對文檔進(jìn)行加密和解密的能力。
- import and export, 導(dǎo)入和導(dǎo)出密鑰的能力。
- key generation, 產(chǎn)生密碼學(xué)中使用的私鑰或者密鑰對的能力,不使用base key,而是使用本地系統(tǒng)的能力。(the ability to create a cryptographically secure key, or key pair, without the use of base key, but using the available entropy of the local system.)
- key wrapping and unwrapping, 密鑰包裹和解包,即在不接觸底層密鑰內(nèi)容的情況下,與第三方傳送、接收使用另一個(gè)密鑰加密后的密鑰的能力。
- random, 生成密碼學(xué)中使用的偽隨機(jī)數(shù)的能力。
使用 Web Crypto API 的原因是我所使用的 PKI.js 依賴了 Web Crypto API 。
PKI(Public Key Infrastructure)是一個(gè)用非對稱密碼算法原理和技術(shù)來實(shí)現(xiàn)并提供安全服務(wù)的具有通用性的安全基礎(chǔ)設(shè)施,是一種遵循標(biāo)準(zhǔn)的利用公鑰加密技術(shù)為網(wǎng)上電子商務(wù)、電子政務(wù)的開展,提供一整套安全的基礎(chǔ)平臺(tái)。PKI,公鑰基礎(chǔ)設(shè)施,顧名思義,PKI技術(shù)就是利用公鑰理論和技術(shù)建立的提供網(wǎng)絡(luò)信息安全服務(wù)的基礎(chǔ)設(shè)施。PKI管理平臺(tái)能夠?yàn)榫W(wǎng)絡(luò)中所有需要采用加密和數(shù)字簽名等密碼服務(wù)的用戶提供所需的密鑰和證書管理,用戶可以利用PKI平臺(tái)提供的安全服務(wù)進(jìn)行安全通信。
安全
前端的安全性問題大體上都可歸結(jié)為 瀏覽器安全問題,Node.js 可以歸納為另外一個(gè)領(lǐng)域。瀏覽器安全問題 又可以細(xì)分出來很多問題,比較常見的如:XSS,CSRF,這些問題看似離我們很遠(yuǎn),因?yàn)槟壳拔覀兪褂玫目蚣芑旧陷o助我們已經(jīng)處理了這些問題,但是整個(gè) Web 世界中還有更多更多我們還未觸及的問題(對于此我也是一個(gè)小白),比如:HTTPS 與中間人攻擊,定制瀏覽器的擴(kuò)展和插件漏洞,目前我主要關(guān)注的點(diǎn)在 定制瀏覽器的擴(kuò)展和插件漏洞 這一塊,這個(gè)事情因?yàn)楹臀以谔幚淼膯栴}息息相關(guān),但又和傳統(tǒng)的 Web 安全問題有了顯著的區(qū)別:
- 權(quán)限更高的 API
- Content Script 劫持
- 中間人攻擊
- 各種“內(nèi)核”級別的攻擊
歸納起來對于權(quán)限的授權(quán),我們應(yīng)該只申請本插件只使用的 API ,千萬不可使用 * 或all_url 的形式,對于 CS 被劫持的問題,可以給網(wǎng)頁注入的內(nèi)容添加一個(gè)哈希運(yùn)算,比如前面我們用到的單向散列函數(shù)來進(jìn)行計(jì)算。
安全是一個(gè)特別綜合性的體系,單一的前端技能可能在這上面能發(fā)揮的認(rèn)知會(huì)比較有限,這里的認(rèn)知 意味著同樣的一件事情,安全工程師能從這里了解到前前后后可能出現(xiàn)的問題。
舉個(gè)例子:我們都知道 location 可以獲取 URL 上的各種參數(shù),其實(shí)如果黑客利用URL中的某些關(guān)鍵信息偽造了一個(gè)釣魚網(wǎng)站,用戶是極容易中獎(jiǎng)的。
另外一個(gè)典型的 CSRF 問題,有著比較復(fù)雜的流程,但是它利用的還是瀏覽器中處理 cookie 的機(jī)制:
- 受害者登錄 a.com,并保留了登錄Cookie
- 攻擊者引誘(黃色網(wǎng)站)受害者訪問 b.com
- b.com 向 a.com 發(fā)送一個(gè)請求 a.com/xxx=123,根據(jù)瀏覽器處理 Cookie 的機(jī)制,此時(shí)發(fā)起的請求會(huì)攜帶a.com 的 Cookie
- a.com 接收請求后,對請求進(jìn)行驗(yàn)證,此時(shí)已經(jīng)確認(rèn)是受害者發(fā)起的請求
a.com 以受害者的名義執(zhí)行了xxx=123
當(dāng)然解決這個(gè)安全問題,業(yè)界已經(jīng)為我們總結(jié)了很多方案,比如 同源檢測,Origin Header等等。不過,大體上前端的安全性我們能注重一些常見問題,基本上能涵蓋80%以上的問題。
對于安全問題,業(yè)界大佬推薦使用 https://msdn.microsoft.com/zh-cn/magazine/dd347831.aspx?f=255&MSPPError=-2147217396 來創(chuàng)建威脅模型,被歸納為STRIDE 威脅建模,它分為如下六個(gè)緯度:
- Spoofing
- Tampering
- Repudiation
- Information Disclosure
- Denial of Service
- Elevation of Privilege
大體上這六個(gè)緯度就已經(jīng)涵蓋了幾乎所有的安全性問題。那么對于前端的項(xiàng)目,我們可以從這六個(gè)緯度中去評估自己的項(xiàng)目而得到答案。
隱私和廣而告之
談及隱私是因?yàn)槿缃裨窖菰搅业碾[私泄露,大數(shù)據(jù)等技術(shù)的成熟度將一個(gè)人的畫像描繪的越來越清晰,數(shù)據(jù)幾乎就是“錢”的代名詞。
可是對于前端而言(Web世界里),隱私的泄露和 `Cookie` `localStorage` 息息相關(guān)。如今的 Web 世界里被追蹤的腳本大多數(shù)是用 Cookie 來實(shí)現(xiàn)的,簡單的來說多數(shù)網(wǎng)站的登錄持久化基本上都依賴于存儲(chǔ)在你設(shè)備上的 Cookie,而對于廣告平臺(tái)的第三方 Cookie 除了隱私問題外,很有可能還有 `安全性` 的問題,如果這個(gè)腳本被劫持了的話,但大多數(shù)瀏覽器都默認(rèn)提供了屏蔽第三方 Cookie,后來大家想到的是通過 `localStorage` 的方案去繞過被屏蔽的第三方 Cookie,這種越演越烈的廣告腳本追蹤,幾乎就是你瀏覽網(wǎng)頁在 Web 的世界里被泄露隱私的來源之一。
有時(shí)候真的很想要一個(gè)不被追蹤而又能搜索數(shù)據(jù)的搜索引擎,但久久不可詢,`隱私` 真是一個(gè)可愛可恨的事情,除非有人能去做這樣的事情。正好 https://mijisou.com 秘跡搜是一個(gè)真正可以保護(hù)你個(gè)人隱私的網(wǎng)絡(luò)搜索服務(wù),它不會(huì)記錄任何你的查詢關(guān)鍵字,也從不存儲(chǔ)你的個(gè)人信息,不傳播你的任何信息,真正做到搜索不留痕,擺脫你不想要的定向廣告的騷擾和可能的隱私泄露,它完美的符合了我的預(yù)期。