Nodejs進階:crypto模塊中你須要掌握的安全基礎知識

1、 文章概述

互聯網時代,網絡上的數據量天天都在以驚人的速度增加。同時,各種網絡安全問題層出不窮。在信息安全重要性日益凸顯的今天,做爲一名開發者,須要增強對安全的認識,並經過技術手段加強服務的安全性。html

crypto模塊是nodejs的核心模塊之一,它提供了安全相關的功能,如摘要運算、加密、電子簽名等。不少初學者對着長長的API列表,不知如何上手,所以它背後涉及了大量安全領域的知識。node

本文重點講解API背後的理論知識,主要包括以下內容:git

  1. 摘要(hash)、基於摘要的消息驗證碼(HMAC)
  2. 對稱加密、非對稱加密、電子簽名
  3. 分組加密模式

2、摘要(hash)

摘要(digest):將長度不固定的消息做爲輸入,經過運行hash函數,生成固定長度的輸出,這段輸出就叫作摘要。一般用來驗證消息完整、未被篡改。github

摘要運算是不可逆的。也就是說,輸入固定的狀況下,產生固定的輸出。但知道輸出的狀況下,沒法反推出輸入。web

僞代碼以下。算法

digest = Hash(message)安全

常見的摘要算法 與 對應的輸出位數以下:網絡

  • MD5:128位
  • SHA-1:160位
  • SHA256 :256位
  • SHA512:512位

nodejs中的例子:編輯器

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、散列 這幾個詞常常會混用,致使很多初學者看了一臉懵逼,其實大部分時候指的都是一回事,記住上面對摘要的定義就行了。ide

3、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

複製代碼

4、對稱加密、非對稱加密

加密/解密:給定明文,經過必定的算法,產生加密後的密文,這個過程叫加密。反過來就是解密。

encryptedText = encrypt( plainText ) plainText = decrypt( encryptedText )

祕鑰:爲了進一步加強加/解密算法的安全性,在加/解密的過程當中引入了祕鑰。祕鑰能夠視爲加/解密算法的參數,在已知密文的狀況下,若是不知道解密所用的祕鑰,則沒法將密文解開。

encryptedText = encrypt(plainText, encryptKey) plainText = decrypt(encryptedText, decryptKey)

根據加密、解密所用的祕鑰是否相同,能夠將加密算法分爲對稱加密非對稱加密

一、對稱加密

加密、解密所用的祕鑰是相同的,即encryptKey === decryptKey

常見的對稱加密算法:DES、3DES、AES、Blowfish、RC五、IDEA。

加、解密僞代碼:

encryptedText = encrypt(plainText, key); // 加密 plainText = decrypt(encryptedText, key); // 解密

二、非對稱加密

又稱公開祕鑰加密。加密、解密所用的祕鑰是不一樣的,即encryptKey !== decryptKey

加密祕鑰公開,稱爲公鑰。解密祕鑰保密,稱爲祕鑰。

常見的非對稱加密算法:RSA、DSA、ElGamal。

加、解密僞代碼:

encryptedText = encrypt(plainText, publicKey); // 加密 plainText = decrypt(encryptedText, priviteKey); // 解密

三、對比與應用

除了祕鑰的差別,還有運算速度上的差別。一般來講:

  1. 對稱加密速度要快於非對稱加密。
  2. 非對稱加密一般用於加密短文本,對稱加密一般用於加密長文本。

二者能夠結合起來使用,好比HTTPS協議,能夠在握手階段,經過RSA來交換生成對稱祕鑰。在以後的通信階段,可使用對稱加密算法對數據進行加密,祕鑰則是握手階段生成的。

備註:對稱祕鑰交換不必定經過RSA,還能夠經過相似DH來完成,這裏不展開。

5、數字簽名

簽名大體能夠猜到數字簽名的用途。主要做用以下:

  1. 確認信息來源於特定的主體。
  2. 確認信息完整、未被篡改。

