onenet http推送 使用官方的nodejs sdk报错

发布于 2022-09-11 23:23:02 字数 5153 浏览 41 评论 0

问题描述

onenet http推送 使用官方的nodejs sdk进行数据解密时报错,错误如下:Error: Invalid IV length

at Decipheriv.createCipherBase (internal/crypto/cipher.js:79:18)
at Decipheriv.createCipherWithIV (internal/crypto/cipher.js:115:20)
at new Decipheriv (internal/crypto/cipher.js:254:22)
at Object.createDecipheriv (crypto.js:117:10)
at decrypt (C:\project\nodejs_sdk\data_push_demo.js:114:27)
at C:\project\nodejs_sdk\data_push_demo.js:74:19
at Layer.handle [as handle_request] (C:\project\nodejs_sdk\node_modules\expr

esslibrouterlayer.js:95:5)

at next (C:\project\nodejs_sdk\node_modules\express\lib\router\route.js:137:

13)

at Route.dispatch (C:\project\nodejs_sdk\node_modules\express\lib\router\rou

te.js:112:3)

at Layer.handle [as handle_request] (C:\project\nodejs_sdk\node_modules\expr

esslibrouterlayer.js:95:5)

问题出现的环境背景及自己尝试过哪些方法

应该是解密时向量iv的问题,已经参照nodejs官方教程,但是仍报错。

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)
//Setup basic express server
var express = require('express');
var app = express();
var server = require('http').createServer(app);

var bodyParser = require('body-parser');

var crypto = require('crypto');

var port = process.env.PORT || 3000;

//以下内容与推送无关*//
server.listen(port, function () {

console.log('Server listening at port %d', port);

});

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

// Routing
app.use(express.static(__dirname + '/www'));
//以上内容与推送无关*//

////////////////////////////////////////////
/*

  • 第三方接收推送的接口需要同时支持post、get两种请求。
  • get 作为设置"第三方品台开发"验证 URL 及 Token 的接口,参照 http://open.iot.10086.cn/doc/...
  • 如下 dataPort 。
  • */

////////////////////////////////////////////

/*

  • 接口的 get 方法只需要接收并原样返回 query 中的 msg 字段即可,
  • 需注意的是有的组件会自动为返回的 String 加上双引号 "" 需要去掉,否则验证会失败。
  • */

app.get('/dataPort', function (req, res) {

console.log(req.query);
//res.body = req.query;

res.send(req.query.msg);

});

/*

  • 接收 post 方式的接口负责解析推过来的数据。

*

  • */

app.post('/dataPort', function (req, res) {

console.log(req.body, req.query);

// 如果存在 enc_msg 字段则是加密传输数据,需要解码。
if (req.body.enc_msg) {

    // 加密的 key 为在 http://open.iot.10086.cn 中
    // 产品管理——>第三方开发平台——>基本配置——>高级配置中设置的 EncodingAESKey 的 base64 所解码的内容
    // 这里比建议用平台随机生成的 EncodingAESKey,可以自己随机选择32位大小写加数字的字符串进行 base64 编码
    // 如下 "TVRJek5EVTJOemd4TWpNME5UWTNPREV5TXpRMU5qYzQ=" 为 “MTIzNDU2NzgxMjM0NTY3ODEyMzQ1Njc4” 的 base64 的编码形式
    // 去掉最后一个等号,以“TVRJek5EVTJOemd4TWpNME5UWTNPREV5TXpRMU5qYzQ”作为平台设置的 EncodingAESKey
    // 不建议试用 base64 的编码的结果最后有两个“=”的值作为 EncodingAESKey

    // 将在平台设置的 EncodingAESKey 加上‘=’ 进行 base64 解码,以下代码的结果为 AESKey = MTIzNDU2NzgxMjM0NTY3ODEyMzQ1Njc4
    //var AESKey = new Buffer('TVRJek5EVTJOemd4TWpNME5UWTNPREV5TXpRMU5qYzQ=', 'base64').toString();
      var AESKey = new Buffer('rlimoYl4HQxU299Jnkfs6j8PhiYleREHSqSOCFNsq8o=', 'base64').toString();

    console.log("AESKey:", AESKey);

    // enc_msg 为包含数据的消息体,首先对 enc_msg 做 base64 解码
    var enc_msg = new Buffer(req.body.enc_msg, 'base64').toString();

    // 解密中使用的秘钥由EncodingAESKey计算得来,使用的初始化iv向量为计算出的aes秘钥的前16字节
    // 去掉 dec 的前16字节,再以前4字节取出消息体长度,及 dec 的前20字节是于推送数据本身无关的。
    var dec = decrypt(AESKey, AESKey.substr(0, 16), req.body.enc_msg);

    // dec 为解密后 OneNET 平台推送数据
    console.log("数据解密后:", dec);

    console.log("数据解密后len:", dec.substr(16, 4));

}
else if(req.body.msg){
    // 如果设置明文推送模式,这相应比较简单。body 中包含 msg、msg_signature、nonce 删个字段
    // 数据详情见 http://open.iot.10086.cn/doc/art284.html#68
}
res.send({code: 200});

});

/**

  • 加密方法
  • @param key 加密key
  • @param iv 向量
  • @param data 需要加密的数据
  • @returns string

*/
var encrypt = function (key, iv, data) {

var cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
var crypted = cipher.update(data, 'utf8', 'binary');
crypted += cipher.final('binary');
crypted = new Buffer(crypted, 'binary').toString('base64');
return crypted;

};

/**

  • 解密方法,调用加解密方法前,请先安装 crypto
  • @param key 解密的key
  • @param iv 向量
  • @param crypted 密文
  • @returns string

*/
var decrypt = function (key, iv, crypted) {

crypted = new Buffer(crypted, 'base64').toString('binary');
//  这里的 aes-256-cbc 指定加密方式,推送数据的加密方式为,key 为密钥 iv 为初始化向量。
var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
var decoded = decipher.update(crypted, 'binary', 'utf8');
decoded += decipher.final('utf8');
return decoded;

};

你期待的结果是什么?实际看到的错误信息又是什么?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文