Node之加密与解密处理

### crypto模块概述

在Node.js中,使用OpenSSL类库作为其内部实现加密与解密处理的基础手段,这是因为目前OpenSSL已经成为了一个经过严格测试的可靠的加密与解密算法的实现工具。

在Node.js中,OpenSSL类库被封装在crypto模块中,因此开发者可以使用crypto模块来实现各种不同的加密与解密处理。例如,crypto模块中包含了类似MD5或SHA-1之类的散列算法。开发者也可以通过crypto模块来实现HMAC运算 [1]。在crypto模块中,提供了一些加密方法来实现数据的可靠加密。另外,在crypto模块中,也提供了一些利用HMAC运算来实现数字签名以及对数字签名进行验证的方

法。

### 查看Node.js中能够使用的所有加密算法

在crypto模块中,为每一种加密算法定义了一个类。可以使用getCiphers方法

来查看Node.js中能够使用的所有加密算法。

```

crypto.getCiphers()

```

### 查看Node.js中能够使用的所有散列算法

可以使用getHashes方法来查看在Node.js中能够使用的所有散列算法。

```

crypto.getHashes()

```

### 散列算法

散列(哈希)算法用来实现一些重要处理,例如,在允许对一段数据进行验证的前提下,将数据进行模糊化,或者为一大段数据提供一个验证码

在node中,为了使用散列算法,首先应该使用createHash方法创建一个hash对象。

```

let hash=crypto.createHash(algorithm)

```

- algorithm:参数值为一个在Node.js中可以使用的算法,如'sha1'、'md5'、'sha256'、'sha512'和'ripemd160'等,用于指定需要使用的散列算法,该方法返回被创建的hash对象

在创建一个hash对象后可以通过使用该对象的update方法创建一个摘要。该方法的使用方式如下所示

```

hash.update(data,[input_encoding])

```

- data:参数值为一个Buffer对象或一个字符串,用于指定摘要内容

- input_encoding:用于指定摘要内容所需使用的编码格式,可指定参数值为“utf8”、“ascii”或“binary”。如果不使用input_encoding参数,则data参数值必须为一个Buffer对象。可以在摘要被输出前使用多次update方法来添加摘要内容。

#### 输出摘要内容

可以使用hash对象的digest方法来输出摘要内容。在使用了hash对象的digest方法后,不能再向hash对象中追加摘要内容。

```

hash.digest([encoding])

```

在hash对象的digest方法中,使用一个可选参数,参数值为一个字符串,用于指定输出摘要的编码格式,可指定参数值为“hex”、“binary”及“base64”。如果使用了该参数,那么digest方法返回字符串格式的摘要内容,如果不使用该参数,那么digest方法返回一个Buffer对象。在hash对象的digest方法被调用之后,该对象不能再被使用。

#### 散列算法完整使用示例

```

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算法将散列算法与一个密钥结合在一起,以阻止对签名完整性的破坏。在Node.js中,为了使用HMAC算法,首先应该使用createHmac方法创建一个hmac对象。

```

crypto.createHmac(algorithm,key)

```

- algorithm:为一个在Node.js中可以使用的算法,例如'sha1'、'md5'、'sha256'、'sha512'和'ripemd160'等,用于指定我们所需要使用的散列算法。该方法返回被创建的hmac对象。

- key:参数值为一个字符串,用于指定一个PEM格式的密钥。

#### 创建一个摘要

在hmac对象的update方法中,使用一个参数,其参数值为一个Buffer对象或一个字符串,用于指定摘要内容。可以在摘要被输出前使用多次update方法来添加摘要内容。

```

hmac.update(data)

```

#### 输出摘要

可以使用hmac对象的digest方法输出摘要内容。在使用了hmac对象的digest方法后,不能再向hmac对象中追加摘要内容。

```

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);

});

```

### 公钥加密

#### 加密数据

在crypto模块中,Cipher类用于对数据进行加密操作。在加密数据之前,首先需要创建一个cipher对象。可以通过如下所示的两种方法创建cipher对象。

1.createCipher方法:该方法使用指定的算法与密码来创建cipher对象。

```

crypto.createCipher(algorithm,password)

```

- algorithm:用于指定在加密数据时所使用的算法,例如“blowfish'”、“aes-256-cbc”等。

- password:用于指定加密时所使用的密码,参数值必须为一个二进制格式的字符串或一个Buffer对象。

2.createCipheriv方法:该方法使用指定的算法、密码与初始向量(Initialization Vector,IV)来创建cipher对象。该方法的使用方式如下:

```

crypto.createCipheriv(algorithm,password,iv)

```

- algorithm:用于指定在加密数据时所使用的算法,例如“blowfish'”、“aes-256-cbc”等。

- password:用于指定加密时所使用的密码,参数值必须为一个二进制格式的字符串或一个Buffer对象。

- iv:用于指定加密时所使用的初始向量,参数值必须为一个二进制格式的字符串或一个Buffer对象。

#### 指定需要被加密的数据。

在创建了一个cipher对象后,可以通过使用该对象的update方法来指定需要被加密的数据。

```

cipher.update(data,[input_encoding],[output_encoding])

```

- data:为必须使用的参数,为一个Buffer对象或一个字符串,用于指定需要加密的数据

- input_encoding:用于指定被加密的数据所需使用的编码格式,可指定参数值为“utf8”、“ascii”及“binary”。

- output_encoding:用于指定输出加密数据时使用的编码格式,可指定参数值为“hex”、“binary”或“base64”。

#### 返回加密数据。

可以使用cipher对象的final方法来返回加密数据。当该方法被调用时,任何cipher对象中所缓存的数据都将被加密,如果加密数据的字节数不足以创建一个块,将使用PKCS填充方式来填充这个块。在使用了cipher对象的final方法后,不能再向cipher对象中追加加密数据。

```

