天天看點

Airbnb技術大牛桑立鋒解析:資料加密都有哪些套路?

 說到桑同學,那比我牛出不止一個數量級了。俄亥俄州立大學畢業的phd,曾在yahoo!、linkedin等多家公司擔任技術骨幹。在過去三四年間獲各種資料加密相關的專利達五項之多。

除了技術紮實,桑同學平時也是極好相處,又特别願意幫助别人。在我過去和他不多的幾次合作中,也不時又機會請教一二。雖然對于資料加密仍然是個門外漢,但是桑同學解釋問題總能聽得懂。是以在我的再三請求下,有了這篇科普性的文章。

雖然我們都就職于airbnb,但是這篇文章和 airbnb 現在使用的技術沒有直接關聯。下面是正文。

資料加密是一個古老的問題,但又是一個無法做到完美的問題,尤其在一個複雜的大型系統中需要考慮方方面面的問題,包括 security, availability, usability, consistentcy, performance,extensibility 等等。除了那些完全不做的,大部分公司都會根據自身的需求、環境、資源以及工程師的能力等,設計和開發适合公司實際情況的解決方案。有做得好的,也有坦誠做得不好的,還有自己認為做得好的但其實經不起真正考驗的。

就算在同一個公司,很多也會有不同的解決方案并存。有些是因為曆史原因,比方說早期用方案a,後來開發了更牛逼的方案b,但沒有把a完全幹掉;或者擴張原因,比方說兼并了一個用不同方案的别家公司;又或者是政治原因,不同部門誰都不屌誰,各自用自認為合适的方案。無論公司選擇什麼方案,因為話題的敏感性(法律原因,或者圈内的潛規則,或者僅僅是不想當出頭鳥而被黑客們盯上),絕大部分都不會公開資料加密的細節。同樣原因,這篇文章也不會涉及筆者公司怎麼做資料加密的具體細節。想到哪兒寫到哪兒吧。

一、為什麼要做資料加密?

先說為什麼要做資料加密。越來越多的資料洩露事件,比方說 yahoo 2013年被盜超過10億使用者資訊,yahoo 2014年又被盜超過5億使用者資訊,linkedin 被盜一億多使用者密碼,ashley madison 被盜三千多萬使用者資料以及大量支付資訊,target 被盜近七千萬使用者資料和銀行賬号,adobe 被盜三千八百萬使用者資料等等,以及由此導緻的大量法律糾紛和巨額賠償,還有很多很多大大小小沒有被公布的安全事件,都說明了資料加密和保護的重要性。

說到這些安全事件中使用者密碼的保護,插個題外話。筆者曾經跟很多工程師(包括很多應用領域專家)聊天的時候,都會被問到,為什麼筆者認為僅僅 hash 使用者密碼是不夠的。很多人(包括網上的很多文章)都誤認為使用者密碼隻要 hash了,就安全了,其實不然。不說 weak hash 函數諸如 rc4、md5,就算用 bcrypt、kdf等運算複雜的hash函數,雖然能防 rainbow table attack,但對 dictionary attack 卻是無效的。當然這不是 hash 函數本身的錯,而是很多人會選一個容易記的密碼,而這類密碼往往 entropy 不夠,很容易被解密。對使用者密碼而言,筆者一直建議不僅需要hash,還要加密(比方說用 keyed hash function,or mac)。

還有很多公司要做加密不僅僅是因為保護使用者隐私,更是法律法規的要求,不得不做。有些涉及特殊資料,如信用卡号碼,那就要做 pci (the payment card industry data security standard );如使用者健康資訊,那就要做 hipaa (the health insurance portability and accountability act)等等。

在筆者看來,任何一個收集以及存儲客戶資料的公司,就算是初創公司,都應該認真對待這個問題。在圈内我們常說,不是系統會不會黑,資料會不會被盜,而是何時被黑被盜的問題。也許有人會說,就算偷了,盜了,那又如何?這種事可大可小,筆者私下就知道有公司被黑後,被迫關門了的。是以安全領域内的及時投資,對公司長期來講都是非常有益的。對重要資料(包括系統密碼,使用者資訊等)進行有效保護,資料被黑被盜的門檻就高了;就算有一天系統被黑了,資料被盜了,也能把損失降到最小。

二、怎麼做資料加密?

你說資料加密這麼重要,怎麼做呢?如果把加密這個問題抽象出來,其實就是要計算一個加密函數:

encrypt(data, key)

(當然還有一個函數就是解密,跟加密類似道理,暫且不論)。看上去似乎是一個非常簡單的問題,但要把它做好非常不容易。尤其是在一個系統複雜的公司,要考慮的問題很多很多。比方說,密碼界有很多算法,應該用什麼加密算法,對稱的還是非對稱的?具體選哪個,aes,des,rsa,ecc等等,各有什麼特點?題外話,筆者在曾經工作過的公司見過很多有趣的例子,比方說有些早期開發人員用 xor 來加密,或者做點簡單的疊代替換,或者自創所謂的加密算法(有點掩耳盜鈴的感覺)等等,這些最後都變成 technical debt,需要花很大力氣去清理。

