### crypto模塊概述
在Node.js中汗贫,使用OpenSSL類庫(kù)作為其內(nèi)部實(shí)現(xiàn)加密與解密處理的基礎(chǔ)手段镜沽,這是因?yàn)槟壳癘penSSL已經(jīng)成為了一個(gè)經(jīng)過(guò)嚴(yán)格測(cè)試的可靠的加密與解密算法的實(shí)現(xiàn)工具雪情。
在Node.js中启上,OpenSSL類庫(kù)被封裝在crypto模塊中薛训,因此開(kāi)發(fā)者可以使用crypto模塊來(lái)實(shí)現(xiàn)各種不同的加密與解密處理盆佣。例如,crypto模塊中包含了類似MD5或SHA-1之類的散列算法陨舱。開(kāi)發(fā)者也可以通過(guò)crypto模塊來(lái)實(shí)現(xiàn)HMAC運(yùn)算 [1]翠拣。在crypto模塊中葫掉,提供了一些加密方法來(lái)實(shí)現(xiàn)數(shù)據(jù)的可靠加密快骗。另外仪芒,在crypto模塊中穆咐,也提供了一些利用HMAC運(yùn)算來(lái)實(shí)現(xiàn)數(shù)字簽名以及對(duì)數(shù)字簽名進(jìn)行驗(yàn)證的方
法。
### 查看Node.js中能夠使用的所有加密算法
在crypto模塊中谜慌,為每一種加密算法定義了一個(gè)類然想。可以使用getCiphers方法
來(lái)查看Node.js中能夠使用的所有加密算法欣范。
```
crypto.getCiphers()
```
### 查看Node.js中能夠使用的所有散列算法
可以使用getHashes方法來(lái)查看在Node.js中能夠使用的所有散列算法变泄。
```
crypto.getHashes()
```
### 散列算法
散列(哈希)算法用來(lái)實(shí)現(xiàn)一些重要處理,例如恼琼,在允許對(duì)一段數(shù)據(jù)進(jìn)行驗(yàn)證的前提下妨蛹,將數(shù)據(jù)進(jìn)行模糊化,或者為一大段數(shù)據(jù)提供一個(gè)驗(yàn)證碼
在node中晴竞,為了使用散列算法蛙卤,首先應(yīng)該使用createHash方法創(chuàng)建一個(gè)hash對(duì)象。
```
let hash=crypto.createHash(algorithm)
```
- algorithm:參數(shù)值為一個(gè)在Node.js中可以使用的算法噩死,如'sha1'表窘、'md5'、'sha256'甜滨、'sha512'和'ripemd160'等,用于指定需要使用的散列算法瘤袖,該方法返回被創(chuàng)建的hash對(duì)象
在創(chuàng)建一個(gè)hash對(duì)象后可以通過(guò)使用該對(duì)象的update方法創(chuàng)建一個(gè)摘要衣摩。該方法的使用方式如下所示
```
hash.update(data,[input_encoding])
```
- data:參數(shù)值為一個(gè)Buffer對(duì)象或一個(gè)字符串,用于指定摘要內(nèi)容
- input_encoding:用于指定摘要內(nèi)容所需使用的編碼格式捂敌,可指定參數(shù)值為“utf8”艾扮、“ascii”或“binary”。如果不使用input_encoding參數(shù)占婉,則data參數(shù)值必須為一個(gè)Buffer對(duì)象泡嘴。可以在摘要被輸出前使用多次update方法來(lái)添加摘要內(nèi)容逆济。
#### 輸出摘要內(nèi)容
可以使用hash對(duì)象的digest方法來(lái)輸出摘要內(nèi)容酌予。在使用了hash對(duì)象的digest方法后,不能再向hash對(duì)象中追加摘要內(nèi)容奖慌。
```
hash.digest([encoding])
```
在hash對(duì)象的digest方法中抛虫,使用一個(gè)可選參數(shù),參數(shù)值為一個(gè)字符串简僧,用于指定輸出摘要的編碼格式建椰,可指定參數(shù)值為“hex”、“binary”及“base64”岛马。如果使用了該參數(shù)棉姐,那么digest方法返回字符串格式的摘要內(nèi)容屠列,如果不使用該參數(shù),那么digest方法返回一個(gè)Buffer對(duì)象伞矩。在hash對(duì)象的digest方法被調(diào)用之后笛洛,該對(duì)象不能再被使用。
#### 散列算法完整使用示例
```
var crypto = require('crypto');
var fs = require('fs');
var shasum = crypto.createHash('sha1');
var s = fs.ReadStream('./app.js');
s.on('data', function(d) {
? ? shasum.update(d);
});
s.on('end', function() {
? ? var d = shasum.digest('hex');
? ? console.log(d);
});
```
### HMAC算法
HMAC算法將散列算法與一個(gè)密鑰結(jié)合在一起扭吁,以阻止對(duì)簽名完整性的破壞撞蜂。在Node.js中,為了使用HMAC算法侥袜,首先應(yīng)該使用createHmac方法創(chuàng)建一個(gè)hmac對(duì)象蝌诡。
```
crypto.createHmac(algorithm,key)
```
- algorithm:為一個(gè)在Node.js中可以使用的算法,例如'sha1'枫吧、'md5'浦旱、'sha256'、'sha512'和'ripemd160'等九杂,用于指定我們所需要使用的散列算法颁湖。該方法返回被創(chuàng)建的hmac對(duì)象。
- key:參數(shù)值為一個(gè)字符串例隆,用于指定一個(gè)PEM格式的密鑰甥捺。
#### 創(chuàng)建一個(gè)摘要
在hmac對(duì)象的update方法中,使用一個(gè)參數(shù)镀层,其參數(shù)值為一個(gè)Buffer對(duì)象或一個(gè)字符串镰禾,用于指定摘要內(nèi)容〕辏可以在摘要被輸出前使用多次update方法來(lái)添加摘要內(nèi)容吴侦。
```
hmac.update(data)
```
#### 輸出摘要
可以使用hmac對(duì)象的digest方法輸出摘要內(nèi)容。在使用了hmac對(duì)象的digest方法后坞古,不能再向hmac對(duì)象中追加摘要內(nèi)容备韧。
```
hmac.digest([encoding])
```
#### HMAC算法的使用示例
```
var crypto = require('crypto');
var fs = require('fs');
var pem = fs.readFileSync('key.pem');
var key = pem.toString('ascii');
var shasum = crypto.createHmac('sha1',key);
var s = fs.ReadStream('./app.js');
s.on('data', function(d) {
? ? shasum.update(d);
});
s.on('end', function() {
? ? var d = shasum.digest('hex');
? ? console.log(d);
});
```
### 公鑰加密
#### 加密數(shù)據(jù)
在crypto模塊中,Cipher類用于對(duì)數(shù)據(jù)進(jìn)行加密操作痪枫。在加密數(shù)據(jù)之前织堂,首先需要?jiǎng)?chuàng)建一個(gè)cipher對(duì)象√拢可以通過(guò)如下所示的兩種方法創(chuàng)建cipher對(duì)象捧挺。
1.createCipher方法:該方法使用指定的算法與密碼來(lái)創(chuàng)建cipher對(duì)象。
```
crypto.createCipher(algorithm,password)
```
- algorithm:用于指定在加密數(shù)據(jù)時(shí)所使用的算法尿瞭,例如“blowfish'”闽烙、“aes-256-cbc”等。
- password:用于指定加密時(shí)所使用的密碼,參數(shù)值必須為一個(gè)二進(jìn)制格式的字符串或一個(gè)Buffer對(duì)象黑竞。
2.createCipheriv方法:該方法使用指定的算法捕发、密碼與初始向量(Initialization Vector,IV)來(lái)創(chuàng)建cipher對(duì)象很魂。該方法的使用方式如下:
```
crypto.createCipheriv(algorithm,password,iv)
```
- algorithm:用于指定在加密數(shù)據(jù)時(shí)所使用的算法扎酷,例如“blowfish'”、“aes-256-cbc”等遏匆。
- password:用于指定加密時(shí)所使用的密碼法挨,參數(shù)值必須為一個(gè)二進(jìn)制格式的字符串或一個(gè)Buffer對(duì)象。
- iv:用于指定加密時(shí)所使用的初始向量幅聘,參數(shù)值必須為一個(gè)二進(jìn)制格式的字符串或一個(gè)Buffer對(duì)象凡纳。
#### 指定需要被加密的數(shù)據(jù)。
在創(chuàng)建了一個(gè)cipher對(duì)象后帝蒿,可以通過(guò)使用該對(duì)象的update方法來(lái)指定需要被加密的數(shù)據(jù)荐糜。
```
cipher.update(data,[input_encoding],[output_encoding])
```
- data:為必須使用的參數(shù),為一個(gè)Buffer對(duì)象或一個(gè)字符串葛超,用于指定需要加密的數(shù)據(jù)
- input_encoding:用于指定被加密的數(shù)據(jù)所需使用的編碼格式暴氏,可指定參數(shù)值為“utf8”、“ascii”及“binary”绣张。
- output_encoding:用于指定輸出加密數(shù)據(jù)時(shí)使用的編碼格式答渔,可指定參數(shù)值為“hex”、“binary”或“base64”侥涵。
#### 返回加密數(shù)據(jù)研儒。
可以使用cipher對(duì)象的final方法來(lái)返回加密數(shù)據(jù)。當(dāng)該方法被調(diào)用時(shí)独令,任何cipher對(duì)象中所緩存的數(shù)據(jù)都將被加密,如果加密數(shù)據(jù)的字節(jié)數(shù)不足以創(chuàng)建一個(gè)塊好芭,將使用PKCS填充方式來(lái)填充這個(gè)塊燃箭。在使用了cipher對(duì)象的final方法后,不能再向cipher對(duì)象中追加加密數(shù)據(jù)舍败。
```
cipher.final([output_encoding])
```
- output_encoding:參數(shù)值為一個(gè)字符串招狸,用于指定在輸出加密數(shù)據(jù)的編碼格式,可指定參數(shù)值為“hex”邻薯、“binary”及“base64”裙戏。如果使用了該參數(shù),那么final方法返回字符串格式的加密數(shù)據(jù)厕诡,如果不使用該參數(shù)累榜,那么final方法返回一個(gè)Buffer對(duì)象。當(dāng)cipher對(duì)象的final方法被調(diào)用之后,該對(duì)象不能再被使用壹罚。
#### 使用cipher對(duì)象加密數(shù)據(jù)
```
var crypto = require('crypto');
var fs = require('fs');
var pem = fs.readFileSync('key.pem');
var key = pem.toString('ascii');
var cipher = crypto.createCipher('blowfish', key);
var text = "test";
cipher.update(text,'binary','hex');
var crypted=cipher.final('hex')
console.log(crypted);
```
### 解密數(shù)據(jù)
在crypto模塊中葛作,Decipher類用于對(duì)加密后的數(shù)據(jù)進(jìn)行解密操作。在解密數(shù)據(jù)之前猖凛,首先需要?jiǎng)?chuàng)建一個(gè)decipher對(duì)象赂蠢。可以通過(guò)如下所示的兩種方法創(chuàng)建decipher對(duì)象辨泳。
1.createDecipher方法:該方法使用指定的算法與密碼來(lái)創(chuàng)建decipher對(duì)象虱岂。
```
crypto.createDecipher(algorithm,password)
```
- algorithm:用于指定在解密數(shù)據(jù)時(shí)所使用的算法,例如“blowfish”菠红、“aes-256-cbc”等第岖,該算法必須與加密該數(shù)據(jù)時(shí)所使用的算法保持一致。
- password:用于指定解密時(shí)所使用的密碼途乃,其參數(shù)值必須為一個(gè)二進(jìn)制格式的字符串或一個(gè)Buffer對(duì)象绍傲,該密碼必須與加
密該數(shù)據(jù)時(shí)所使用的密碼保持一致。
2.createDecipheriv方法:該方法使用指定的算法耍共、密碼與初始向量來(lái)創(chuàng)建decipher對(duì)象烫饼。
```
crypto.createDecipheriv(algorithm,password,iv)
```
- algorithm:用于指定在解密數(shù)據(jù)時(shí)所使用的算法,例如“blowfish”试读、“aes-256-cbc”等杠纵,該算法必須與加密該數(shù)據(jù)時(shí)所使用的算法保持一致。
- password:用于指定解密時(shí)所使用的密碼钩骇,其參數(shù)值必須為一個(gè)二進(jìn)制格式的字符串或一個(gè)Buffer對(duì)象比藻,該密碼必須與加
密該數(shù)據(jù)時(shí)所使用的密碼保持一致。
- iv:用于指定解密時(shí)所使用的初始向量倘屹,參數(shù)值必須為一個(gè)二進(jìn)制格式的字符串或一個(gè)Buffer對(duì)象银亲,該初始向量必須與加密該數(shù)據(jù)時(shí)所使用的初始向量保持一致。
createDecipheriv方法返回一個(gè)被創(chuàng)建的decipher對(duì)象纽匙。
#### 數(shù)據(jù)解密
在創(chuàng)建了一個(gè)decipher對(duì)象之后务蝠,可以通過(guò)使用該對(duì)象的update方法來(lái)指定需要被解密的數(shù)據(jù)。
```
decipher.update(data,[input_encoding],[output_encoding])
```
#### 返回經(jīng)過(guò)解密之后的原始數(shù)據(jù)
```
decipher.final([output_encoding])
```
### 創(chuàng)建簽名
在網(wǎng)絡(luò)中烛缔,私鑰的擁有者可以在一段數(shù)據(jù)被發(fā)送之前先對(duì)該數(shù)據(jù)進(jìn)行簽名操作馏段,在簽名的過(guò)程中,將對(duì)這段數(shù)據(jù)執(zhí)行加密處理践瓷。在經(jīng)過(guò)加密后的數(shù)據(jù)發(fā)送之后院喜,數(shù)據(jù)的接收者可以通過(guò)公鑰的使用來(lái)對(duì)該簽名進(jìn)行解密及驗(yàn)證操作,以確保這段數(shù)據(jù)是私鑰的擁有者所發(fā)出的原始數(shù)據(jù)晕翠,且在網(wǎng)絡(luò)的傳輸過(guò)程中未被修改喷舀。
在Node.js中,在進(jìn)行簽名操作之前,首先需要使用createSign方法創(chuàng)建一個(gè)sign對(duì)象
```
crypto.createSign(algorithm)
```
- algorithm:指定加密算法
createSign方法返回被創(chuàng)建的sign對(duì)象元咙。
#### 指定加密數(shù)據(jù)
在創(chuàng)建了一個(gè)sign對(duì)象后梯影,可以通過(guò)使用該對(duì)象的update方法來(lái)指定需要被加密的數(shù)據(jù)。
```
sign.update(data)
```
在sign對(duì)象的update方法中庶香,使用一個(gè)參數(shù)甲棍,其參數(shù)值為一個(gè)Buffer對(duì)象或一個(gè)字符串,用于指定需要被加密的數(shù)據(jù)赶掖「忻停可以在對(duì)數(shù)據(jù)進(jìn)行簽名前使用多次update方法來(lái)添加數(shù)據(jù)。
#### 對(duì)數(shù)據(jù)進(jìn)行簽名
可以使用sign對(duì)象的sign方法對(duì)數(shù)據(jù)進(jìn)行簽名奢赂。在使用了sign對(duì)象的sign方法之后陪白,不能再使用sign對(duì)象的update方法追加數(shù)據(jù)。
```
sign.sign(private_key,[output_format])
```
- private_key:為一個(gè)字符串膳灶,用于指定PEM格式的私鑰咱士。
- output_format:用于指定簽名輸出時(shí)所使用的編碼格式,可指定參數(shù)值為“hex”轧钓、“binary”或“base64”序厉。
### 簽名驗(yàn)證
在crypto模塊中,Verify類用于對(duì)簽名進(jìn)行驗(yàn)證操作毕箍。在對(duì)簽名進(jìn)行驗(yàn)證之前弛房,首先需要?jiǎng)?chuàng)建一個(gè)verify對(duì)象,可以通過(guò)createVerify方法創(chuàng)建verify對(duì)象
```
crypto.createVerify(algorithm)
```
- algorithm:用于指定在驗(yàn)證簽名數(shù)據(jù)時(shí)所使用的算法
createVerify方法返回一個(gè)被創(chuàng)建的verify對(duì)象而柑。
#### 指定需要被驗(yàn)證的數(shù)據(jù)
```
verify.update(data)
```
可以使用verify對(duì)象的verify方法來(lái)對(duì)簽名進(jìn)行驗(yàn)證文捶。
```
verify.verify(object,signature,[signature_format])
```
- object:用于指定驗(yàn)證時(shí)所使用的對(duì)象,參數(shù)值為一個(gè)字符串媒咳,該字符串值可以為一個(gè)RSA公鑰粹排、一個(gè)DSA公鑰或一個(gè)X.509證書(shū)。
- signature:必須為sign對(duì)象涩澡,用于指定被驗(yàn)證的簽名恨搓。
- signature_format:用于指定在生成該簽名時(shí)所使用的編碼格式,可指定參數(shù)值為“hex”筏养、“binary”及“base64”。
#### 使用verify對(duì)象對(duì)簽名進(jìn)行驗(yàn)證
```
var crypto = require('crypto');
var fs = require('fs');
var privatePem = fs.readFileSync('key.pem');
var publicPem = fs.readFileSync('cert.pem');
var key = privatePem.toString();
var pubkey = publicPem.toString();
var data = "test"
var sign = crypto.createSign('RSA-SHA256');
sign.update(data);
var sig = sign.sign(key, 'hex');
var verify = crypto.createVerify('RSA-SHA256');
verify.update(data);
console.log(verify.verify(pubkey, sig, 'hex'));
```
### 壓縮與解壓縮處理
在Node.js中常拓,可以使用zlib模塊進(jìn)行壓縮及解壓縮處理渐溶,在該模塊內(nèi)部使用zlib類庫(kù)實(shí)現(xiàn)這些處理。具體不做描述弄抬,可見(jiàn)node官方文檔