小程序中无法直接使用jsencrypt,直接上错误信息如下
点开错误信息,可见小程序环境中中是没有navigator对象的,所以代码中才会报错
全局搜了一遍源码中navigator相关代码有两处:
源码中有用到navigator.appName和navigator.userAgent两个字段,我们分析两处代码,对于appName主要用与判断浏览器选择不同的大数处理方式,这里我们可以考虑直接删除其他代码选择am3,或者构造一个navigator.appName = 'Netscape';对于userAgent主要用于IE11之前的浏览器做兼容处理,对此我们也可以直接给userAgent赋值来绕过。
// 可以直接从浏览器中取值
var navigator = {
appName: 'Netscape',
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
};
解决完navigator会发现还有类似问题,window对象同样是不存在的,依葫芦画瓢
源码中中使用到window对象的地方主要是在有crypto属性时做rng_pool的初始化,以及mousemove的事件监听,这里没有添加事件并没不会影响到加密,所以直接给一个空的window对象也是可以的。
// 用到的window属性基本是用于判断是否使用window对象提供的方法,只要相关代码不报错就好了。
var window = {
crypto: null
}
到这一步就不会再报错了,可以使用jsencrypt中的方法来做加密解密了
const Key = 'TEST KEY';
const encrypt = new JSEncrypt();
// 这里使用指定的公钥
encrypt.setPublicKey(`-----BEGIN PUBLIC KEY-----
your public key
-----END PUBLIC KEY-----`);
let encryptedKey = encrypt.encrypt(Key);
mpvue中引入jsEncrypt
拷贝一份jsEncrypt源码,然后按照以上的方式进行修改,直接引入使用
const {JSEncrypt} = require('./jsencrypt');
const encrypt = new JSEncrypt();
不出意外会有以下报错,反正我是遇到了。。。
怎么搞呢,导出的JSEncrypt是undefined,见鬼了。看源码中,其实已经是做了模块化的包装,在mpvue中还会有一次打包,会将代码再做一次封装,那么我直接把源码中的包装代码移除然后export JSEncrypt就好了
/* eslint-disable */
// (function (global, factory) {
// typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
// typeof define === 'function' && define.amd ? define(['exports'], factory) :
// (factory((global.JSEncrypt = {})));
// }(this, (function (exports) {
'use strict';
.....
export default JSEncrypt// 新加的导出
// window.JSEncrypt = JSEncrypt;
// exports.JSEncrypt = JSEncrypt;
// exports.default = JSEncrypt;
// Object.defineProperty(exports, '__esModule', { value: true });
// })));
到此已经可以在mpvue中愉快地使用JSEncrypt了。
encrypt 方法默认输出的是base64
/**
* Proxy method for RSAKey object's encrypt, encrypt the string using the public
* components of the rsa key object. Note that if the object was not set will be created
* on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
* @param {string} str the string to encrypt
* @return {string} the encrypted string encoded in base64
* @public
*/
JSEncrypt.prototype.encrypt = function (str) {
// Return the encrypted string.
try {
return hex2b64(this.getKey().encrypt(str));
}
catch (ex) {
return false;
}
};
如果项目使用的是hex那就需要再进行一次转换了,如果项目也和我一样使用到了CryptoJS,那可以这样操作。
//encryptedString 是JSEncrypt加密后输出的base64串
CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(encryptedString))
如果没有用到CryptoJS,也可以直接把源码中的hex2b64移除,或者把源码中的b64tohex方法导出使用。