cipher.final([output_encoding])

```

- output_encoding:参数值为一个字符串,用于指定在输出加密数据的编码格式,可指定参数值为“hex”、“binary”及“base64”。如果使用了该参数,那么final方法返回字符串格式的加密数据,如果不使用该参数,那么final方法返回一个Buffer对象。当cipher对象的final方法被调用之后,该对象不能再被使用。

#### 使用cipher对象加密数据

```

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);

```

### 解密数据

在crypto模块中,Decipher类用于对加密后的数据进行解密操作。在解密数据之前,首先需要创建一个decipher对象。可以通过如下所示的两种方法创建decipher对象。

1.createDecipher方法:该方法使用指定的算法与密码来创建decipher对象。

```

crypto.createDecipher(algorithm,password)

```

- algorithm:用于指定在解密数据时所使用的算法,例如“blowfish”、“aes-256-cbc”等,该算法必须与加密该数据时所使用的算法保持一致。

- password:用于指定解密时所使用的密码,其参数值必须为一个二进制格式的字符串或一个Buffer对象,该密码必须与加

密该数据时所使用的密码保持一致。

2.createDecipheriv方法:该方法使用指定的算法、密码与初始向量来创建decipher对象。

```

crypto.createDecipheriv(algorithm,password,iv)

```

- algorithm:用于指定在解密数据时所使用的算法,例如“blowfish”、“aes-256-cbc”等,该算法必须与加密该数据时所使用的算法保持一致。

- password:用于指定解密时所使用的密码,其参数值必须为一个二进制格式的字符串或一个Buffer对象,该密码必须与加

密该数据时所使用的密码保持一致。

- iv:用于指定解密时所使用的初始向量,参数值必须为一个二进制格式的字符串或一个Buffer对象,该初始向量必须与加密该数据时所使用的初始向量保持一致。

createDecipheriv方法返回一个被创建的decipher对象。

#### 数据解密

在创建了一个decipher对象之后,可以通过使用该对象的update方法来指定需要被解密的数据。

```

decipher.update(data,[input_encoding],[output_encoding])

```

#### 返回经过解密之后的原始数据

```

decipher.final([output_encoding])

```

### 创建签名

在网络中,私钥的拥有者可以在一段数据被发送之前先对该数据进行签名操作,在签名的过程中,将对这段数据执行加密处理。在经过加密后的数据发送之后,数据的接收者可以通过公钥的使用来对该签名进行解密及验证操作,以确保这段数据是私钥的拥有者所发出的原始数据,且在网络的传输过程中未被修改。

在Node.js中,在进行签名操作之前,首先需要使用createSign方法创建一个sign对象

```

crypto.createSign(algorithm)

```

- algorithm:指定加密算法

createSign方法返回被创建的sign对象。

#### 指定加密数据

在创建了一个sign对象后,可以通过使用该对象的update方法来指定需要被加密的数据。

```

sign.update(data)

```

在sign对象的update方法中,使用一个参数,其参数值为一个Buffer对象或一个字符串,用于指定需要被加密的数据。可以在对数据进行签名前使用多次update方法来添加数据。

#### 对数据进行签名

可以使用sign对象的sign方法对数据进行签名。在使用了sign对象的sign方法之后,不能再使用sign对象的update方法追加数据。

```

sign.sign(private_key,[output_format])

```

- private_key:为一个字符串,用于指定PEM格式的私钥。

- output_format:用于指定签名输出时所使用的编码格式,可指定参数值为“hex”、“binary”或“base64”。

### 签名验证

在crypto模块中,Verify类用于对签名进行验证操作。在对签名进行验证之前,首先需要创建一个verify对象,可以通过createVerify方法创建verify对象

```

crypto.createVerify(algorithm)

```

- algorithm:用于指定在验证签名数据时所使用的算法

createVerify方法返回一个被创建的verify对象。

#### 指定需要被验证的数据

```

verify.update(data)

```

可以使用verify对象的verify方法来对签名进行验证。

```

verify.verify(object,signature,[signature_format])

```

- object:用于指定验证时所使用的对象,参数值为一个字符串,该字符串值可以为一个RSA公钥、一个DSA公钥或一个X.509证书。

- signature:必须为sign对象,用于指定被验证的签名。

- signature_format:用于指定在生成该签名时所使用的编码格式,可指定参数值为“hex”、“binary”及“base64”。

#### 使用verify对象对签名进行验证

```

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模块进行压缩及解压缩处理,在该模块内部使用zlib类库实现这些处理。具体不做描述,可见node官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 在最近的每日读诗中很喜欢这首: 生活 - 萨罗基妮·奈杜 孩子,你还没体验过人生,尽管它看起来 是梦中可爱的钟乳石...
    回归自己的成长阅读 107评论 0 1
  • “你知道我为什么坚持跑步吗?因为我希望到结婚那天能有一个很好的身材,在场所有的女宾都羡慕你”
    Kukuxixi阅读 166评论 0 0
  • 在硬笔书法爱好者中,流传着一本"武功秘籍",虽只是一九八六年《中国钢笔书法》杂志的增刊,却被太多人收藏。 ...
    自在天狐阅读 481评论 0 4
  • 宋子韵听完也很无奈,她看着炽游,没有说话,二人又相互天谈了些,睡了,最后的一个安稳的睡眠了。 第二日,宋府张灯...
    Satan小单阅读 331评论 1 1
  • 道教有一部专门劝人行善积阴德的典籍,叫《文昌帝君阴骘文》,主要内容就是说只要你阴德积的厚,即使在独处而无人知晓时也...
    洼泥阅读 455评论 1 3