爲了達到上述目的,須要有兩個過程:

  1. 發送方:生成簽名。
  2. 接收方:驗證簽名。

一、發送方生成簽名

  1. 計算原始信息的摘要。
  2. 經過私鑰對摘要進行簽名,獲得電子簽名。
  3. 將原始信息、電子簽名,發送給接收方。

附:簽名僞代碼

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

二、接收方驗證簽名

  1. 經過公鑰解開電子簽名,獲得摘要D1。(若是解不開,信息來源主體校驗失敗)
  2. 計算原始信息的摘要D2。
  3. 對比D一、D2,若是D1等於D2,說明原始信息完整、未被篡改。

附:簽名驗證僞代碼

digest1 = verify(digitalSignature, publicKey); // 獲取摘要 digest2 = hash(message); // 計算原始信息的摘要 digest1 === digest2 // 驗證是否相等

三、對比非對稱加密

因爲RSA算法的特殊性,加密/解密、簽名/驗證 看上去特別像,不少同窗都很容易混淆。先記住下面結論,後面有時間再詳細介紹。

  1. 加密/解密:公鑰加密,私鑰解密。
  2. 簽名/驗證:私鑰簽名,公鑰驗證。

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

常見的對稱加密算法,如AES、DES都採用了分組加密模式。這其中,有三個關鍵的概念須要掌握:模式、填充、初始化向量。

搞清楚這三點,纔會知道crypto模塊對稱加密API的參數表明什麼含義,出了錯知道如何去排查。

一、分組加密模式

所謂的分組加密,就是將(較長的)明文拆分紅固定長度的塊,而後對拆分的塊按照特定的模式進行加密。

常見的分組加密模式有:ECB(不安全)、CBC(最經常使用)、CFB、OFB、CTR等。

以最簡單的ECB爲例,先將消息拆分紅等分的模塊,而後利用祕鑰進行加密。

圖片來源:這裏,更多關於分組加密模式的介紹能夠參考 wiki

後面假設每一個塊的長度爲128位

二、初始化向量:IV

爲了加強算法的安全性,部分分組加密模式(CFB、OFB、CTR)中引入了初始化向量(IV),使得加密的結果隨機化。也就是說,對於同一段明文,IV不一樣,加密的結果不一樣。

以CBC爲例,每個數據塊,都與前一個加密塊進行亦或運算後,再進行加密。對於第一個數據塊,則是與IV進行亦或。

IV的大小跟數據塊的大小有關(128位),跟祕鑰的長度無關。

如圖所示,圖片來源 這裏

三、填充:padding

分組加密模式須要對長度固定的塊進行加密。分組拆分完後,最後一個數據塊長度可能小於128位,此時須要進行填充以知足長度要求。

填充方式有多重。常見的填充方式有PKCS7

假設分組長度爲k字節,最後一個分組長度爲k-last,能夠看到:

  1. 無論明文長度是多少,加密以前都會會對明文進行填充 (否則解密函數沒法區分最後一個分組是否被填充了,由於存在最後一個分組長度恰好等於k的狀況)
  2. 若是最後一個分組長度等於k-last === k,那麼填充內容爲一個完整的分組 k k k ... k (k個字節)
  3. 若是最後一個分組長度小於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
複製代碼

歸納來講

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

7、寫在後面

crypto模塊涉及的安全知識較多,篇幅所限,這裏沒辦法一一展開。爲了講解方便,部份內容可能不夠嚴謹,若有錯漏敬請指出。

有疑問或感興趣的同窗歡迎留言交流,也可留意個人github關注最新內容更新《nodejs-learning-guide》

8、相關連接

Nodejs學習筆記

Cryptographic hash function

Hash-based message authentication code

HMAC vs MAC functions

What is the difference between MAC and HMAC?

Block cipher mode of operation

RSA的公鑰和私鑰到底哪一個纔是用來加密和哪一個用來解密? - 劉巍然-學酥的回答 - 知乎

相關文章
相關標籤/搜索