记一次在node.js中使用crypto的createCipheriv方法进行加密时所遇到的坑

  Node.js的crypto模块提供了一组包括对OpenSSL的哈希、HMAC、加密、解密、签名,以及验证等一整套功能的封装。具体的使用方法可以参考这篇文章中的描述:node.js_crypto模块

  本文重点介绍在使用createCipheriv方法时所遇到的坑。对应的解密算法createDecipheriv应该是一样的问题。

  按照文档中的描述,createCipheriv方法接受三个参数:algorithm用于指定加密算法,如aes-128-ecb、aes-128-cbc等;key是用于加密的密钥;iv参数可选,用于指定加密时所用的向量。注意这里的密钥必须是8/16/32位,如果加密算法是128,则对应的密钥是16位,如果加密算法是256,则对应的密钥是32位。代码如下:

const crypto = require("crypto");

function encrypt (key, iv, data) {
    let decipher = crypto.createCipheriv(‘aes-128-cbc‘, key, iv);
    // decipher.setAutoPadding(true);
    return decipher.update(data, ‘binary‘, ‘base64‘) + decipher.final(‘base64‘);
}

function decrypt (key, iv, crypted) {
     crypted = new Buffer(crypted, ‘base64‘).toString(‘binary‘);
     let decipher = crypto.createDecipheriv(‘aes-128-cbc‘, key, iv);
     return decipher.update(crypted, ‘binary‘, ‘utf8‘) + decipher.final(‘utf8‘);
}

  下面是测试结果:

let key = ‘123456789abcdefg‘;
console.log(‘加密的key:‘, key);
let iv = ‘abcdefg123456789‘;
console.log(‘加密的iv:‘, iv);
let data = "This is an example";
console.log("需要加密的数据:", data);
let crypted = encrypt(key, iv, data);
console.log("数据加密后:", crypted);
let dec = decrypt(key, iv, crypted);
console.log("数据解密后:", dec);

  以上加密和解密的算法在node.js中运行没有问题。但如果服务端用的不是node.js,而是Java、C#或者C语言编写的服务,则用node.js加密之后的结果在服务端验证无法通过。究其原因可能是因为node.js在实现createCipheriv的算法上与其它语言有差异,而这个差异也可能体现在编码格式上。在上述node.js代码中,无论如何修改encrypt函数中update()和final()方法的参数,例如改为"utf8"、"hex",或者将传入的参数改为buffer等,虽然得出的加密结果会有区别,但是服务端验证都会失败。

  在多次尝试失败后,我们只能认定node.js中的crypto模块与其它语言中的实现存在差异。所以我们不得已选择其它的开源包来替换node.js中的crypto模块。经过尝试,aes-js包是个不错的选择。按照文档中的描述,我们将上面node.js中的encrypt函数修改为:

const aesjs = require(‘aes-js‘);

function encrypt (key, iv, data) {
    let aesCbc = new aesjs.ModeOfOperation.cbc(aesjs.utils.utf8.toBytes(key), aesjs.utils.utf8.toBytes(iv));
    let encryptedBytes = aesCbc.encrypt(aesjs.utils.utf8.toBytes(data));
    return aesjs.utils.hex.fromBytes(encryptedBytes);
}

function decrypt (key, iv, crypted) {
    let aesCbc = new aesjs.ModeOfOperation.cbc(aesjs.utils.utf8.toBytes(key), aesjs.utils.utf8.toBytes(iv));
    let encryptedBytes = aesCbc.decrypt(aesjs.utils.hex.toBytes(crypted));
    return aesjs.utils.utf8.fromBytes(encryptedBytes);
}

  上面这段代码要求加密的数据是16位,测试结果如下:

let key = ‘123456789abcdefg‘;
console.log(‘加密的key:‘, key);
let iv = ‘abcdefg123456789‘;
console.log(‘加密的iv:‘, iv);
let data = "Thisisanexample.";
console.log("需要加密的数据:", data);
let crypted = encrypt(key, iv, data);
console.log("数据加密后:", crypted);
let dec = decrypt(key, iv, crypted);
console.log("数据解密后:", dec);

  采用aes-js计算得到的加密结果可以通过服务端的验证。

原文地址:https://www.cnblogs.com/jaxu/p/11649131.html

时间: 2024-10-04 07:44:12

记一次在node.js中使用crypto的createCipheriv方法进行加密时所遇到的坑的相关文章

