加密算法介紹
目前常用的加密算法主要有:哈希算法(比如MD5、SHA族窟哺、Hmac)瑰煎,對(duì)稱加密算法(比如AES)铺然,非對(duì)稱加密算法(RSA),以及Diffie-Hellman密鑰協(xié)商算法等等酒甸,這幾種算法都有各自的特點(diǎn)魄健,適合的場(chǎng)景也不一樣,這里只做簡(jiǎn)單的介紹插勤,想詳細(xì)了解的話沽瘦,網(wǎng)上資料很多革骨,可以自行查看相關(guān)的資料。
各類算法的特點(diǎn):
哈希算法:正向快速析恋,不可逆性良哲,即加密后是很難解密出明文的。經(jīng)常用于數(shù)據(jù)加密和數(shù)據(jù)校驗(yàn)助隧。
對(duì)稱加密算法:AES是一種常用的對(duì)稱加密算法筑凫,其特點(diǎn)是加解密都用同一個(gè)密鑰。
非對(duì)稱加密算法RSA:RSA算法是一種非對(duì)稱加密算法并村,由一個(gè)私鑰和一個(gè)公鑰構(gòu)成的密鑰對(duì)巍实,通過(guò)私鑰加密,公鑰解密哩牍,或者通過(guò)公鑰加密棚潦,私鑰解密。其中膝昆,公鑰可以公開(kāi)瓦盛,私鑰必須保密。
Diffie-Hellman密鑰協(xié)商算法:Diffie-Hellman是一種密鑰協(xié)商算法(簡(jiǎn)稱DH算法)外潜,DH算法基于一種數(shù)學(xué)原理,能夠在雙方不泄露密鑰的情況下協(xié)商出一種密鑰來(lái)挠唆。
場(chǎng)景描述
在客戶端向服務(wù)器端發(fā)送數(shù)據(jù)的過(guò)程中处窥,如果是比較重要的數(shù)據(jù)(比如密碼,敏感數(shù)據(jù)等)玄组,一般需要先在客戶端進(jìn)行加密后再發(fā)送滔驾,服務(wù)器接收到數(shù)據(jù)后再進(jìn)行解密得到原始數(shù)據(jù)。(反過(guò)來(lái)服務(wù)器返回?cái)?shù)據(jù)給客戶端也是一樣的道理)
這里假設(shè)客戶端和服務(wù)器端采用AES(對(duì)稱加密算法)進(jìn)行加解密傳輸?shù)臄?shù)據(jù)俄讹,AES加密算法有一個(gè)特點(diǎn)就是加解密都用同一個(gè)密鑰(這里把該密鑰稱作secretKey)哆致,所以雙方都通過(guò)secretKey進(jìn)行數(shù)據(jù)加解密。
因此在客戶端向服務(wù)器第一次傳輸數(shù)據(jù)的時(shí)候患膛,客戶端需要先向服務(wù)器端獲取secretKey摊阀,并且保存在客戶端,而這種直接向服務(wù)器獲取明文secretKey的過(guò)程是很容易被第三者攔截的踪蹬,也就是說(shuō)這一過(guò)程是不安全的胞此。(哈哈,除非是服務(wù)器把secretKey寫(xiě)到紙上跃捣,親手偷偷地遞給客戶端)
因此呢漱牵,客戶端向服務(wù)器獲取secretKey的這一過(guò)程,也是需要進(jìn)行加密的疚漆。
那么酣胀,服務(wù)器需要怎么做才能把secretKey安全的送達(dá)客戶端呢刁赦?
目前常采用的方法有:RSA 或 Diffie-Hellman
通過(guò)RSA安全傳輸密鑰
RSA有一個(gè)公鑰和一個(gè)私鑰,公鑰是允許公開(kāi)出去的闻镶,私鑰是保留的甚脉。RSA的要點(diǎn)在于用公鑰加密的數(shù)據(jù)需要用私鑰解密,用私鑰加密的數(shù)據(jù)儒溉,需要用公鑰解密宦焦。因此,比如這時(shí)候客戶端把公鑰發(fā)送給服務(wù)器顿涣,服務(wù)器利用客戶端的公鑰對(duì)secretKey進(jìn)行加密波闹,那么這份加密后的secretKey數(shù)據(jù),就只有客戶端的私鑰能解開(kāi)啦涛碑。即使第三者拿到了這份數(shù)據(jù)也解密不了精堕,除非能獲取到客戶端的私鑰。
所以蒲障,通過(guò)RSA的方式歹篓,服務(wù)器就能把secretKey安全的傳遞到客戶端的手里啦。(不過(guò)揉阎,RSA也是有安全漏洞的庄撮,被稱作中間人攻擊,由于篇幅原因毙籽,這里就先不講啦洞斯!大家自行百度。)
雖然使用RSA能夠安全的傳輸secretKey密鑰坑赡,但是麻煩點(diǎn)在于需要生成一對(duì)公鑰和私鑰烙如,并且把公鑰發(fā)送給對(duì)方,而且加解密速度比較慢毅否。所以亚铁,介紹第二種:Diffie-Hellman密鑰協(xié)商算法。
通過(guò)DH算法協(xié)商密鑰
嚴(yán)格來(lái)說(shuō)螟加,DH算法其實(shí)并不是一種加密算法徘溢,因?yàn)樗旧聿⒉皇怯糜诩用艿模业睦斫馐怯糜陔p方協(xié)商計(jì)算捆探,即雙方按照某種合約進(jìn)行計(jì)算甸昏,從而計(jì)算出一種相同的結(jié)果。
原理如下:
第一步:初始化
????比如現(xiàn)在服務(wù)器提供了兩個(gè)隨機(jī)公鑰數(shù)字(允許公開(kāi)):pubN=10徐许,modN=3;
???????客戶端自己生成了一個(gè)隨機(jī)私鑰數(shù)字(不可公開(kāi)施蜜,服務(wù)器也不知道):cPrivN=2;
服務(wù)器端也自己生成了一個(gè)隨機(jī)私鑰數(shù)字(不可公開(kāi),客戶端也不知道):sPrivN=4;
第二步:客戶端雌隅、服務(wù)器端分別基于相同的數(shù)學(xué)公式進(jìn)行計(jì)算翻默,計(jì)算結(jié)果稱作公鑰結(jié)果:pubResult
客戶端進(jìn)行數(shù)學(xué)計(jì)算:cPubResult = pubN * cPrivN % modN = 10 * 2 % 3 = 2缸沃;(計(jì)算結(jié)果允許公開(kāi))
服務(wù)器進(jìn)行數(shù)學(xué)計(jì)算:sPubResult = pubN * sPrivN % modN = 10 * 4 % 3 = 1;(計(jì)算結(jié)果允許公開(kāi))
客戶端和服務(wù)器端交換公鑰結(jié)果修械,客戶端得到sPubResult=1趾牧,服務(wù)器端得到cPubResult=2。
第三步:協(xié)商出一致的密鑰數(shù)字:keyN(客戶端和服務(wù)器端得出的結(jié)果是一致的)
客戶端:cKeyN = sPubResult * cPrivN % modN= 1 * 2 % 3 = 2肯污;
服務(wù)器:sKeyN = cPubResult * sPrivN % modN= 2 * 4 % 3 = 2翘单;
到目前為止呢,雙方都協(xié)商出了密鑰蹦渣,并且是一致的哄芜,但是呢,有沒(méi)有見(jiàn)過(guò)密鑰是number類型的柬唯?想必都沒(méi)有吧认臊,所以需要進(jìn)行第四步,生成更長(zhǎng)的密鑰锄奢。
第四步:對(duì)密鑰數(shù)字進(jìn)行hash生成密鑰串
const hash = crypto.createHash('sha256');
hash.update(this.keyN.toString());
this.secretKey = hash.digest('hex');