摘要:加解密偽代碼加密解密非對(duì)稱加密又稱公開秘鑰加密。常見的非對(duì)稱加密算法。通常來(lái)說(shuō)對(duì)稱加密速度要快于非對(duì)稱加密。在之后的通訊階段,可以使用對(duì)稱加密算法對(duì)數(shù)據(jù)進(jìn)行加密,秘鑰則是握手階段生成的。確認(rèn)信息完整未被篡改。
一、 文章概述
互聯(lián)網(wǎng)時(shí)代,網(wǎng)絡(luò)上的數(shù)據(jù)量每天都在以驚人的速度增長(zhǎng)。同時(shí),各類網(wǎng)絡(luò)安全問(wèn)題層出不窮。在信息安全重要性日益凸顯的今天,作為一名開發(fā)者,需要加強(qiáng)對(duì)安全的認(rèn)識(shí),并通過(guò)技術(shù)手段增強(qiáng)服務(wù)的安全性。
crypto模塊是nodejs的核心模塊之一,它提供了安全相關(guān)的功能,如摘要運(yùn)算、加密、電子簽名等。很多初學(xué)者對(duì)著長(zhǎng)長(zhǎng)的API列表,不知如何上手,因此它背后涉及了大量安全領(lǐng)域的知識(shí)。
本文重點(diǎn)講解API背后的理論知識(shí),主要包括如下內(nèi)容:
摘要(hash)、基于摘要的消息驗(yàn)證碼(HMAC)
對(duì)稱加密、非對(duì)稱加密、電子簽名
分組加密模式
本文摘錄自《Nodejs學(xué)習(xí)筆記》,更多章節(jié)及更新,請(qǐng)?jiān)L問(wèn) github主頁(yè)地址。二、摘要(hash)
摘要(digest):將長(zhǎng)度不固定的消息作為輸入,通過(guò)運(yùn)行hash函數(shù),生成固定長(zhǎng)度的輸出,這段輸出就叫做摘要。通常用來(lái)驗(yàn)證消息完整、未被篡改。
摘要運(yùn)算是不可逆的。也就是說(shuō),輸入固定的情況下,產(chǎn)生固定的輸出。但知道輸出的情況下,無(wú)法反推出輸入。
偽代碼如下。
digest = Hash(message)
常見的摘要算法 與 對(duì)應(yīng)的輸出位數(shù)如下:
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進(jìn)制 // 5d41402abc4b2a76b9719d911017c592
備注:在各類文章或文獻(xiàn)中,摘要、hash、散列 這幾個(gè)詞經(jīng)常會(huì)混用,導(dǎo)致不少初學(xué)者看了一臉懵逼,其實(shí)大部分時(shí)候指的都是一回事,記住上面對(duì)摘要的定義就好了。三、MAC、HMAC
MAC(Message Authentication Code):消息認(rèn)證碼,用以保證數(shù)據(jù)的完整性。運(yùn)算結(jié)果取決于消息本身、秘鑰。
MAC可以有多種不同的實(shí)現(xiàn)方式,比如HMAC。
HMAC(Hash-based Message Authentication Code):可以粗略地理解為帶秘鑰的hash函數(shù)。
nodejs例子如下:
const crypto = require("crypto"); // 參數(shù)一:摘要函數(shù) // 參數(shù)二:秘鑰 let hmac = crypto.createHmac("md5", "123456"); let ret = hmac.update("hello").digest("hex"); console.log(ret); // 9c699d7af73a49247a239cb0dd2f8139四、對(duì)稱加密、非對(duì)稱加密
加密/解密:給定明文,通過(guò)一定的算法,產(chǎn)生加密后的密文,這個(gè)過(guò)程叫加密。反過(guò)來(lái)就是解密。
encryptedText = encrypt( plainText )
plainText = decrypt( encryptedText )
秘鑰:為了進(jìn)一步增強(qiáng)加/解密算法的安全性,在加/解密的過(guò)程中引入了秘鑰。秘鑰可以視為加/解密算法的參數(shù),在已知密文的情況下,如果不知道解密所用的秘鑰,則無(wú)法將密文解開。
encryptedText = encrypt(plainText, encryptKey)
plainText = decrypt(encryptedText, decryptKey)
根據(jù)加密、解密所用的秘鑰是否相同,可以將加密算法分為對(duì)稱加密、非對(duì)稱加密。
1、對(duì)稱加密加密、解密所用的秘鑰是相同的,即encryptKey === decryptKey。
常見的對(duì)稱加密算法:DES、3DES、AES、Blowfish、RC5、IDEA。
加、解密偽代碼:
encryptedText = encrypt(plainText, key); // 加密2、非對(duì)稱加密
plainText = decrypt(encryptedText, key); // 解密
又稱公開秘鑰加密。加密、解密所用的秘鑰是不同的,即encryptKey !== decryptKey。
加密秘鑰公開,稱為公鑰。解密秘鑰保密,稱為秘鑰。
常見的非對(duì)稱加密算法:RSA、DSA、ElGamal。
加、解密偽代碼:
encryptedText = encrypt(plainText, publicKey); // 加密3、對(duì)比與應(yīng)用
plainText = decrypt(encryptedText, priviteKey); // 解密
除了秘鑰的差異,還有運(yùn)算速度上的差異。通常來(lái)說(shuō):
對(duì)稱加密速度要快于非對(duì)稱加密。
非對(duì)稱加密通常用于加密短文本,對(duì)稱加密通常用于加密長(zhǎng)文本。
兩者可以結(jié)合起來(lái)使用,比如HTTPS協(xié)議,可以在握手階段,通過(guò)RSA來(lái)交換生成對(duì)稱秘鑰。在之后的通訊階段,可以使用對(duì)稱加密算法對(duì)數(shù)據(jù)進(jìn)行加密,秘鑰則是握手階段生成的。
備注:對(duì)稱秘鑰交換不一定通過(guò)RSA,還可以通過(guò)類似DH來(lái)完成,這里不展開。五、數(shù)字簽名
從簽名大致可以猜到數(shù)字簽名的用途。主要作用如下:
確認(rèn)信息來(lái)源于特定的主體。
確認(rèn)信息完整、未被篡改。
為了達(dá)到上述目的,需要有兩個(gè)過(guò)程:
發(fā)送方:生成簽名。
接收方:驗(yàn)證簽名。
1、發(fā)送方生成簽名計(jì)算原始信息的摘要。
通過(guò)私鑰對(duì)摘要進(jìn)行簽名,得到電子簽名。
將原始信息、電子簽名,發(fā)送給接收方。
附:簽名偽代碼
digest = hash(message); // 計(jì)算摘要2、接收方驗(yàn)證簽名
digitalSignature = sign(digest, priviteKey); // 計(jì)算數(shù)字簽名
通過(guò)公鑰解開電子簽名,得到摘要D1。(如果解不開,信息來(lái)源主體校驗(yàn)失敗)
計(jì)算原始信息的摘要D2。
對(duì)比D1、D2,如果D1等于D2,說(shuō)明原始信息完整、未被篡改。
附:簽名驗(yàn)證偽代碼
digest1 = verify(digitalSignature, publicKey); // 獲取摘要3、對(duì)比非對(duì)稱加密
digest2 = hash(message); // 計(jì)算原始信息的摘要
digest1 === digest2 // 驗(yàn)證是否相等
由于RSA算法的特殊性,加密/解密、簽名/驗(yàn)證 看上去特別像,很多同學(xué)都很容易混淆。先記住下面結(jié)論,后面有時(shí)間再詳細(xì)介紹。
加密/解密:公鑰加密,私鑰解密。
簽名/驗(yàn)證:私鑰簽名,公鑰驗(yàn)證。
六、分組加密模式、填充、初始化向量常見的對(duì)稱加密算法,如AES、DES都采用了分組加密模式。這其中,有三個(gè)關(guān)鍵的概念需要掌握:模式、填充、初始化向量。
搞清楚這三點(diǎn),才會(huì)知道crypto模塊對(duì)稱加密API的參數(shù)代表什么含義,出了錯(cuò)知道如何去排查。
1、分組加密模式所謂的分組加密,就是將(較長(zhǎng)的)明文拆分成固定長(zhǎng)度的塊,然后對(duì)拆分的塊按照特定的模式進(jìn)行加密。
常見的分組加密模式有:ECB(不安全)、CBC(最常用)、CFB、OFB、CTR等。
以最簡(jiǎn)單的ECB為例,先將消息拆分成等分的模塊,然后利用秘鑰進(jìn)行加密。
圖片來(lái)源:這里,更多關(guān)于分組加密模式的介紹可以參考 wiki。
后面假設(shè)每個(gè)塊的長(zhǎng)度為128位2、初始化向量:IV
為了增強(qiáng)算法的安全性,部分分組加密模式(CFB、OFB、CTR)中引入了初始化向量(IV),使得加密的結(jié)果隨機(jī)化。也就是說(shuō),對(duì)于同一段明文,IV不同,加密的結(jié)果不同。
以CBC為例,每一個(gè)數(shù)據(jù)塊,都與前一個(gè)加密塊進(jìn)行亦或運(yùn)算后,再進(jìn)行加密。對(duì)于第一個(gè)數(shù)據(jù)塊,則是與IV進(jìn)行亦或。
IV的大小跟數(shù)據(jù)塊的大小有關(guān)(128位),跟秘鑰的長(zhǎng)度無(wú)關(guān)。
如圖所示,圖片來(lái)源 這里
3、填充:padding分組加密模式需要對(duì)長(zhǎng)度固定的塊進(jìn)行加密。分組拆分完后,最后一個(gè)數(shù)據(jù)塊長(zhǎng)度可能小于128位,此時(shí)需要進(jìn)行填充以滿足長(zhǎng)度要求。
填充方式有多重。常見的填充方式有PKCS7。
假設(shè)分組長(zhǎng)度為k字節(jié),最后一個(gè)分組長(zhǎng)度為k-last,可以看到:
不管明文長(zhǎng)度是多少,加密之前都會(huì)會(huì)對(duì)明文進(jìn)行填充 (不然解密函數(shù)無(wú)法區(qū)分最后一個(gè)分組是否被填充了,因?yàn)榇嬖谧詈笠粋€(gè)分組長(zhǎng)度剛好等于k的情況)
如果最后一個(gè)分組長(zhǎng)度等于k-last === k,那么填充內(nèi)容為一個(gè)完整的分組 k k k ... k (k個(gè)字節(jié))
如果最后一個(gè)分組長(zhǎng)度小于k-last < k,那么填充內(nèi)容為 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概括來(lái)說(shuō)
分組加密:先將明文切分成固定長(zhǎng)度的塊(128位),再進(jìn)行加密。
分組加密的幾種模式:ECB(不安全)、CBC(最常用)、CFB、OFB、CTR。
填充(padding):部分加密模式,當(dāng)最后一個(gè)塊的長(zhǎng)度小于128位時(shí),需要通過(guò)特定的方式進(jìn)行填充。(ECB、CBC需要填充,CFB、OFB、CTR不需要填充)
初始化向量(IV):部分加密模式(CFB、OFB、CTR)會(huì)將 明文塊 與 前一個(gè)密文塊進(jìn)行亦或操作。對(duì)于第一個(gè)明文塊,不存在前一個(gè)密文塊,因此需要提供初始化向量IV(把IV當(dāng)做第一個(gè)明文塊 之前的 密文塊)。此外,IV也可以讓加密結(jié)果隨機(jī)化。
七、寫在后面crypto模塊涉及的安全知識(shí)較多,篇幅所限,這里沒(méi)辦法一一展開。為了講解方便,部分內(nèi)容可能不夠嚴(yán)謹(jǐn),如有錯(cuò)漏敬請(qǐng)指出。
有疑問(wèn)或感興趣的同學(xué)歡迎留言交流,也可留意我的github關(guān)注最新內(nèi)容更新《nodejs-learning-guide》。
八、相關(guān)鏈接Nodejs學(xué)習(xí)筆記
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的公鑰和私鑰到底哪個(gè)才是用來(lái)加密和哪個(gè)用來(lái)解密? - 劉巍然-學(xué)酥的回答 - 知乎
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/11318.html
摘要:非對(duì)稱加密的理論知識(shí),可以參考筆者前面的文章進(jìn)階模塊之理論篇。非對(duì)稱加密中,公鑰加密,私鑰解密,加解密對(duì)應(yīng)的分別如下。相關(guān)鏈接程序猿小卡的學(xué)習(xí)筆記非對(duì)稱解密出錯(cuò) 前言 剛回答了SegmentFault上一個(gè)兄弟提的問(wèn)題《非對(duì)稱解密出錯(cuò)》。這個(gè)屬于Node.js在安全上的應(yīng)用,遇到同樣問(wèn)題的人應(yīng)該不少,基于回答的問(wèn)題,這里簡(jiǎn)單總結(jié)下。 非對(duì)稱加密的理論知識(shí),可以參考筆者前面的文章《NOD...
摘要:背景前一陣子比特股的創(chuàng)始人質(zhì)疑了系統(tǒng)中的一系列問(wèn)題,絕大多數(shù)都被的創(chuàng)始人之一正面回應(yīng)過(guò)了,具體可以看看這個(gè)但是有一個(gè)問(wèn)題沒(méi)有回應(yīng)或者說(shuō)還沒(méi)有提出解決方案。的組合堪稱完美。 背景 前一陣子比特股的創(chuàng)始人Daniel Larimer質(zhì)疑了lisk系統(tǒng)中的一系列問(wèn)題,絕大多數(shù)都被lisk的創(chuàng)始人之一Max正面回應(yīng)過(guò)了,具體可以看看這個(gè)http://ethereum.stackexchange...
摘要:在中加密是一個(gè)很簡(jiǎn)單卻又不能忽略的模塊,數(shù)據(jù)只有加密起來(lái)才更安全,這樣就散算據(jù)庫(kù)密碼泄漏也都是密文。當(dāng)然也可以自定義構(gòu)造方法,來(lái)制定用其他的方案進(jìn)行加密。應(yīng)用先示范下使用系統(tǒng)的來(lái)演示下簡(jiǎn)單的注入構(gòu)造加密方案 在 Spring Security 中加密是一個(gè)很簡(jiǎn)單卻又不能忽略的模塊,數(shù)據(jù)只有加密起來(lái)才更安全,這樣就散算據(jù)庫(kù)密碼泄漏也都是密文。本文分析對(duì)應(yīng)的版本是 5.14。 概念 Spr...
摘要:攻擊方式端口掃描攻擊洪水攻擊洪水攻擊跳轉(zhuǎn)攻擊防范手段保證服務(wù)器系統(tǒng)的安全確保服務(wù)器軟件沒(méi)有任何漏洞,防止攻擊者入侵。 前端需要知道的web安全知識(shí) 標(biāo)簽(空格分隔): 未分類 安全 [Doc] Crypto (加密) [Doc] TLS/SSL [Doc] HTTPS [Point] XSS [Point] CSRF [Point] 中間人攻擊 [Point] Sql/Nosql ...
閱讀 2955·2021-10-14 09:42
閱讀 3716·2021-08-11 11:19
閱讀 3557·2019-08-30 13:57
閱讀 3142·2019-08-30 13:49
閱讀 1554·2019-08-29 18:38
閱讀 910·2019-08-29 13:16
閱讀 1867·2019-08-26 13:25
閱讀 3241·2019-08-26 13:24