每個算法也有不同的變種和模式,各有什麼特點,性能如何?如果某個算法被宣布不安全了,如何快速疊代?這個 key 怎麼來?多長才是安全的?怎麼啟動?怎麼儲存?怎麼傳播?怎麼控制通路權限?怎麼知道誰通路了什麼?怎麼來監控?怎麼來預警?怎麼來系統性的更新這些 key?key 能不能丢,丢了怎麼辦?不同的應用可能是用不同的語言寫的,怎麼相容?怎麼支援大流量等等,等等。還有更加不近人情的要求,比方說如何保證被加密的資料能夠 preserve 原始資料的順序,支援搜尋,但又不犧牲安全性等(這方面 mit 有學者在研究,有興趣的朋友可以看看他們的論文)。

一個好的加密設計方案,不僅僅方案本身要滿足安全上嚴格的要求,解決上面提到的很多問題,還需要實用,容易擴充和維護。在資料加密變得越來越重要,系統越來越複雜的年代,如果資源允許,應該把加密服務獨立出來,然後提供高性能,統一,簡單又容易了解的接口來進行資料加密,讓應用開發人員很友善的使用,這樣他們隻需要專注他/她所擅長的領域,而不需要去思考怎麼解決安全問題,因為術業有專攻。好的加密方案應該把資料和秘鑰的存儲分開,并且把存儲和運算分開,尤其在 soa 架構下, 這可能跟很多傳統的資料加密方法(比方說直接實用某個語言的内置庫加密解密)非常不一樣。很多解決方案往往密鑰和被加密的資料同時存在一個服務中,結果就是如果那個服務被黑了,那就整個被黑了。下面就撿幾個要點簡略講講。

(1)為什麼要把運算和存儲的分離?很多需要被加密的資料,往往和具體商業邏輯資料一起,屬于不同的服務,比方說支付資訊屬于支付服務,護照号碼屬于使用者服務等。把運算和存儲分離可以帶來很多好處,比方說:

加密服務變得簡單和高效。因為不需要存儲那些被加密的資料,加密服務系統不會很複雜,也不需要負責存儲系統所帶來的維護,擴充等諸多問題;

加密服務的安全性能提高很多。因為運算和存儲的分離,如果僅僅是被加密的資料洩露(比方說資料庫被盜),那些資料就沒法被解密,因為黑客沒法從外部通路加密服務。如果僅僅是客戶服務被黑,想要盜取大量資料并且通過加密服務來解密而不被發現也很難。如果僅僅是加密服務服務被黑,因為加密服務本身并不擁有資料,被洩露的資料也不會很多。隻有當加密服務和客戶服務同時被黑,才會洩露大量資料,而同時能夠侵入加密服務和客戶服務的難度要高很多很多;

靈動性。因為資料屬于客戶服務,不同的客戶可以對資料進行不同的處理,比方說不同的有效性規則,資料交易完整性等等。

(2)其次是 granular control。假設支付服務要求加密/解密信用卡号碼,使用者服務要求加密/解密護照号碼,如何能保證使用者服務不能加密/解密信用卡号碼。這就需要解決兩個基本問題:客戶認證(authentication)和權限控制(authorization)。怎麼做客戶認證(authentication)?客戶認證要知道每一個請求是誰發出的。因為隻有知道客戶是誰才可以進行權限檢查。常用的有基于客戶證書的(如 client certificate over tls),基于 oauth(開放授權)的,或者各種各樣定制的方案,如基于 curve25519 等等。筆者一般遵循兩個原則:

是不是業界公認的。如果不是,最好避免。業界公認的解決方案往往經過過嚴格的檢驗, 評價,批評,經得起考驗;

有沒有廣泛的類庫支援,以及多語言的支援。如果有,可以節省大量的開發以及維護的時間和精力。

(3)資料監控和預警。為了審計以及安全的需求,一般要對加密服務做很多的資料監控,預警的工作。這樣可以知道誰在通路這些資料,何時通路的,怎麼通路的,通路的模式是怎麼樣的。監控系統還需要偵測異常的流量變化,進行流量控制以及快速的反攻擊保護。

(4)最後,重中之重,怎麼保護 root key?無論是用哪種 envelope encryption的變種,都會涉及到怎麼保護 root key。這是一個很有意思的話題,但篇幅關系就不展開來講了。常見的有用 secret sharing的一些變種方式,也有通過公證人公證整個過程藏在銀行保險箱的,也有藏在創始人地下室的:)怎麼來 bootstrap 和 deploy 這個 root key 到加密服務裡也是一個非常有意思和挑戰的問題。

總的來說,資料加密不是一件神秘的事情,但要做好非常不容易,需要一定的技術積累和資源的投入。做任何一個安全系統,風險都不小。圈内人第一反應是懷疑,因為職業病;圈外人很多也覺得重要,但不關心,或者說不知道怎麼關心。但不管如何,無論是因為潛在的法律風險還是使用者的信任風險,這種安全上的投入從長期來說一定是值得的。

傳送門:

繼續閱讀