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. Java基础8:深入理解内部类

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  2. 补习系列(8)-springboot 单元测试之道

    目录 目标 一.About 单元测试 二.About Junit 三.SpringBoot-单元测试 项目依赖 测试样例 四.Mock测试 五.最后 目标 了解 单元测试的背景 了解如何 利用 spr ...

  3. Linux基础知识第二讲,文件目录命令使用

    目录 一丶Linux终端使用技巧. 1.自动补全 Tab技巧. 2.使用输入过的命令 二丶Linux 目录知识 1.linux目录的特点 2.ls 隐藏文件的查看 3.ls 常用选项 4.通配符的配合 ...

  4. JDK源码分析(3)之 ArrayList 相关

    ArrayList的源码其实比较简单,所以我并没有跟着源码对照翻译,文本只是抽取了一些我觉得有意思或一些有疑惑的地方分析的. 一.成员变量 private static final int DEFAU ...

  5. Docker系列07—Dockerfile 详解

    本文收录在容器技术学习系列文章总目录 1.认识Dockerfile 1.1 镜像的生成途径 基于容器制作  dockerfile,docker build 基于容器制作镜像,已经在上篇Docker系列 ...

  6. 【转】Android开发笔记(序)写在前面的目录

    原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...

  7. 2019年10个最受欢迎的JavaScript动画库!

    摘要: 非常炫酷的动画库! 原文:值得看看,2019 年 11 个受欢迎的 JavaScript 动画库! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 1. Three.js 超过 ...

  8. HTML中特殊符号

  9. CSS实现单行、多行文本超出部分显示省略号

     单行文本超出,代码如下: css代码: <style> .one{ width:200px; overflow: hidden; text-overflow:ellipsis; whit ...

  10. markdown写作方法规范参考汇总

    目录 markdown写作方法 markdown规范 补 本文转载自:https://blog.csdn.net/xiaogeldx/article/details/89208074 本文总结了自己的 ...