說(shuō)到桑同學(xué),那比我牛出不止一個(gè)數(shù)量級(jí)了。俄亥俄州立大學(xué)畢業(yè)的PhD,曾在Yahoo!、LinkedIn等多家公司擔(dān)任技術(shù)骨干。在過(guò)去三四年間獲各種數(shù)據(jù)加密相關(guān)的專(zhuān)利達(dá)五項(xiàng)之多。
除了技術(shù)扎實(shí),桑同學(xué)平時(shí)也是極好相處,又特別愿意幫助別人。在我過(guò)去和他不多的幾次合作中,也不時(shí)又機(jī)會(huì)請(qǐng)教一二。雖然對(duì)于數(shù)據(jù)加密仍然是個(gè)門(mén)外漢,但是桑同學(xué)解釋問(wèn)題總能聽(tīng)得懂。因此在我的再三請(qǐng)求下,有了這篇科普性的文章。
雖然我們都就職于Airbnb,但是這篇文章和 Airbnb 現(xiàn)在使用的技術(shù)沒(méi)有直接關(guān)聯(lián)。下面是正文。
數(shù)據(jù)加密是一個(gè)古老的問(wèn)題,但又是一個(gè)無(wú)法做到完美的問(wèn)題,尤其在一個(gè)復(fù)雜的大型系統(tǒng)中需要考慮方方面面的問(wèn)題,包括 security, availability, usability, consistentcy, performance,extensibility 等等。除了那些完全不做的,大部分公司都會(huì)根據(jù)自身的需求、環(huán)境、資源以及工程師的能力等,設(shè)計(jì)和開(kāi)發(fā)適合公司實(shí)際情況的解決方案。有做得好的,也有坦誠(chéng)做得不好的,還有自己認(rèn)為做得好的但其實(shí)經(jīng)不起真正考驗(yàn)的。
就算在同一個(gè)公司,很多也會(huì)有不同的解決方案并存。有些是因?yàn)闅v史原因,比方說(shuō)早期用方案A,后來(lái)開(kāi)發(fā)了更牛逼的方案B,但沒(méi)有把A完全干掉;或者擴(kuò)張?jiān)颍确秸f(shuō)兼并了一個(gè)用不同方案的別家公司;又或者是政治原因,不同部門(mén)誰(shuí)都不屌誰(shuí),各自用自認(rèn)為合適的方案。無(wú)論公司選擇什么方案,因?yàn)樵掝}的敏感性(法律原因,或者圈內(nèi)的潛規(guī)則,或者僅僅是不想當(dāng)出頭鳥(niǎo)而被黑客們盯上),絕大部分都不會(huì)公開(kāi)數(shù)據(jù)加密的細(xì)節(jié)。同樣原因,這篇文章也不會(huì)涉及筆者公司怎么做數(shù)據(jù)加密的具體細(xì)節(jié)。想到哪兒寫(xiě)到哪兒吧。
一、為什么要做數(shù)據(jù)加密?
先說(shuō)為什么要做數(shù)據(jù)加密。越來(lái)越多的數(shù)據(jù)泄露事件,比方說(shuō) Yahoo 2013年被盜超過(guò)10億用戶(hù)信息,Yahoo 2014年又被盜超過(guò)5億用戶(hù)信息,LinkedIn 被盜一億多用戶(hù)密碼,Ashley Madison 被盜三千多萬(wàn)用戶(hù)數(shù)據(jù)以及大量支付信息,Target 被盜近七千萬(wàn)用戶(hù)數(shù)據(jù)和銀行賬號(hào),Adobe 被盜三千八百萬(wàn)用戶(hù)數(shù)據(jù)等等,以及由此導(dǎo)致的大量法律糾紛和巨額賠償,還有很多很多大大小小沒(méi)有被公布的安全事件,都說(shuō)明了數(shù)據(jù)加密和保護(hù)的重要性。
說(shuō)到這些安全事件中用戶(hù)密碼的保護(hù),插個(gè)題外話。筆者曾經(jīng)跟很多工程師(包括很多應(yīng)用領(lǐng)域?qū)<?聊天的時(shí)候,都會(huì)被問(wèn)到,為什么筆者認(rèn)為僅僅 Hash 用戶(hù)密碼是不夠的。很多人(包括網(wǎng)上的很多文章)都誤認(rèn)為用戶(hù)密碼只要 Hash了,就安全了,其實(shí)不然。不說(shuō) weak Hash 函數(shù)諸如 RC4、MD5,就算用 Bcrypt、KDF等運(yùn)算復(fù)雜的Hash函數(shù),雖然能防 Rainbow Table Attack,但對(duì) Dictionary Attack 卻是無(wú)效的。當(dāng)然這不是 Hash 函數(shù)本身的錯(cuò),而是很多人會(huì)選一個(gè)容易記的密碼,而這類(lèi)密碼往往 entropy 不夠,很容易被解密。對(duì)用戶(hù)密碼而言,筆者一直建議不僅需要Hash,還要加密(比方說(shuō)用 keyed hash function,or MAC)。
還有很多公司要做加密不僅僅是因?yàn)楸Wo(hù)用戶(hù)隱私,更是法律法規(guī)的要求,不得不做。有些涉及特殊數(shù)據(jù),如信用卡號(hào)碼,那就要做 PCI (The Payment Card Industry Data Security Standard );如用戶(hù)健康信息,那就要做 HIPAA (The Health Insurance Portability and Accountability Act)等等。
在筆者看來(lái),任何一個(gè)收集以及存儲(chǔ)客戶(hù)數(shù)據(jù)的公司,就算是初創(chuàng)公司,都應(yīng)該認(rèn)真對(duì)待這個(gè)問(wèn)題。在圈內(nèi)我們常說(shuō),不是系統(tǒng)會(huì)不會(huì)黑,數(shù)據(jù)會(huì)不會(huì)被盜,而是何時(shí)被黑被盜的問(wèn)題。也許有人會(huì)說(shuō),就算偷了,盜了,那又如何?這種事可大可小,筆者私下就知道有公司被黑后,被迫關(guān)門(mén)了的。所以安全領(lǐng)域內(nèi)的及時(shí)投資,對(duì)公司長(zhǎng)期來(lái)講都是非常有益的。對(duì)重要數(shù)據(jù)(包括系統(tǒng)密碼,用戶(hù)信息等)進(jìn)行有效保護(hù),數(shù)據(jù)被黑被盜的門(mén)檻就高了;就算有一天系統(tǒng)被黑了,數(shù)據(jù)被盜了,也能把損失降到最小。
二、怎么做數(shù)據(jù)加密?
你說(shuō)數(shù)據(jù)加密這么重要,怎么做呢?如果把加密這個(gè)問(wèn)題抽象出來(lái),其實(shí)就是要計(jì)算一個(gè)加密函數(shù):
encrypt(data, key)
(當(dāng)然還有一個(gè)函數(shù)就是解密,跟加密類(lèi)似道理,暫且不論)。看上去似乎是一個(gè)非常簡(jiǎn)單的問(wèn)題,但要把它做好非常不容易。尤其是在一個(gè)系統(tǒng)復(fù)雜的公司,要考慮的問(wèn)題很多很多。比方說(shuō),密碼界有很多算法,應(yīng)該用什么加密算法,對(duì)稱(chēng)的還是非對(duì)稱(chēng)的?具體選哪個(gè),AES,DES,RSA,ECC等等,各有什么特點(diǎn)?題外話,筆者在曾經(jīng)工作過(guò)的公司見(jiàn)過(guò)很多有趣的例子,比方說(shuō)有些早期開(kāi)發(fā)人員用 XOR 來(lái)加密,或者做點(diǎn)簡(jiǎn)單的迭代替換,或者自創(chuàng)所謂的加密算法(有點(diǎn)掩耳盜鈴的感覺(jué))等等,這些最后都變成 technical debt,需要花很大力氣去清理。
每個(gè)算法也有不同的變種和模式,各有什么特點(diǎn),性能如何?如果某個(gè)算法被宣布不安全了,如何快速迭代?這個(gè) key 怎么來(lái)?多長(zhǎng)才是安全的?怎么啟動(dòng)?怎么保存?怎么傳播?怎么控制訪問(wèn)權(quán)限?怎么知道誰(shuí)訪問(wèn)了什么?怎么來(lái)監(jiān)控?怎么來(lái)預(yù)警?怎么來(lái)系統(tǒng)性的更新這些 key?key 能不能丟,丟了怎么辦?不同的應(yīng)用可能是用不同的語(yǔ)言寫(xiě)的,怎么兼容?怎么支持大流量等等,等等。還有更加不近人情的要求,比方說(shuō)如何保證被加密的數(shù)據(jù)能夠 preserve 原始數(shù)據(jù)的順序,支持搜索,但又不犧牲安全性等(這方面 MIT 有學(xué)者在研究,有興趣的朋友可以看看他們的論文)。
一個(gè)好的加密設(shè)計(jì)方案,不僅僅方案本身要滿足安全上嚴(yán)格的要求,解決上面提到的很多問(wèn)題,還需要實(shí)用,容易擴(kuò)展和維護(hù)。在數(shù)據(jù)加密變得越來(lái)越重要,系統(tǒng)越來(lái)越復(fù)雜的年代,如果資源允許,應(yīng)該把加密服務(wù)獨(dú)立出來(lái),然后提供高性能,統(tǒng)一,簡(jiǎn)單又容易理解的接口來(lái)進(jìn)行數(shù)據(jù)加密,讓?xiě)?yīng)用開(kāi)發(fā)人員很方便的使用,這樣他們只需要專(zhuān)注他/她所擅長(zhǎng)的領(lǐng)域,而不需要去思考怎么解決安全問(wèn)題,因?yàn)樾g(shù)業(yè)有專(zhuān)攻。好的加密方案應(yīng)該把數(shù)據(jù)和秘鑰的存儲(chǔ)分開(kāi),并且把存儲(chǔ)和運(yùn)算分開(kāi),尤其在 SOA 架構(gòu)下, 這可能跟很多傳統(tǒng)的數(shù)據(jù)加密方法(比方說(shuō)直接實(shí)用某個(gè)語(yǔ)言的內(nèi)置庫(kù)加密解密)非常不一樣。很多解決方案往往密鑰和被加密的數(shù)據(jù)同時(shí)存在一個(gè)服務(wù)中,結(jié)果就是如果那個(gè)服務(wù)被黑了,那就整個(gè)被黑了。下面就撿幾個(gè)要點(diǎn)簡(jiǎn)略講講。
(1)為什么要把運(yùn)算和存儲(chǔ)的分離?很多需要被加密的數(shù)據(jù),往往和具體商業(yè)邏輯數(shù)據(jù)一起,屬于不同的服務(wù),比方說(shuō)支付信息屬于支付服務(wù),護(hù)照號(hào)碼屬于用戶(hù)服務(wù)等。把運(yùn)算和存儲(chǔ)分離可以帶來(lái)很多好處,比方說(shuō):
加密服務(wù)變得簡(jiǎn)單和高效。因?yàn)椴恍枰鎯?chǔ)那些被加密的數(shù)據(jù),加密服務(wù)系統(tǒng)不會(huì)很復(fù)雜,也不需要負(fù)責(zé)存儲(chǔ)系統(tǒng)所帶來(lái)的維護(hù),擴(kuò)展等諸多問(wèn)題;
加密服務(wù)的安全性能提高很多。因?yàn)檫\(yùn)算和存儲(chǔ)的分離,如果僅僅是被加密的數(shù)據(jù)泄露(比方說(shuō)數(shù)據(jù)庫(kù)被盜),那些數(shù)據(jù)就沒(méi)法被解密,因?yàn)楹诳蜎](méi)法從外部訪問(wèn)加密服務(wù)。如果僅僅是客戶(hù)服務(wù)被黑,想要盜取大量數(shù)據(jù)并且通過(guò)加密服務(wù)來(lái)解密而不被發(fā)現(xiàn)也很難。如果僅僅是加密服務(wù)服務(wù)被黑,因?yàn)榧用芊?wù)本身并不擁有數(shù)據(jù),被泄露的數(shù)據(jù)也不會(huì)很多。只有當(dāng)加密服務(wù)和客戶(hù)服務(wù)同時(shí)被黑,才會(huì)泄露大量數(shù)據(jù),而同時(shí)能夠侵入加密服務(wù)和客戶(hù)服務(wù)的難度要高很多很多;
靈動(dòng)性。因?yàn)閿?shù)據(jù)屬于客戶(hù)服務(wù),不同的客戶(hù)可以對(duì)數(shù)據(jù)進(jìn)行不同的處理,比方說(shuō)不同的有效性規(guī)則,數(shù)據(jù)交易完整性等等。
(2)其次是 granular control。假設(shè)支付服務(wù)要求加密/解密信用卡號(hào)碼,用戶(hù)服務(wù)要求加密/解密護(hù)照號(hào)碼,如何能保證用戶(hù)服務(wù)不能加密/解密信用卡號(hào)碼。這就需要解決兩個(gè)基本問(wèn)題:客戶(hù)認(rèn)證(authentication)和權(quán)限控制(authorization)。怎么做客戶(hù)認(rèn)證(authentication)?客戶(hù)認(rèn)證要知道每一個(gè)請(qǐng)求是誰(shuí)發(fā)出的。因?yàn)橹挥兄揽蛻?hù)是誰(shuí)才可以進(jìn)行權(quán)限檢查。常用的有基于客戶(hù)證書(shū)的(如 client certificate over TLS),基于 OAuth(開(kāi)放授權(quán))的,或者各種各樣定制的方案,如基于 Curve25519 等等。筆者一般遵循兩個(gè)原則:
是不是業(yè)界公認(rèn)的。如果不是,最好避免。業(yè)界公認(rèn)的解決方案往往經(jīng)過(guò)過(guò)嚴(yán)格的檢驗(yàn), 評(píng)價(jià),批評(píng),經(jīng)得起考驗(yàn);
有沒(méi)有廣泛的類(lèi)庫(kù)支持,以及多語(yǔ)言的支持。如果有,可以節(jié)省大量的開(kāi)發(fā)以及維護(hù)的時(shí)間和精力。
(3)數(shù)據(jù)監(jiān)控和預(yù)警。為了審計(jì)以及安全的需求,一般要對(duì)加密服務(wù)做很多的數(shù)據(jù)監(jiān)控,預(yù)警的工作。這樣可以知道誰(shuí)在訪問(wèn)這些數(shù)據(jù),何時(shí)訪問(wèn)的,怎么訪問(wèn)的,訪問(wèn)的模式是怎么樣的。監(jiān)控系統(tǒng)還需要偵測(cè)異常的流量變化,進(jìn)行流量控制以及快速的反攻擊保護(hù)。
(4)最后,重中之重,怎么保護(hù) root key?無(wú)論是用哪種 envelope encryption的變種,都會(huì)涉及到怎么保護(hù) root key。這是一個(gè)很有意思的話題,但篇幅關(guān)系就不展開(kāi)來(lái)講了。常見(jiàn)的有用 secret sharing的一些變種方式,也有通過(guò)公證人公證整個(gè)過(guò)程藏在銀行保險(xiǎn)箱的,也有藏在創(chuàng)始人地下室的:)怎么來(lái) bootstrap 和 deploy 這個(gè) root key 到加密服務(wù)里也是一個(gè)非常有意思和挑戰(zhàn)的問(wèn)題。
總的來(lái)說(shuō),數(shù)據(jù)加密不是一件神秘的事情,但要做好非常不容易,需要一定的技術(shù)積累和資源的投入。做任何一個(gè)安全系統(tǒng),風(fēng)險(xiǎn)都不小。圈內(nèi)人第一反應(yīng)是懷疑,因?yàn)槁殬I(yè)病;圈外人很多也覺(jué)得重要,但不關(guān)心,或者說(shuō)不知道怎么關(guān)心。但不管如何,無(wú)論是因?yàn)闈撛诘姆娠L(fēng)險(xiǎn)還是用戶(hù)的信任風(fēng)險(xiǎn),這種安全上的投入從長(zhǎng)期來(lái)說(shuō)一定是值得的。