深度理解Nodejs中crypto模組的安全知識

前端攻城小牛發表於2018-12-31

本篇文章給大家詳細介紹了Nodejs中crypto模組的安全知識的相關內容,寫的十分的全面細緻,具有一定的參考價值,對此有需要的朋友可以參考學習下。如有不足之處,歡迎批評指正。

深度理解Nodejs中crypto模組的安全知識

網際網路時代,網路上的資料量每天都在以驚人的速度增長。同時,各類網路安全問題層出不窮。在資訊保安重要性日益凸顯的今天,作為一名開發者,需要加強對安全的認識,並通過技術手段增強服務的安全性。 crypto模組是nodejs的核心模組之一,它提供了安全相關的功能,如摘要運算、加密、電子簽名等。很多初學者對著長長的API列表,不知如何上手,因此它背後涉及了大量安全領域的知識。 本文重點講解API背後的理論知識,主要包括如下內容: 摘要(hash)、基於摘要的訊息驗證碼(HMAC) 對稱加密、非對稱加密、電子簽名 分組加密模式

摘要(hash)

摘要(digest):將長度不固定的訊息作為輸入,通過執行hash函式,生成固定長度的輸出,這段輸出就叫做摘要。通常用來驗證訊息完整、未被篡改。 摘要運算是不可逆的。也就是說,輸入固定的情況下,產生固定的輸出。但知道輸出的情況下,無法反推出輸入。 虛擬碼如下。 digest = Hash(message) 常見的摘要演算法 與 對應的輸出位數如下: MD5:128位 SHA-1:160位 SHA256 :256位 SHA512:512位 nodejs中的例子: /歡迎加入全棧開發交流圈一起學習交流:619586920

var crypto = require('crypto');
var md5 = crypto.createHash('md5');
var message = 'hello';
var digest = md5.update(message, 'utf8').digest('hex'); 
console.log(digest);
// 輸出如下:注意這裡是16進位制
// 5d41402abc4b2a76b9719d911017c592
複製程式碼

備註:在各類文章或文獻中,摘要、hash、雜湊 這幾個詞經常會混用,導致不少初學者看了一臉懵逼,其實大部分時候指的都是一回事,記住上面對摘要的定義就好了。

MAC、HMAC

MAC(Message Authentication Code):訊息認證碼,用以保證資料的完整性。運算結果取決於訊息本身、祕鑰。 MAC可以有多種不同的實現方式,比如HMAC。 HMAC(Hash-based Message Authentication Code):可以粗略地理解為帶祕鑰的hash函式。 nodejs例子如下:

const crypto = require('crypto');
// 引數一:摘要函式
// 引數二:祕鑰
let hmac = crypto.createHmac('md5', '123456');
let ret = hmac.update('hello').digest('hex');
console.log(ret);
// 9c699d7af73a49247a239cb0dd2f8139
/歡迎加入全棧開發交流圈一起學習交流:619586920
複製程式碼

對稱加密、非對稱加密 加密/解密:給定明文,通過一定的演算法,產生加密後的密文,這個過程叫加密。反過來就是解密。

encryptedText = encrypt( plainText )
plainText = decrypt( encryptedText )
複製程式碼

祕鑰:為了進一步增強加/解密演算法的安全性,在加/解密的過程中引入了祕鑰。祕鑰可以視為加/解密演算法的引數,在已知密文的情況下,如果不知道解密所用的祕鑰,則無法將密文解開。

encryptedText = encrypt(plainText, encryptKey)
plainText = decrypt(encryptedText, decryptKey)
複製程式碼

根據加密、解密所用的祕鑰是否相同,可以將加密演算法分為對稱加密、非對稱加密。 1、對稱加密 加密、解密所用的祕鑰是相同的,即encryptKey === decryptKey。 常見的對稱加密演算法:DES、3DES、AES、Blowfish、RC5、IDEA。 加、解密虛擬碼:

encryptedText = encrypt(plainText, key); // 加密
plainText = decrypt(encryptedText, key); // 解密
複製程式碼

2、非對稱加密 又稱公開祕鑰加密。加密、解密所用的祕鑰是不同的,即encryptKey !== decryptKey。 加密祕鑰公開,稱為公鑰。解密祕鑰保密,稱為祕鑰。 常見的非對稱加密演算法:RSA、DSA、ElGamal。 加、解密虛擬碼:

encryptedText = encrypt(plainText, publicKey); // 加密
plainText = decrypt(encryptedText, priviteKey); // 解密
複製程式碼

3、對比與應用 除了祕鑰的差異,還有運算速度上的差異。通常來說: 對稱加密速度要快於非對稱加密。 非對稱加密通常用於加密短文字,對稱加密通常用於加密長文字。 兩者可以結合起來使用,比如HTTPS協議,可以在握手階段,通過RSA來交換生成對稱祕鑰。在之後的通訊階段,可以使用對稱加密演算法對資料進行加密,祕鑰則是握手階段生成的。 備註:對稱祕鑰交換不一定通過RSA,還可以通過類似DH來完成,這裡不展開。 數字簽名 從簽名大致可以猜到數字簽名的用途。主要作用如下: 確認資訊來源於特定的主體。 確認資訊完整、未被篡改。 為了達到上述目的,需要有兩個過程: 傳送方:生成簽名。 接收方:驗證簽名。 1、傳送方生成簽名 計算原始資訊的摘要。 通過私鑰對摘要進行簽名,得到電子簽名。 將原始資訊、電子簽名,傳送給接收方。 附:簽名虛擬碼

