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. Python:游戏:测试打字速度

    现在写书的人真是一点责任心都没有,最近看了几本书,其中的代码都存在错误. 最近迷恋 Python 游戏,买了<Python游戏编程入门>[美] Jonathan S·Harbour 著 一 ...

  2. 【Vue】----- computed与watch的区别

    1.computed computed是一种计算属性,用来监听属性的变化: computed里面的方法调用的时候不需要加(),并且里面的方法必须要有一个返回值: computed里面的方法不是通过事件 ...

  3. springboot+mybatis+dubbo+aop日志终结篇

    之前的几篇文章把dubbo服务层都介绍完毕,本篇文章咱们主要写web层如何调用服务层的方法.文章底部附带源码. 启动服务 服务启动时,会向zk注册自己提供的服务,zk则会记录服务提供者的IP地址以及暴 ...

  4. Nacos系列:基于Nacos的注册中心

    前言 所谓注册中心,其实是分布式架构演进过程中的产物,在系统中充当一个协调者的角色.但是,为什么需要这样一个协调者的角色呢?我们先来看一个例子,以便理解为什么分布式架构中需要有注册中心. 案例 小明和 ...

  5. ruby中to_s和to_str、to_i和to_int、to_a和to_ary、to_h和to_hash的解释说明

    包括to_s和to_str.to_i和to_int.to_a和to_ary.to_h和to_hash.统称为to_x和to_xxx. 那么,to_x和to_xxx的区别是什么,什么时候使用to_x,什 ...

  6. 【记录一次坑经历】axios使用x-www-form-urlencoded 服务器报400(错误的请求。 )(后端.Net MVC5 WebApi OAuth,前端Electron-Vue)

    首先放上源码 electron-vue axios 注册 import Vue from 'vue' import axios from 'axios'   axios.defaults.baseUR ...

  7. sqlserver数据库发送邮箱

    Exec [msdb].dbo.sp_send_dbmail @profile_name='SQLMailConfig', @recipients = @email,    //需要发送的邮箱 @su ...

  8. 你必须知道的.net读书笔记第四回:后来居上:class和struct

     基本概念 1.1. 什么是class? class(类)是面向对象编程的基本概念,是一种自定义数据结构类型,通常包含字段.属性.方法.属性.构造函数.索引器.操作符等.因为是基本的概念,所以不必在此 ...

  9. Fundebug发布Vue插件,简化BUG监控接入代码

    摘要: 代码越短越好! 我们发布了fundebug-vue插件,可以简化Vue框架接入Fundebug的代码. Vue如何接入Fundebug 1. 安装fundebug-javascript与fun ...

  10. 流程控制值while 循环

    一.结束循环的两种方式 1. 修改条件tag=Truewhile tag: print(1) print(2) print(3) tag=False print(4) 2.while + break ...