'use strict';
var crypto = require('crypto');
var pkcs7 = require('pkcs7');
/**
* @module open-service-node-sdk/lib/decrypt
* @author xuyuanxiang <xuyuanxiang@wosai-inc.com> ({@link http://xuyuanxiang.me})
* @description 解密方案如下:
* 1. 取出返回的JSON中的encrypt字段。
* 2. 对密文BASE64解码:encrypted = Base64_Decode(encrypt)
* 3. 使用AESKey做AES解密:decrypted = AES_Decrypt(encrypted)
* 4. 验证解密后appId、消息长度
* 5. 去掉头部的16个随机字节,4个字节的消息长度和尾部的appId即为最终的消息体原文msg
*
* @example
* const decrypt = require('open-service-node-sdk/lib/decrypt');
* // 回调Post参数
* const body = {
* encrypt: 'ol5ZdzGiGK9yXYIuKB0wb5I4DTnZwkNcuo0b3OZgCUNqMRIdb9mfsmjVEe5vJT+pp7M5kyY8lfxFGnrT/qr0UER9v+skaX5GQ59AEtILoe4='
* };
* const encodingAESKey = 'KLN4DMkqdDKnUvLQ501oitOHsrZy6VRXadgdNcu3jgd';
* const appId = 'e490e912-4c09-11e7-b114-b2f933d5fe66';
* const decoded = decrypt(encodingAESKey, appId, body.encrypt);
* console.log(decoded);
* // output:
* // {
* // before: 'nO3FK7ahlgrn6sSQ',
* // content: { text: 'hello world' },
* // after: 'e490e912-4c09-11e7-b114-b2f933d5fe66'
* // }
* @param {String} encodingAESKey - 数据加密密钥
* @param {String} appId - 应用开发商创建应用获取的appId
* @param {String} encrypt - 消息密文, 回调接口Post参数中的encrypt字段
* @return {{before: String, content: *, after: String}}
*/
module.exports = function decrypt(encodingAESKey, appId, encrypt) {
// 密钥,生成规则:Base64_Decode(数据加密密钥 + “=”)
var key = new Buffer(encodingAESKey + '=', 'base64');
// 初始向量大小为16字节,取key前16字节
var iv = key.slice(0, 16);
// 对密文BASE64解码
var buff = new Buffer(encrypt, 'base64').toString('binary');
// AES解密
var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
decipher.setAutoPadding(false);
var decoded = Buffer.concat([decipher.update(buff, 'binary'), decipher.final()]);
// 验证解密后appId、消息长度
var out = new Buffer(pkcs7.unpad(decoded));
// 16字节的随机字符串
var before = out.slice(0, 16).toString('utf8');
// 4字节的msg长度,网络字节序
var len = out.readInt32BE(16);
// 消息体明文
var msg = out.slice(20, 20 + len).toString('utf8');
// 应用开发商创建应用获取的appId
var after = out.slice(20 + len).toString('utf8');
var content = void 0;
try {
content = JSON.parse(msg);
} catch (e) {
content = msg;
}
return {
before,
content,
after
};
};