digest = hash(message); // 計算摘要
digitalSignature = sign(digest, priviteKey); // 計算數字簽名
複製程式碼

2、接收方驗證簽名 通過公鑰解開電子簽名,得到摘要D1。(如果解不開,資訊來源主體校驗失敗) 計算原始資訊的摘要D2。 對比D1、D2,如果D1等於D2,說明原始資訊完整、未被篡改。 附:簽名驗證虛擬碼

digest1 = verify(digitalSignature, publicKey); // 獲取摘要
digest2 = hash(message); // 計算原始資訊的摘要
digest1 === digest2 // 驗證是否相等
/歡迎加入全棧開發交流圈一起學習交流:619586920
複製程式碼

3、對比非對稱加密 由於RSA演算法的特殊性,加密/解密、簽名/驗證 看上去特別像,很多同學都很容易混淆。先記住下面結論,後面有時間再詳細介紹。 加密/解密:公鑰加密,私鑰解密。 簽名/驗證:私鑰簽名,公鑰驗證。

分組加密模式、填充、初始化向量

常見的對稱加密演算法,如AES、DES都採用了分組加密模式。這其中,有三個關鍵的概念需要掌握:模式、填充、初始化向量。 搞清楚這三點,才會知道crypto模組對稱加密API的引數代表什麼含義,出了錯知道如何去排查。 1、分組加密模式 所謂的分組加密,就是將(較長的)明文拆分成固定長度的塊,然後對拆分的塊按照特定的模式進行加密。 常見的分組加密模式有:ECB(不安全)、CBC(最常用)、CFB、OFB、CTR等。 以最簡單的ECB為例,先將訊息拆分成等分的模組,然後利用祕鑰進行加密。

深度理解Nodejs中crypto模組的安全知識

後面假設每個塊的長度為128位 2、初始化向量:IV 為了增強演算法的安全性,部分分組加密模式(CFB、OFB、CTR)中引入了初始化向量(IV),使得加密的結果隨機化。也就是說,對於同一段明文,IV不同,加密的結果不同。 以CBC為例,每一個資料塊,都與前一個加密塊進行亦或運算後,再進行加密。對於第一個資料塊,則是與IV進行亦或。 IV的大小跟資料塊的大小有關(128位),跟祕鑰的長度無關。

深度理解Nodejs中crypto模組的安全知識

3、填充:padding 分組加密模式需要對長度固定的塊進行加密。分組拆分完後,最後一個資料塊長度可能小於128位,此時需要進行填充以滿足長度要求。 填充方式有多重。常見的填充方式有PKCS7。 假設分組長度為k位元組,最後一個分組長度為k-last,可以看到: 不管明文長度是多少,加密之前都會會對明文進行填充 (不然解密函式無法區分最後一個分組是否被填充了,因為存在最後一個分組長度剛好等於k的情況) 如果最後一個分組長度等於k-last === k,那麼填充內容為一個完整的分組 k k k ... k (k個位元組) 如果最後一個分組長度小於k-last < k,那麼填充內容為 k-last mod k

01 -- if lth mod k = k-1
02 02 -- if lth mod k = k-2
.
.
.
k k ... k k -- if lth mod k = 0
/歡迎加入全棧開發交流圈一起學習交流:619586920
複製程式碼

概括來說 分組加密:先將明文切分成固定長度的塊(128位),再進行加密。 分組加密的幾種模式:ECB(不安全)、CBC(最常用)、CFB、OFB、CTR。 填充(padding):部分加密模式,當最後一個塊的長度小於128位時,需要通過特定的方式進行填充。(ECB、CBC需要填充,CFB、OFB、CTR不需要填充) 初始化向量(IV):部分加密模式(CFB、OFB、CTR)會將 明文塊 與 前一個密文塊進行亦或操作。對於第一個明文塊,不存在前一個密文塊,因此需要提供初始化向量IV(把IV當做第一個明文塊 之前的 密文塊)。此外,IV也可以讓加密結果隨機化。

結語

感謝您的觀看,如有不足之處,歡迎批評指正。

本次給大家推薦一個免費的學習群,裡面概括移動應用網站開發,css,html,webpack,vue node angular以及面試資源等。 對web開發技術感興趣的同學,歡迎加入Q群:864305860,不管你是小白還是大牛我都歡迎,還有大牛整理的一套高效率學習路線和教程與您免費分享,同時每天更新視訊資料。 最後,祝大家早日學有所成,拿到滿意offer,快速升職加薪,走上人生巔峰。

相關文章