起點
最近空閑時間都在研究Google開源項目Tink的源碼,發(fā)現(xiàn)很多密碼學(xué)相關(guān)概念似懂非懂,直接導(dǎo)致越看越蒙圈。在通過谷歌度娘惡補基礎(chǔ)知識的過程中涩堤,發(fā)現(xiàn)密碼學(xué)理論艱深,概念繁多分瘾。寫這篇文章就是希望把關(guān)鍵點記錄下來胎围,一來可以加深印象,留著以后溫故而知新;二來也許可以給有同樣需求的朋友一點捷徑白魂。
這篇文章注定會很長汽纤,因為我會盡量把每個概念或名詞都附上詳細(xì)解釋,而我又不想分開來寫碧聪。本文是我在翻閱了很多網(wǎng)絡(luò)文章后冒版,加入自己的理解后整理而成液茎。所有出處和參考資料都在文章結(jié)尾逞姿,侵刪!
本人水平有限捆等,錯誤難免滞造,如果您發(fā)現(xiàn)錯誤,請務(wù)必指出栋烤,非常感謝!
密碼學(xué)的方法論
密碼學(xué)和軟件開發(fā)不同谒养,軟件開發(fā)是工程,是手藝明郭,造輪子是寫代碼的一大樂趣买窟。開發(fā)過程中常常要做出多方面的權(quán)衡(例如CAP),難有明確的對錯薯定。
密碼學(xué)就不一樣了始绍。密碼學(xué)是科學(xué),不是工程话侄,有嚴(yán)格的技術(shù)規(guī)范亏推,嚴(yán)禁沒有經(jīng)過學(xué)術(shù)訓(xùn)練者隨意創(chuàng)造。要有嚴(yán)謹(jǐn)?shù)睦碚摻D甓眩瑖?yán)密的數(shù)學(xué)證明吞杭。少有需要權(quán)衡的地方,正確就是正確变丧,錯誤就是錯誤芽狗。
密碼學(xué)有很多陷阱,設(shè)計密碼學(xué)協(xié)議或者軟件痒蓬,是極其容易出錯的高風(fēng)險專業(yè)活動译蒂,單純的碼農(nóng)背景是做不了的。本著不作死就不會死的偉大理念谊却,首先推薦讀者盡可能使用 TLS 這種標(biāo)準(zhǔn)化柔昼、開源、使用廣泛炎辨、久經(jīng)考驗捕透、高性能協(xié)議。
經(jīng)過幾十年的軍備競賽式發(fā)展,已經(jīng)發(fā)展出大量巧妙而狡猾的攻擊方法乙嘀,我們使用的算法末购,都是在所有已知攻擊方法下都無法攻破的,由于大多數(shù)碼農(nóng)并沒有精力去了解最前沿的攻擊方法虎谢,我們也就沒有能力去評價一個加密算法盟榴,更沒有能力自己發(fā)明算法。所以最好跟著業(yè)界的主流技術(shù)走婴噩,肯定不會有大錯擎场。
現(xiàn)在搞現(xiàn)代密碼學(xué)研究的主要都是數(shù)學(xué)家,在這領(lǐng)域里几莽,以一個碼農(nóng)的知識背景迅办,已經(jīng)很難理解最前沿的東西,連正確使用加密算法都是要謹(jǐn)慎謹(jǐn)慎再謹(jǐn)慎章蚣。一個碼農(nóng)站欺,能了解密碼學(xué)基本概念,跟進(jìn)密碼學(xué)的最新應(yīng)用趨勢纤垂,并正確配置部署TLS這種協(xié)議矾策,就很不錯了。
本文也只是整理一些粗淺的密碼學(xué)常識峭沦,讀完這篇文章贾虽,并不能使你具有設(shè)計足夠安全的密碼學(xué)能力。
上面提到過的密碼學(xué)算法很難被正確地使用熙侍,各種細(xì)節(jié)非常容易出錯榄鉴。 例如:
- 大多數(shù)碼農(nóng)都聽說過aes,可是你又了解多少細(xì)節(jié)呢蛉抓,比如:aes應(yīng)該用哪種模式庆尘?應(yīng)該用哪種padding?IV/nonce應(yīng)該取多少bit巷送?IV/nonce應(yīng)該怎么生成驶忌? key size應(yīng)該選多大?key應(yīng)該怎么生成笑跛?應(yīng)不應(yīng)該加MAC付魔?MAC算法的選擇?MAC和加密應(yīng)該怎么組合飞蹂?
- 大多數(shù)知道RSA的碼農(nóng)分不清 RSASSA-PKCS1-v1_5 几苍、RSAES-OAEP 和 RSASSA-PSS?
- 更多錯誤參見 stackoverflow問答陈哑,強烈推薦仔細(xì)閱讀
有沒有被這一連串的問題弄懵逼妻坝?點開 stackoverflow 之后更是不知所云伸眶,備受打擊?沒關(guān)系刽宪,下面跟我一起來完成這個補完計劃吧厘贼。
下文我提到的每個算法都是當(dāng)前安全的,哪些過時或被破解的不在本文討論范圍內(nèi)
在各種適用場景下圣拄,你應(yīng)該使用的現(xiàn)代密碼學(xué)算法:
加密數(shù)據(jù)
適用場景:需要避免把明文數(shù)據(jù)在網(wǎng)絡(luò)上傳輸?shù)臅r候嘴秸。
推薦選擇:(1) 首選NaCl,或者libsodium庇谆。使用crypto_secretbox() 或 crypto_secretbox_open() 函數(shù) 岳掐;(2) Chacha20-Poly1305算法;(3) AES-GCM 算法族铆;
以上3種算法岩四,都是AEAD類的算法哭尝,目前來看是最好的選擇哥攘。
并且,我們還應(yīng)該:
- 避免AES-ECB
- 避免AES-CTR
- 避免64bit塊大小的塊加密算法
- 避免OFB模式
- 不要使用RC4材鹦,RC4已經(jīng)被攻破
我們先看看 AES-ECB 和 AES-CTR 存在什么問題逝淹,再看 AES-GCM 是怎么解決的。
- Electronic Codebook Book (ECB)
電碼本模式桶唐,將整個明文進(jìn)行分組栅葡,分組長度可為128,256尤泽,或512bits欣簇,然后對每個小組進(jìn)行加密。
可以看出坯约,明文中重復(fù)的排列會反映在密文中熊咽。并且,當(dāng)密文被篡改時闹丐,解密后對應(yīng)的明文分組也會出錯横殴,且解密者察覺不到密文被篡改了。也就是說卿拴,ECB不能提供對密文的完整性校驗衫仑。
因此,在任何情況下都不推薦使用ECB模式堕花。
Ek
使用秘鑰k對輸入做對稱加密運算
- CounTeR (CTR)
計數(shù)器模式文狱,我們不再對密文進(jìn)行加密,而是對一個逐次累加的計數(shù)器進(jìn)行加密缘挽,用加密后的比特序列與明文分組進(jìn)行 XOR 得到密文瞄崇。過程如下圖:
該模式下陷虎,每次與明文分組進(jìn)行XOR的比特序列是不同的,因此杠袱,計數(shù)器模式解決了ECB模式中尚猿,相同的明文會得到相同的密文的問題。
但CTR仍然不能提供密文消息完整性校驗的功能楣富。
有的人可能會想到凿掂,如果將密文的hash值隨密文一起發(fā)送,密文接收者對收到的密文計算hash值纹蝴,與收到的hash值進(jìn)行比對庄萎,這樣是否就能校驗消息的完整性呢?
再仔細(xì)想想塘安,就能發(fā)現(xiàn)這其中的漏洞糠涛。當(dāng)篡改者截獲原始的密文消息時,先篡改密文兼犯,而后計算篡改后的密文hash, 替換掉原始消息中的密文hash忍捡。這樣,消息接收者仍然沒有辦法發(fā)現(xiàn)對源密文的篡改切黔。
可見砸脊,使用單向散列函數(shù)計算hash值仍然不能解決消息完整性校驗的問題。
XOR
異或纬霞,英文為exclusive OR凌埂。是一個數(shù)學(xué)運算符,應(yīng)用于邏輯運算诗芜。數(shù)學(xué)符號為“⊕”瞳抓,計算機符號為“xor”。
異或也叫半加運算伏恐,其運算法則相當(dāng)于不帶進(jìn)位的二進(jìn)制加法孩哑。
運算法則為:0⊕0=0,1⊕0=1脐湾,0⊕1=1臭笆,1⊕1=0(同為0,異為1)秤掌。
MAC (Message Authentication Code)
想要校驗消息的完整性愁铺,必須引入另一個概念:消息驗證碼。消息驗證碼是一種與秘鑰相關(guān)的單項散列函數(shù)闻鉴。
密文的收發(fā)雙方需要提前共享一個秘鑰茵乱,例如當(dāng)韓梅梅向李雷發(fā)送消息m時,不僅僅發(fā)送消息m孟岛,還要發(fā)送一個由MAC函數(shù)計算得到的MAC值瓶竭。李雷會用自己的密鑰對收到的消息m再次進(jìn)行MAC計算督勺,并判斷這個值與收到的MAC值是否相等,如果不匹配則說明可能消息m被篡改了斤贰。由于竊聽者不知道秘鑰智哀,所以不能為篡改后的消息計算出正確的MAC值。-
GMAC (Galois message authentication code mode)
伽羅瓦消息驗證碼荧恍,GMAC就是利用伽羅華域(Galois Field瓷叫,GF,有限域)乘法運算來計算消息的MAC值送巡。假設(shè)秘鑰長度為128bits, 當(dāng)密文大于128bits時摹菠,需要將密文按128bits進(jìn)行分組。流程如下圖:
Mh
將輸入與秘鑰h在有限域GF(2^128)上做乘法
- GCM (Galois/Counter Mode)
AES-GCM中的G就是指GMAC骗爆,C就是指CTR次氨。是一種AEAD,是目前TLS的主力算法摘投,互聯(lián)網(wǎng)上https流量的大部分依賴使用AES-GCM煮寡。
GCM可以提供對消息的加密和完整性校驗,另外谷朝,它還可以提供附加消息的完整性校驗洲押。在實際應(yīng)用場景中武花,有些信息是我們不需要保密圆凰,但信息的接收者需要確認(rèn)它的真實性的,例如源IP体箕、源端口专钉、目的IP和IV等等。因此累铅,我們可以將這一部分作為附加消息加入到MAC值的計算當(dāng)中跃须。
AEAD
在通常的密碼學(xué)應(yīng)用中,Confidentiality (保密) 用加密實現(xiàn)娃兽,Message authentication (消息認(rèn)證) 用MAC實現(xiàn)菇民。這兩種算法的配合方式,引發(fā)了很多安全漏洞投储,過去曾經(jīng)有3種方法:
- Encrypt-and-MAC
- MAC-then-Encrypt
- Encrypt-then-MAC
后來發(fā)現(xiàn),1和2都是有安全問題玛荞,所以2008年起,逐漸提出了“用一個算法在內(nèi)部同時實現(xiàn)cipher+MAC”的idea勋眯,稱為 AEAD(Authenticated encryption with additional data)婴梧。 在這種概念里,cipher+MAC 被 一個AEAD算法替換塞蹭。Authenticated encryption
我們再看看另外幾個推薦的加密庫
NaCl
NaCl 是密碼學(xué)學(xué)術(shù)權(quán)威 Daniel J. Bernstein教授設(shè)計的一個密碼學(xué)算法庫,2008年發(fā)開始公布番电。NaCl的特點是:api簡潔而易用竟坛,高性能钧舌,高安全性担汤,主要用于網(wǎng)絡(luò)通信、加密洼冻、解密崭歧、簽名等,NaCl提供了構(gòu)建高層密碼學(xué)工具的核心功能撞牢。目前僅有C和Python版率碾。
libsodium
libsodium 是對NaCl庫的一個分支,進(jìn)一步改進(jìn)接口易用性屋彪,和可移植性所宰。網(wǎng)站看上去清爽多了,還提供了GitHub地址
ChaCha20-poly1305
是一種AEAD畜挥,提出者是Daniel J. Bernstein教授仔粥。由 ChaCha20流密碼 和 Poly1305消息認(rèn)證碼( MAC )結(jié)合的一種應(yīng)用在互聯(lián)網(wǎng)安全協(xié)議中的認(rèn)證加密算法,由Google公司率先在Andriod移動平臺中的Chrome中代替 RC4 使用蟹但。由于其算法精簡躯泰、安全性強、兼容性強等特點华糖,目前Google致力于全面將其在移動端推廣麦向。
對稱簽名
適用場景:安全加固一個API,各種開放API的調(diào)用方認(rèn)證
如果你需要對一個API做認(rèn)證( authenticating )客叉,但是不需要做加密( encrypting )诵竭,記得千萬不要自己發(fā)明算法,你自己發(fā)明的MAC算法基本都有安全漏洞兼搏,如果不信卵慰,請Google一下 “長度擴(kuò)展攻擊” 長度擴(kuò)展攻擊 ,Flickr的漏洞案例
同時向族,必須要注意的是呵燕,要使用一個常數(shù)時間字符串對比算法(這個地方和碼農(nóng)的常識完全相反,請務(wù)必留意)
此外件相,應(yīng)該
- 避免自行設(shè)計的“帶密碼的hash”結(jié)構(gòu)再扭,你的設(shè)計基本都是有安全漏洞氧苍;
- 避免HMAC-MD5,避免HMAC-SHA1泛范,使用HMAC-SHA256, HMAC-SHA512等让虐;
- 避免復(fù)雜的多項式MAC;
- 避免加密hash值的結(jié)構(gòu)罢荡;
- 避免CRC赡突;
未完待續(xù)……