nodeJS之crypto模块md5和Hmac加密

原文地址:https://www.cnblogs.com/tugenhua0707/p/9128690.html

在nodejs中,可以使用crypto模块来实现各种不同的加密与解密处理,在crypto模块中包含了类似MD5或SHA-1这些散列算法,我们可以通过crypto模块来实现HMAC运算。
什么是HMAC运算?
HMAC的中文意思是:散列运算消息认证码;运算使用散列算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。HMAC运算可以用来验证两段数据是否匹配,以确认该数据没有被篡改。

在crypto模块中,为每一种加密算法定义了一个类。可以使用getCiphers方法来查看nodejs中能够使用的所有加密算法。该方法返回一个数组,包括了nodejS中能够使用的所有散列算法。使用方法如下所示:

const crypto = require('crypto');
console.log(crypto.getCiphers());
/*
输出如下
[ '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对象。使用方法如下:

crypto.createHash(params);

在如上方法中,需要使用一个参数,其参数值为一个在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值很容易。
3. 抗修改性:对原数据进行任何改动,哪怕只修改一个字节,所得到的MD5值都有很大的区别。
4. 强抗碰撞:已知原数据和其MD5值,想找到一个具有相同的MD5值的伪数据是非常困难的。

MD5的作用是让大容量信息在用数字签名软件签署私人秘钥前被压缩成一种保密的格式(就是把任意长度的字符串变换成一定长的十六进制数字串)。

如下使用代码:

const crypto = require('crypto');

const str = 'abc';

// 创建一个hash对象
const md5 = crypto.createHash('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 = crypto.createHash('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 = crypto.createHash('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 = crypto.createHash('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对象,创建方法如下所示:

crypto.createHmac(params, key);

该方法中使用两个参数,第一个参数含义是在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 = crypto.createHmac('md5', 'abc'); // 往hmac对象中添加摘要内容
const up = hmac.update('123456'); // 使用 digest 方法输出摘要内容 const result = up.digest('hex'); console.log(result); // 8c7498982f41b93eb0ce8216b48ba21d

nodeJS之crypto模块md5和Hmac加密的更多相关文章

  1. nodeJS之crypto模块公钥加密及解密

    nodeJS之crypto模块公钥加密及解密 NodeJS有以下4个与公钥加密相关的类.1. Cipher: 用于加密数据:2. Decipher: 用于解密数据:3. Sign: 用于生成签名:4. ...

  2. BASE64,MD5,SHA,HMAC加密與解密算法(java)

    package com.ice.webos.util.security; import java.io.UnsupportedEncodingException; import java.math.B ...

  3. 使用nodeJS的 crypto模块来为你的密码hash加盐

    这篇文章将向你解释如何使用Node.js的Crypto模块对你的密码进行加盐hash.在这里,我们将不会对不懂的密码存储方式进行详细的比较.我们将要做的是知道在Node.js中使用加盐hash在进行密 ...

  4. 浅析nodeJS中的Crypto模块,包括hash算法,HMAC算法,加密算法知识,SSL协议

    node.js的crypto在0.8版本,这个模块的主要功能是加密解密. node利用 OpenSSL库(https://www.openssl.org/source/)来实现它的加密技术, 这是因为 ...

  5. 使用crypto模块实现md5加密功能(解决中文加密前后端不一致的问题)

    正常情况下使用md5加密 var crypto = require('crypto'); var md5Sign = function (data) { var md5 = crypto.create ...

  6. Nodejs进阶:MD5入门介绍及crypto模块的应用

    本文摘录自<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 简介 MD5(Message-Digest Algorithm) ...

  7. Nodejs:md5入门介绍及crypto模块的应用

    简介 MD5(Message-Digest Algorithm)是计算机安全领域广泛使用的散列函数(又称哈希算法.摘要算法),主要用来确保消息的完整和一致性.常见的应用场景有密码保护.下载文件校验等. ...

  8. nodeJS之crypto加密

    前面的话 加密模块提供了 HTTP 或 HTTPS 连接过程中封装安全凭证的方法.也提供了 OpenSSL 的哈希,hmac, 加密(cipher), 解密(decipher), 签名(sign) 和 ...

  9. Nodejs进阶:crypto模块中你需要掌握的安全基础

    本文摘录自<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址. 一. 文章概述 互联网时代,网络上的数据量每天都在以惊人的速度增长.同时,各类网络安全问题层出不穷.在信 ...

随机推荐

  1. Vue依赖收集引发的问题

    问题背景 在我们的项目中有一个可视化配置的模块,是通过go.js生成canvas来实现的.但是,我们发现这个模块在浏览器中经常会引起该tab页崩溃.开启chrome的任务管理器一看,进入该页面内存和c ...

  2. leetcode — path-sum

    /** * Source : https://oj.leetcode.com/problems/path-sum/ * * * Given a binary tree and a sum, deter ...

  3. 以语音评测的PC端demo代码为例,讲解口语评测如何实现

    本文由云+社区发表 作者:腾讯智慧教育 概述 腾讯云智聆口语评测(英文版)(Smart Oral Evaluation-English,SOE-E)是腾讯云推出的语音评测产品,是基于英语口语类教育培训 ...

  4. linux rsync 实际应用

    linux rsync 实际应用 一.rsync的概述 rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——remote sync.rsync是Linux系统下的文件同步和 ...

  5. 痞子衡嵌入式:常用的数据差错控制技术(1)- 重复校验(Repetition Code)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式里数据差错控制技术-重复校验. 在嵌入式应用里,除了最核心的数据处理外,我们还会经常和数据传输打交道.数据传输需要硬件传输接口的支持 ...

  6. GUID获取16位19位22位的唯一字符串

    /// <summary> /// 根据GUID获取16位的唯一字符串 /// </summary> /// <param name=\"guid\" ...

  7. mysql 的优化

    =>记录慢速查询 在一个 SQL 服务器中,数据表都是保存在磁盘上的.索引为服务器提供了一种在表中查找特定数据行的方法,而不用搜索整个表.当必须要搜索整个表时,就称为表扫描.通常 来说,您可能只 ...

  8. 驰骋工作流引擎JFlow与activiti的对比 -总结

    共同点: 1. 嵌入式的工作流引擎,降低集群复杂性. 2. 严格而灵活的流程版本控制 3. 支持多种数据库 4. 支持多种流程设计模式 5. 成熟度高的开源工作流,具有可靠的稳定性和性能. 区别: 1 ...

  9. .NET和Java之争

    这几天连续有多篇文章(详细文章列表在<.NET和Java之争一点随想>和<由优劣语言之争引起的思考>有写)诋毁.NET,这类文章我十几年前就看得多了,只不过十几年前是C和C++ ...

  10. [Android framework学习] ViewGroup的addView函数分析

    博客首页:http://www.cnblogs.com/kezhuang/p/ Android中整个的View的组装是采用组合模式. ViewGroup就相当与树根,各种Layout就相当于枝干,各种 ...