nodeJS之crypto模块md5和Hmac加密
nodeJS之crypto模块md5和Hmac加密
在nodejs中,可以使⽤crypto模块来实现各种不同的加密与解密处理,在crypto模块中包含了类似MD5或SHA-1这些散列算法,我们可以通过crypto模块来实现HMAC运算。
什么是HMAC运算?
HMAC的中⽂意思是:散列运算消息认证码;运算使⽤散列算法,以⼀个密钥和⼀个消息为输⼊,⽣成⼀个消息摘要作为输出。HMAC运算可以⽤来验证两段数据是否匹配,以确认该数据没有被篡改。
在crypto模块中,为每⼀种加密算法定义了⼀个类。可以使⽤getCiphers⽅法来查看nodejs中能够使⽤的所有加密算法。该⽅法返回⼀个数组,包括了nodejS中能够使⽤的所有散列算法。使⽤⽅法如下所⽰:
const crypto = require('crypto');
console.Ciphers());
/*
输出如下
[ 'aes-128-cbc',
'aes-128-cbc-hmac-sha1',
'aes-128-cbc-hmac-sha256',
'aes-128-ccm',
'aes-128-cfb',
'aes-128-cfb1',
'aes-128-cfb8',
'aes-128-ctr',
'aes-128-ecb',
'aes-128-gcm',
'aes-128-ofb',
'aes-128-xts',
'aes-192-cbc',
'aes-192-ccm',
'aes-192-cfb',
'aes-192-cfb1',
'aes-192-cfb8',
'aes-192-ctr',
'aes-192-ecb',
'aes-192-gcm',
'aes-192-ofb',
'aes-256-cbc',
'aes-256-cbc-hmac-sha1',
'aes-256-cbc-hmac-sha256',
'aes-256-ccm',
'aes-256-cfb',
'aes-256-cfb1',
'aes-256-cfb8',
'aes-256-ctr',
'aes-256-ecb',
'aes-256-gcm',
'aes-256-ofb',
'aes-256-xts',
'aes128',
'aes192',
'aes256',
'bf',
'bf-cbc',
'bf-cfb',
'bf-ecb',
'bf-ofb',
'blowfish',
'camellia-128-cbc',
'camellia-128-cfb',
'camellia-128-cfb1',
'camellia-128-cfb8',
'camellia-128-ecb',
'camellia-128-ofb',
'camellia-192-cbc',
'camellia-192-cfb',
'camellia-192-cfb1',
'camellia-192-cfb8',
'camellia-192-ecb',
'camellia-192-ofb',
'camellia-256-cbc',
'camellia-256-cfb',
'camellia-256-cfb1',
'camellia-256-cfb8',
'camellia-256-ecb',
'camellia-256-ofb',
'camellia128',
'camellia192',
'camellia256',
'cast',
'cast-cbc',
'cast5-cbc',
'cast5-cfb',
'cast5-ecb',
'cast5-ofb',
'des',
'des-cbc',
'des-cfb',
'des-cfb1',
'des-cfb8',
'des-ecb',
'des-ede',
'des-ede-cbc',
'des-ede-cfb',
'des-ede-ofb',
'des-ede3',
'des-ede3-cbc',
'des-ede3-cfb',
'des-ede3-cfb1',
'des-ede3-cfb8',
'des-ede3-ofb',
'des-ofb',
'des3',
'desx',
'desx-cbc',
'id-aes128-CCM',
'id-aes128-GCM',
'id-aes128-wrap',
'id-aes192-CCM',
'id-aes192-GCM',
'id-aes192-wrap',
'id-aes256-CCM',
'id-aes256-GCM',
'id-aes256-wrap',
'id-smime-alg-CMS3DESwrap',
'idea',
... 19 more items ]
*/
⼀:散列算法
散列(也可以叫哈希)算法,它是⽤来对⼀段数据进⾏验证前,将该数据模糊化,或者也可以为⼀⼤段数据提供⼀个校验码。
在nodejs中,为了使⽤该散列算法,我们先要使⽤ createHash⽅法创建⼀个hash对象。使⽤⽅法如下:
在如上⽅法中,需要使⽤⼀个参数,其参数值为⼀个在Node.js中可以使⽤的算法,⽐如 'sha1', 'md5', 'sha512' 等等这样的,⽤于指定需要使⽤的散列算法,该⽅法返回被创建的hash对象。
在创建完hash对象后,可以通过使⽤该对象的update⽅法创建⼀个摘要。该⽅法的使⽤⽅式如下:
hash.update(data, [encoding]);
在如上⾯的⽅法,该⽅法需要使⽤两个参数,第⼀个参数是必选项,该参数值是⼀个Buffer对象或⼀个字符串,⽤于指定摘要内容;第⼆个参数 encoding⽤于指定摘要内容所需使⽤的编码格式,可以指定为 'utf-8', 'ascii', 或 'binary'. 如果不使⽤第⼆个参数,则第⼀个参数data参数值必须为⼀个Buffer对象,我们也可以在摘要被输出前使⽤多次updata⽅法来添加摘要内容。
在第⼀步创建了⼀个hash对象后,第⼆步就是添加摘要内容,那么第三步我们就是使⽤hash对象的digest⽅法来输出摘要内容了;在使⽤hash对象的digest
⽅法后,不能再向hash对象中追加摘要内容,也就是说你使⽤了digest⽅法作为输出后,你再追加内容也不会执⾏,因此是不能向hash对象中追加内容。
使⽤⽅法如下:
hash.digest([encoding]);
该⽅法有⼀个参数,该参数是⼀个可选值,表⽰的意思是⽤于指定输出摘要的编码格式,可指定参数
值为 'hex', 'binary', 及 'base64'.如果使⽤了该参数,那么digest⽅法返回字符串格式的摘要内容,如果不使⽤该参数,那么digest⽅法返回⼀个是Buffer对象。
⼆:MD5算法
MD5是计算机领域使⽤最⼴泛的散列函数(可以叫哈希算法、摘要算法),注意是⽤来确保消息的完整和⼀致性。
下⾯我们最主要是以 md5 加密为例来了解下加密算法。
MD5算法有以下特点:
1. 压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2. 容易计算:从原数据算出MD5值很容易。js代码加密软件
3. 抗修改性:对原数据进⾏任何改动,哪怕只修改⼀个字节,所得到的MD5值都有很⼤的区别。
4. 强抗碰撞:已知原数据和其MD5值,想到⼀个具有相同的MD5值的伪数据是⾮常困难的。
MD5的作⽤是让⼤容量信息在⽤数字签名软件签署私⼈秘钥前被压缩成⼀种保密的格式(就是把任意长
度的字符串变换成⼀定长的⼗六进制数字串)。
如下使⽤代码:
const crypto = require('crypto');
const str = 'abc';
// 创建⼀个hash对象
const md5 = ateHash('md5');
// 往hash对象中添加摘要内容
md5.update(str);
// 使⽤ digest ⽅法输出摘要内容,不使⽤编码格式的参数其输出的是⼀个Buffer对象
// console.log(md5.digest());
// 输出 <Buffer 90 01 50 98 3c d2 4f b0 d6 96 3f 7d 28 e1 7f 72>
/
/ 使⽤编码格式的参数,输出的是⼀个字符串格式的摘要内容
console.log(md5.digest('hex')); // 输出 900150983cd24fb0d6963f7d28e17f72
Md5算法demo实列:
现在我们来看下⼀个demo,⽐如⼀些登录信息,⽐如密码直接以明⽂的⽅式存放在数据库中是不安全的,开发⼈员直接可以通过⾁眼就可以知道,可以记下来,因此我们需要使⽤md5来加密⼀下;因此我们可以做如下代码加密:
const crypto = require('crypto');
var cryptoPassFunc = function(password) {
const md5 = ateHash('md5');
return md5.update(password).digest('hex');
};
const password = '123456';
const croptyPass = cryptoPassFunc(password);
const croptyPass2 = cryptoPassFunc(password);
console.log(croptyPass); // e10adc3949ba59abbe56e057f20f883e
console.log(croptyPass2); // e10adc3949ba59abbe56e057f20f883e
如上console.log输出的是通过md5加密后代码了;
只对md5加密的缺点:
通过上⾯对md5加密后确实⽐明⽂好很多,⾄少很多⼈直接使⽤⾁眼看到的并记不住,也不知道密码多少,但是只对md5加密也存在缺点,如上代码使⽤console.log打印两次后,加密后的代码是⼀样,也就是说相同的明⽂密码,加密后,输出两次,md5的值也是⼀样的。所以这样也是不安全的。
密码加盐:
什么意思呢?就是在密码的特定位置上插⼊特定的字符串后,再对修改后的字符串进⾏md5加密,这样做的好处是每次调⽤代码的时候,插⼊的字符串不⼀样,会导致最后的md5值会不⼀样的。代码如下:
const crypto = require('crypto');
var saltPasswordFunc = function(password, salt) {
// 密码加盐
const saltPassword = password + ':' + salt;
console.log('原始密码:%s', password);
console.log('加盐后的密码:%s', saltPassword);
const md5 = ateHash('md5');
const result = md5.update(saltPassword).digest('hex');
console.log('加盐密码后的md5的值为:%s', result);
};
const password = '123456';
saltPasswordFunc(password, 'abc');
/*
输出结果为:
原始密码:123456
加盐后的密码:123456:abc
加盐密码后的md5的值为:51011af1892f59e74baf61f3d4389092
*/
saltPasswordFunc(password, 'def');
/*
输出结果为:
原始密码:123456
加盐后的密码:123456:def
加盐密码后的md5的值为:5091d17d6b08ba9a95ccef51f598b249
*/
密码加密:随机盐值
如上通过密码加盐,⽐单单的使⽤md5加密,安全性相对来说更⾼点,但是也存在问题,⽐如字符串拼接算法中的字符串开发者知道的,第⼆个是盐值固定,也就是说拼接的字符串的盐值是固定的;所以存在这⼏个问题,因此下⾯我们需要⼀个随机数来⽣成随机盐值。这样安全性或许会更⾼点。
因此优化后的代码如下:(优化点⽆⾮就是⽣成⼀个随机数当做盐值)
const crypto = require('crypto');
var getRandomSalt = function() {
// 使⽤六位随机数吧
const randomSalt = Math.random().toString().slice(2, 8);
console.log(randomSalt);
return randomSalt;
};
var saltPasswordFunc = function(password, salt) {
// 密码加盐
const saltPassword = password + ':' + salt;
console.log('原始密码:%s', password);
console.log('加盐后的密码:%s', saltPassword);
const md5 = ateHash('md5');
const result = md5.update(saltPassword).digest('hex');
console.log('加盐密码后的md5的值为:%s', result);
};
const password = '123456';
saltPasswordFunc(password, getRandomSalt());
/*
输出结果为:
原始密码:123456
加盐后的密码:123456:随机⽣成6位数字
加盐密码后的md5的值为:密码+ ':' + 随机⽣成6位数字的md5值
*/
saltPasswordFunc(password, getRandomSalt());
/*
输出结果为:
原始密码:123456
加盐后的密码:123456:随机⽣成6位数字
加盐密码后的md5的值为:密码+ ':' + 随机⽣成6位数字的md5值
*/
这样做的好处是:每次运⾏的时候,或者说叫请求的时候,盐值是不⼀样的,导致每次⽣成的md5加密后的密码是不⼀样的。
三:HMAC算法
HMAC算法是将散列算法与⼀个密钥结合在⼀起,以阻⽌对签名完整性破坏,其实就是类似于上⾯的提到的md5密码中加盐道理是类似的。使⽤HMAC算法前,我们使⽤createHmac⽅法创建⼀个hmac对象,创建⽅法如下所⽰:
该⽅法中使⽤两个参数,第⼀个参数含义是在Node.js中使⽤的算法,⽐如'sha1', 'md5', 'sha256', 'sha512'等等,该⽅法返回的是hmac对象。
key参数值为⼀个字符串,⽤于指定⼀个PEM格式的密钥。
在创建完成hmac对象后,我们也是⼀样使⽤⼀个update⽅法来创建⼀个摘要,该⽅法使⽤如下所⽰:
hmac.update(data);
在update⽅法中,使⽤⼀个参数,其参数值为⼀个Buffer对象或⼀个字符串,⽤于指定摘要内容。也是⼀样可以在被输出之前使⽤多次update⽅法来添加摘要内容。
最后⼀步就是使⽤hmac对象的digest⽅法来输出摘要内容了;在使⽤hmac对象的digest⽅法后,不能再向hmac对象中追加摘要内容,也就是说你使⽤了digest⽅法作为输出后,因此是不能向hmac对象中追加内容。使⽤⽅法如下:
hmac.digest([encoding]);
该⽅法有⼀个参数,该参数是⼀个可选值,表⽰的意思是⽤于指定输出摘要的编码格式,可指定参数值为 'hex', 'binary', 及 'base64'.如果使⽤了该参数,那么digest⽅法返回字符串格式的摘要内容,如果不使⽤该参数,那么digest⽅法返回⼀个是Buffer对象。
如下使⽤⼀个简单的demo
const crypto = require('crypto');
// 创建⼀个hmac对象
const hmac = ateHmac('md5', 'abc');
// 往hmac对象中添加摘要内容
const up = hmac.update('123456');
// 使⽤ digest ⽅法输出摘要内容
const result = up.digest('hex');
console.log(result); // 8c7498982f41b93eb0ce8216b48ba21d
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论