使用jsencrypt.js实现对请求参数进行RSA加密&解密,针对加密字符串过长造成加密出错进行分段加密&分段解密的处理
在开发中为了安全起见,我们都会难免遇到需要对一些敏感参数进行加密或者解密。所以,今天给大家分享的就是使用jsencrypt对请求参数进行RSA加密与解密,把整个的操作流程当做一篇文章给记录下来,以防急时之需!!!
如何使用?
使用之前,需要给项目引入jsencrypt依赖,如果你是工程项目,请给项目中拉取以下依赖
npm install jsencrypt --save
拉取之后可以通过以下方式引入到项目中进行使用
import JSEncrypt from 'jsencrypt'
如果是传统开发的朋友,请不用着急,本次讲解的demo就是使用的传统方式。
jsencrypt在加密或者解密的时候需要用到密钥,所以需要先生成一对密钥:公钥(加密),私钥(解密)。
生成方法
在终端(基于Unix的操作系统)中输入以下命令
openssl genrsa -out rsa_1024_priv.pem 1024
执行这段命令后会生成一个私钥,可以通过执行以下操作进行查看
cat rsa_1024_priv.pem
然后就可以将其复制并粘贴到需要使用私钥的地方即可。
接下来,可以通过执行以下命令获取公钥
openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem
同样,可以通过执行以下操作进行查看
cat rsa_1024_pub.pem
如果已经完成了以上操作,那么恭喜你,你现在可以去给参数进行加密了。
如何给参数加密?
给简单的字符串进行加密与解密,可以使用以下方式
//加密获得签名,key公钥,str加密对字符串内容
function getCode(key, str) {
var encrypt = new JSEncrypt()
encrypt.setPublicKey(key)
var data = encrypt.encrypt(str)
return data
}
//解密获得明文,key私钥,str加密后的签名
function deCode(key, str) {
var encrypt = new JSEncrypt()
encrypt.setPrivateKey(key)
var data = encrypt.decrypt(str)
return data
}
如果是给一段较长的字符串加密,这里可能就会有坑了,因为长度问题可能会造成加解密失败,如果你遇到了,请使用下面方式进行分段加解密,这样就解决了该问题的出现
//分段加密算法方法
JSEncrypt.prototype.encryptLong = function (string) {
var k = this.getKey(),
maxLength = (((k.n.bitLength()+7)>>3)-11);
try {
var lt = "",
ct = "";
if (string.length > maxLength) {
lt = string.match(/.{1,50}/g);
lt.forEach(entry => {
var t1 = k.encrypt(entry);
ct += t1 ;
});
return hex2b64(ct);
}
var t = k.encrypt(string),
y = hex2b64(t);
return y;
} catch (ex) {
return ex;
}
};
//分段解密算法方法
JSEncrypt.prototype.decryptLong = function (string) {
var k = this.getKey(),
maxLength = (((k.n.bitLength()+7)>>3)-11);
try {
var ct = '';
string = b64tohex(string)
if (string.length > maxLength) {
var lt = string.match(/.{1,256}/g);
lt.forEach(function(entry) {
var t1 = k.decrypt(entry);
ct += t1;
});
return ct;
}
var y = k.decrypt(b64tohex(string));
return y;
} catch (ex) {
return ex;
}
};
//分段加密
function getLongCode(key, str) {
var encrypt = new JSEncrypt()
encrypt.setPublicKey(key)
var data = encrypt.encryptLong(str)
return data
}
//分段解密
function deLongCode(key, str) {
var decryptLong = new JSEncrypt()
decryptLong.setPrivateKey(key)
var data = decryptLong.decryptLong(str)
return /^{.+}$/g.test(data) && JSON.parse(data) || data
}
上方代码中出现了几个未定义的方法,hex2b64,b64tohex,这两个方法是base64分段的算法函数,下面是补充的算法封装函数依赖
var dbits;
var canary = 244837814094590;
var j_lm = ((canary & 16777215) == 15715070);
function BigInteger(e, d, f) {
if (e != null) {
if ("number" == typeof e) {
this.fromNumber(e, d, f)
} else {
if (d == null && "string" != typeof e) {
this.fromString(e, 256)
} else {
this.fromString(e, d)
}
}
}
}
function nbi() {
return new BigInteger(null)
}
function am1(f, a, b, e, h, g) {
while (--g >= 0) {
var d = a * this[f++] + b[e] + h;
h = Math.floor(d / 67108864);
b[e++] = d & 67108863
}
return h
}
function am2(f, q, r, e, o, a) {
var k = q & 32767,
p = q >> 15;
while (--a >= 0) {
var d = this[f] & 32767;
var g = this[f++] >> 15;
var b = p * d + g * k;
d = k * d + ((b & 32767) << 15) + r[e] + (o & 1073741823);
o = (d >>> 30) + (b >>> 15) + p * g + (o >>> 30);
r[e++] = d & 1073741823
}
return o
}
function am3(f, q, r, e, o, a) {
var k = q & 16383,
p = q >> 14;
while (--a >= 0) {
var d = this[f] & 16383;
var g = this[f++] >> 14;
var b = p * d + g * k;
d = k * d + ((b & 16383) << 14) + r[e] + o;
o = (d >> 28) + (b >> 14) + p * g;
r[e++] = d & 268435455
}
return o
}
//if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) { //xpp注释
// BigInteger.prototype.am = am2;
// dbits = 30
//} else {
// if (j_lm && (navigator.appName != "Netscape")) {
// BigInteger.prototype.am = am1;
// dbits = 26
// } else {
BigInteger.prototype.am = am3;
dbits = 28
// }
//}
BigInteger.prototype.DB = dbits;
BigInteger.prototype.DM = ((1 << dbits) - 1);
BigInteger.prototype.DV = (1 << dbits);
var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2, BI_FP);
BigInteger.prototype.F1 = BI_FP - dbits;
BigInteger.prototype.F2 = 2 * dbits - BI_FP;
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = new Array();
var rr, vv;
rr = "0".charCodeAt(0);
for (vv = 0; vv <= 9; ++vv) {
BI_RC[rr++] = vv
}
rr = "a".charCodeAt(0);
for (vv = 10; vv < 36; ++vv) {
BI_RC[rr++] = vv
}
rr = "A".charCodeAt(0);
for (vv = 10; vv < 36; ++vv) {
BI_RC[rr++] = vv
}
function int2char(a) {
return BI_RM.charAt(a)
}
function intAt(b, a) {
var d = BI_RC[b.charCodeAt(a)];
return (d == null) ? -1 : d
}
function bnpToRadix(b) {
if (b == null) {
b = 10
}
if (this.signum() == 0 || b < 2 || b > 36) {
return "0"
}
var cs = this.chunkSize(b);
var a = Math.pow(b, cs);
var d = nbv(a),
y = nbi(),
z = nbi(),
r = "";
this.divRemTo(d, y, z);
while (y.signum() > 0) {
r = (a + z.intValue()).toString(b).substr(1) + r;
y.divRemTo(d, y, z)
}
return z.intValue().toString(b) + r
}
function bnSigNum() {
if (this.s < 0) {
return -1
} else {
if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) {
return 0
} else {
return 1
}
}
}
function bnpChunkSize(r) {
return Math.floor(Math.LN2 * this.DB / Math.log(r))
}
function bnIntValue() {