使用CryptoJS解决百度小程序用户信息解密
问题描述:
swan.getUserInfo()百度官方的这个获取用户信息的方法,需要对接口返回的加密数据( data )进行对称解密。
用户数据的签名验证和加解密
智能小程序可以通过各种前端接口获取百度提供的开放数据。考虑到开发者服务器也需要获取这些开放数据,百度会对这些数据做签名和加密处理。开发者后台拿到开放数据后可以对数据进行校验签名和解密,来保证数据不被篡改。
加密数据解密算法
接口如果涉及敏感数据,接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据(data)进行对称解密。
解密过程:开发者智能小程序(通过 swan.request)将加密数据发送至自身 Server 进行解密后返回智能小程序。
解密算法如下:
对称解密使用的算法为 AES-192-CBC,数据采用PKCS#7填充;
对称解密的目标密文为 Base64_Decode(data);
对称解密秘钥 AESKey = Base64_Decode(session_key), AESKey 是24字节;
对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
解密后内容如下:
干货:模仿 Node 的 demo,使用 CryptoJS实现纯 js 下解密百度小程序用户信息(仿微信小程序案例)
1.将 CryptoJS 的包放入 小程序的 utils 中(点击下载)
2. 封装 RdWXBizDataCrypt.js
/**
* Created by hs on 2018/11/20.
*/
// 引入CryptoJS
var Crypto = require('cryptojs/cryptojs.js').Crypto;
var app = getApp();
function RdWXBizDataCrypt(appId, sessionKey, clientId) {
this.appId = appId
this.sessionKey = sessionKey
this.appkey = clientId
}
RdWXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// base64 decode :使用 CryptoJS 中 Crypto.util.base64ToBytes()进行 base64解码
var encryptedData = Crypto.util.base64ToBytes(encryptedData)
var key = Crypto.util.base64ToBytes(this.sessionKey);
var iv = Crypto.util.base64ToBytes(iv);
// 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充
var mode = new Crypto.mode.CBC(Crypto.pad.pkcs7);
try {
// 解密
var bytes = Crypto.AES.decrypt(encryptedData, key, {
asBpytes: true,
iv: iv,
mode: mode
});
//去掉尾部APPkey
bytes = bytes.replace(this.appkey, "");
//去掉16位随即长度和个人数据,20位
bytes = bytes.substr(20);
//转为JSON数据
var decryptResult = JSON.parse(bytes);
} catch (err) {
console.log("222", err)
}
// if (decryptResult.appid !== this.appId) {
// console.log(err)
// }
return decryptResult
}
module.exports = RdWXBizDataCrypt
3. 在 app.js 中引入 RdWXBizDataCrypt
var WXBizDataCrypt = require('utils/RdWXBizDataCrypt.js');
var AppId = '**************'
var AppSecret = '***************************'
var Appkey = '***************************'
App({
onLaunch: function () {
},
getUserInfo:function(cb){
var that =this;
if(this.globalData.userInfo){
typeof cb == "function" && cb(this.globalData.userInfo)
}else{
//调用登录接口,获取 code
swan.login({
success: function (res) {
//发起网络请求
swan.request({
url: 'https://openapi.baidu.com/nalogin/getSessionKeyByCode',
data:{
client_id: Appkey,
sk: AppSecret,
code: res.code,
},
header: {
"Content-Type": "application/x-www-form-urlencoded" },
method: 'GET',
success: function(res){
var pc =new WXBizDataCrypt(AppId, res.data.session_key)
swan.getUserInfo({
success: function (res) {
var data = pc.decryptData(res.encryptedData , res.iv)
console.log('解密后 data: ', data)
}
})
},
fail: function(res) {},
complete: function(res) {}
});
}
})
}
}
})
4. 实现效果