導讀
這是我的第一篇博文。在我本科學到的密碼學課上,密碼學就給我留下了理論艱深,概念繁多的可怕陰影,秘鑰長度之長,處理過程之繁瑣曾讓我一度懷疑自己不是一個合格的工科生。因區塊鏈開發中再次涉及到了密碼學的相關知識,所以這幾天又系統的學習了一遍,本文是一些對密碼學的知識的整理。首先,我會對密碼學學科的概念及背景進行簡單介紹。其次,我會通過具體案例來說明密碼學的安全原理。最后,我對現在不同的加密算法庫及其應用場景進行了分類整理,方面大家對照選取。
本文的主要參考博客如下:
《現代密碼學指南》https://blog.helong.info/blog/2015/06/06/modern-crypto/
《Node.js區塊鏈開發》https://blog.csdn.net/shebao3333/article/details/79538354
一.為什么需要密碼學?
就如人穿衣是為了保證個體隱私性一樣,在復雜的互聯網上傳輸的數據同樣需要隱私性。密碼學作為一門研究如何隱秘的傳輸信息的學科,是為互聯網中傳輸數據穿衣加盾的最好工具。
二.密碼學如何保證信息安全?
著名密碼學家Colin Percival 在其公開演講Everything you need to know about cryptography in 1 hour中曾指出,密碼學被攻破常常是因為編寫者使用錯誤的工具或者以錯誤的方式使用它們,經驗告訴我們不要嘗試親自寫密碼學代碼,因為那往往都是有漏洞的。
密碼學中主要研究三個對象:
1.明文(plaintext):我們想要保護的原始數據
2.密文(ciphertext):經過密碼學加密處理后的數據,這部分數據往往會被攻擊者得到
3.秘鑰(secret key):是明文密文相互轉化的工具
下面我會以《Node.js區塊鏈開發》中的一個小例子,來具體說明密碼學是如何保證數據在互聯網中的安全傳輸的。
安全需求:
一個男生Bob想要和自己心儀的女生Alice表白,說出“I LOVE YOU”。但是Bob很靦腆不敢當面表達自己的心聲,因此他就想到將這句話使用信息加密的方式傳輸給他,讓女生Alice使用密碼進行解密,搞一波摩爾斯電碼的浪漫。為了保證男生可以以這種方式表白成功,他需要考慮以下四個問題:
(1)加密:信息只能女生Alice看見,其他人不可以看見
(2)解密:女生Alice在收到加密后的信息后,可以成功解密得到男生的心聲“I LOVE YOU”
(3)簽名:男生Bob為信息簽名,保證信息在傳遞的過程中不被修改,類似於我們日常生活中的筆跡簽名
(4)驗證:女生收到信息后根據簽名的簽名可以確定信息確實為男生所傳遞
解決步驟:
(1)生成密鑰對(密碼是打開密碼箱的唯一方式)
//加載工具模塊,crypto用來加密解密信息, ed25519用來簽名驗證信息
1 var crypto=require("crypto");
2 var ed25519=require("ed25519");
//選取密碼,生成對應信息摘要,繼而生成相應的公私鑰對 BobKeyPair(publickey,privatekey)
1 var password="123456"; //密碼 2 var hash=crypto.createHash("sha256").update(plaintext).digest(); //明文摘要 3 var BobKeyPair=ed25519.MakeKeypair(hash); //為了使得心儀女生Alice知道心意,Bob將BobKeyPair.publicKey傳給Alice
(2)Bob加密信息
//使用公鑰 BobKeyPair.publicKey 進行加密
1 var plaintext="Alice,I Love you!"; //明文 2 var msgCiphered=cipher("aes192",BobKeyPair.publicKey,plaintext); //密文
(3)Bob給信息簽名
//使用私鑰 BobKeyPair.privateKey 進行簽名
1 var Bobsig=ed25519.Sign(new Buffer(msgCiphered,"utf-8"),BobKeyPair.privateKey);
(4)Alice驗證並解密加密后的信息(msgCiphered,Bobsig)
//為了安全起見,一般都是先驗證安全性,再去解密信息,這符合我們的常識
//使用Bob之前提供的公鑰進行簽名認證,確認信息的發送者確實是Bob則進行解密操作,否則返回錯誤信息
1 if(ed25519.Verify(new Buffer(msgCiphered,"utf-8"),BobSig,BobKeyPair.publicKey)){ 2 console.log("簽名合法,確實是Bob發來的信息!"); 3 var Desmsg=decipher("aes192",BobKeyPair.publicKey msgCiphered); 4 console.log("Bob said:"+Desmsg); 5 ) else{ 6 console.log("對方不是Bob,要小心"); 7 }
經過一系列的操作,Bob終於表達了自己的想法,且保證沒有被其他人發現自己的心思。希望以上的小故事能讓你對密碼學的加解密過程有一個大致的了解,對密碼學的探索欲望也強了一點。
三.不同情境下如何選擇相應的加密算法?
上一節密碼學如何保證信息安全中有提到,秘鑰(secret key)是明文與密文成功轉換的關鍵所在。因此就有了著名的對稱加密和非對稱加密兩種算法。接下來我會從不同的方面分別給出對應的選擇策略
對稱加密:加密和解密的秘鑰key至始至終使用的是同一個
非對稱加密:加密和解密相互轉換時使用的秘鑰不同,一個叫公鑰一個叫私鑰
1.數據加密算法選擇(ECC>RSA)
(1)NaCl庫/libsodium庫中的crypto_secretbox()/crypto_secretbox_open() 函數》》》》》》》》(2)Chacha20-Poly1305 算法》》》》》》》》》(3)AES-GCM 算法
三者按優先級排序推薦使用,具體區別請查看《現代密碼學實踐指南》
2.秘鑰長度選擇(推薦256bit)
下表對比了相同安全程度時,不同算法的密鑰長度,單位:bit
3.簽名算法選擇
對稱加密:HMAC類算法(擇SHA2類的算法:: SHA-256, SHA-384, SHA-512, SHA-512/256)
SHA2類算法的區別於介紹可見:https://en.wikipedia.org/wiki/SHA-2
非對稱加密:NaCl,Ed25519
4.隨機ID生成(推薦256bit)
一定要使用 /dev/urandom
避免用戶空間的隨機數生成器如:havaged,prngs,egd,等
5.客戶端-服務器結構層的傳輸協議選擇(TLS)
6.網站(支持https協議)選擇
OpenSSL,Google的BoringSSL,或者是 AWS的 ELB 都是不錯的選擇
后記
以上是在學習的過程中的一點積累和認識,因非專業密碼學專業出身里面難免會有不清楚的地方,希望以后可以再接再厲!!