node.js中的http.response.end方法使用说明

转载自:http://m.jb51.net/article/58468.htm 本文介绍了http.response.end的方法说明.语法.接收参数.使用实例和实现源码,需要的朋友可以参考下 方法说明: 结束响应,告诉客户端所有消息已经发送.当所有要返回的内容发送完毕时,该函数必须被调用一次. 如何不调用该函数,客户端将永远处于等待状态. 语法: response.end([data], [encoding]) 接收参数: data : end()执行完毕后要输出的字符,如果指定了 data

笔记-Node.js中的核心API之HTTP

最近正在学习Node,在图书馆借了基本关于Node的书,同时在网上查阅资料,颇有收获,但是整体感觉对Node的理解还是停留在一个很模棱两可的状态.比如Node中的模块,平时练习就接触到那么几个,其他的一些模块暂时只会在学习的时候接触到,不常用便就荒废了.正所谓好记心不如烂笔头,多做笔记还是更有利于理解和记忆.自己做的总结也方便回头复习,所以决定踏上漫长的修炼之旅-- Node提供了许多API,其中一些比较重要.这些核心的API是所有Node应用的支柱,你会不停的用到他们. HTTP服务器 Nod

在Node.js中使用RabbitMQ系列二 任务队列

在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心解决的问题是避免立即处理那些耗时的任务,也就是避免请求-响应的这种同步模式.取而代之的是我们通过调度算法,让这些耗时的任务之后再执行,也就是采用异步的模式.我们需要将一条消息封装成一个任务,并且将它添加到任务队列里面.后台会运行多个工作进程(worker process),通过调度算法,将队列里的任

Node.js权威指南 (10) - Node.js中的错误处理与断言处理

10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 10.1.4 绑定回调函数与拦截回调函数 / 279 10.1.5 domain堆栈的弹出与推入 / 280 10.1.6 Domain对象的销毁 / 28610.2 Node.js中的断言处理 / 286 10.2.1 equal方法与notEqual方法 / 287 10.2.2 strictE

node.js中的交互式运行环境-REPL

<Node.js权威指南>第2章Node.js中的交互式运行环境--REPL 开发者可以在该环境中很方便地输入各种JavaScript表达式并观察表达式的运行结果. 在学习Node.js框架的过程中,通过该运行环境的使用,我们可以很方便地了解Node.js中定义的各种对象所拥有的各种属性及方法.本节为大家介绍在REPL运行环境中操作变量 2.2 在REPL运行环境中操作变量 在REPL运行环境中,可以使用var关键字来定义一个变量并为其赋值,但是在输入了对其赋值进行的表达式后,该表达式的执行结

node.js中的exports和module.exports

不同的编程语言都有各自的代码组织和复用的方式,如.net.php中的命名空间,python中的import,ruby中的module等,来避免命名空间污染.一直都没搞清楚node中的exports和module.exports的区别,借此搞清楚node的代码模块复用方式. 首先怎么创建node中的modules. 可以直接创建一个文件作为module,如下module.js function writeLine(){ console.log("module.js"); } export

在node.js中使用COOKIE

node.js中如何向客户端发送COOKIE呢?有如下两个方案: 一.使用response.writeHead,代码示例: //设置过期时间为一分钟 1 var today = new Date(); 2 var time = today.getTime() + 60*1000; 3 var time2 = new Date(time); 4 var timeObj = time2.toGMTString(); 5 response.writeHead({ 6 'Set-Cookie':'myC

setTimeout函数在浏览器中和Node.js中的区别

setTimeout函数delay时间之后执行一次func. setTimeout函数原型: var timeoutID = window.setTimeout(func, [delay, param1, param2, ...]); var timeoutID = window.setTimeout(code, [delay]);//not recommended for the same reasons as using eval() //param1, param2, and so for

log4js-Node.js中的日志管理模块使用与封装

开发过程中,日志记录是必不可少的事情,尤其是生产系统中经常无法调试,因此日志就成了重要的调试信息来源. Node.js,已经有现成的开源日志模块,就是log4js,源码地址:点击打开链接 项目引用方法: npm install log4js 1.配置说明(仅以常用的dateFile日志类型举例,更多说明参考log4js-wiki): { "appenders": [ // 下面一行应该是用于跟express配合输出web请求url日志的 {"type": "