记一次在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计算得到的加密结果可以通过服务端的验证。
记一次在node.js中使用crypto的createCipheriv方法进行加密时所遇到的坑的更多相关文章
- node.js中的http.response.end方法使用说明
转载自:http://m.jb51.net/article/58468.htm 本文介绍了http.response.end的方法说明.语法.接收参数.使用实例和实现源码,需要的朋友可以参考下 方法说 ...
- 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查
Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...
- 如何在Node.js中合并两个复杂对象
通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢? 例如我有以下两个object: ...
- Node.js中的Session,不要觉得简单哦。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .学习网站上有对应 ...
- Node.js 中MongoDB的基本接口操作
Node.js 中MongoDB的基本接口操作 连接数据库 安装mongodb模块 导入mongodb模块 调用connect方法 文档的增删改查操作 插入文档 方法: db.collection(& ...
- 在node.js中使用COOKIE
node.js中如何向客户端发送COOKIE呢?有如下两个方案: 一.使用response.writeHead,代码示例: //设置过期时间为一分钟 var today = new Date(); v ...
- 初步揭秘node.js中的事件
当你学习node.js的时候,Events是一个非常重要的需要理解的事情.非常多的Node对象触发事件,你能在文档API中找到很多例子.但是关于如何写自己的事件和监听,你可能还不太清楚.如果你不了解, ...
- Node.js权威指南 (10) - Node.js中的错误处理与断言处理
10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...
- Node.js中的URL
Node.js中的URL 什么是URL URL是Uniform Location Resource的缩写,翻译为"统一资源定位符",也就是描述资源位置的固定表示方法.被URL描述的 ...
随机推荐
- idea中自定义快捷键
idea中自定义快捷键 在开发的过程中,总要写一些重复的代码,那么使用自定义快捷键,可以将这些经常用到的代码,自动生成. 1.在idea工具中点击File-->Settings 2.在弹出来的界 ...
- vue axios 总结篇
1.npm --save 和 --save-dev 有什么区别 发布到线上的叫生产环境~,在本地开发的时候叫开发环境,--save就是会打包到线上去并且在线上环境能用到的,比如你npm install ...
- iOS app反编译
对于APP store 上的应用都是加密的了,反编译起来有难度. 对于自己用xcode 编译的ipa 或者是其他渠道下载的ipa包都可以使用反编译工具进行反编译. https://cnbin.gith ...
- iOS 基本控件的使用以及系统层次架构(1)
User Interface iOS系统架构层次图 -CocoaTouch UI相关 -媒体层(Media) 音频.视频.图形.动画 -核心服务层(Core services) 内存.网络.文件.线 ...
- 揭秘 iOS App Extension 开发 —— Today 篇
转自:http://www.cocoachina.com/ios/20160619/16760.html 本文授权转载,作者:Cyandev(简书) 从 iOS 8 开始,苹果引入了全新的 App E ...
- BZOJ1014 火星人的prefix
火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字 ...
- BX谷 2019年最新所有人都能学会的数据分析课视频教程
第一章 数据分析师职业概览 1-1 数据分析师的职业概览免费试学 数据分析师的"钱"景如何 什么人适合学数据分析 数据分析师的临界知识 数据分析师的主要职责 第二章 数据分析和数据 ...
- 统计学习方法与Python实现(一)——感知机
统计学习方法与Python实现(一)——感知机 iwehdio的博客园:https://www.cnblogs.com/iwehdio/ 1.定义 假设输入的实例的特征空间为x属于Rn的n维特征向量, ...
- WPF 画一个3D矩形并旋转
具体的代码还是线性代数. 主要是旋转和平移. 这个例子的中模型是在世界原点建立.所以旋转会以自身轴心旋转. 如果不在世界原点建立模型,还想以自身为旋转轴旋转. 则是需要以下步骤: 模型的中心点为V1( ...
- JS-选择排序
选择排序 选择排序的原理如下.遍历数组,设置最小值的索引为 0,如果取出的值比当前最小值小,就替换最小值索引,遍历完成后,将第一个元素和最小值索引上的值交换.如上操作后,第一个元素就是数组中的最小值, ...