在一次项目实战中,前端登录使用了RSA加密,使用LoadRunner压测的第一步,就是模拟用户登录,可惜loadRunner11并不能录制前端的加密过程,并且安装的LR是基于C语言版,网络上关于RSA的加密更多的是Java版,最后,选择在Jmeter中先尝试一下能否解决加密的问题,毕竟它有很多处理器,用于脚本的插入;

  把解决过程中遇到的问题,简单做个记录,防止遗忘,也算是给自己下一次项目一个经验总结了;

【1】了解加密方式-----RSA

  询问开发前端的加密方式:先请求public_key,再加密密码,再提交。

  加密的代码前端代码实现:

  $.getJSON('/public_key?t='+timestamp).then((rsa) => {

    let rsaKey = new RSAKey();

   rsaKey.setPublic(b64tohex(rsa.modulus), b64tohex(rsa.exponent));

   data.password = hex2b64(rsaKey.encrypt(data.password));

    $.post('/ajax_login_check', data).then(this.completed, this.failed);

  }, this.failed);

  备注:以上来自开发,后来在了解RSA的实现方式中,发现大家的RSA前端加密方式是一样的~

  已知了上面这些,下面开始自己玩前端RSA加密的方式,抓包查看登录的请求,有三个重要的请求:

  ①GET /public_key?t=1495537754854 :用于获取RAS生成公钥时的两个重要参数exponent 和 modulus;

  ②POST /ajax_login_check:用于将已加密的密码 && 登录名post到服务器去验证,验证成功后返回success;

  ③GET /:在 /ajax_login_check验证成功后,GET /请求会返回一个TOKEN值,作为该用户进入系统后的令牌,执行系统内的每一个操作时,对应的请求都需要在头部添加该参数,否则会报403错误;

【2】查找加密使用的js文件

  也是走了很多弯路,先在DOS下折腾,后又安装了eclipse,在网上找寻各种加密代码,打成jar包,在LoadRunner中却无法使用;将网上关于RSA的java类及方法直接放在Jmeter中进行加密,Jmeter连import都不支持;

  然后,仔细查看登录的每一个请求包,注意到一个js文件,其中有关于BigInteger和RSA的函数定义(C语言中是这样称呼的,我也这样称呼了),想一想既然是在前端加密,那服务器会不会直接将加密使用的方法返回给客户端呢,谷歌浏览器按“F12”查看登录页面的Sources,查找js文件,后来发现前面提到的js文件sec.min.js中竟然有开发用于加密的函数hex2b64(),急忙将该js文件保存在本地,开发使用到的加密的方法都可以在这个文件中找到,喜极而泣;

【3】使用Jmeter的JSR223后置处理器,完成加密

  使用apache-jmeter-2.12 + jdk 1.6,在JSR223中load("sec.min.js");,总是报错“jmeter.modifiers.JSR223PreProcessor: Problem in JSR223 script JSR223 PreProcessor javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "load" is not defined.”,后考虑是不是版本问题,换了apache-jmeter-3.2 + jdk1.8,load不再报错;

  注:①使用到的js文件需要放在jmeter的bin目录下;②JSR223中,Language选择“JavaScript”;

  Jmeter中加密的调用实现如下:

  JSR223中使用到的modules的正则表达式提取如下:

【4】调试js文件

  勾选Jmeter“选项”→“Log Viewer”,添加Debug后置处理器;在Jmeter中会打印代码执行的情况,有错误的话就逐步排除;PS:调试很艰难,且调且珍惜;

  ①navigator  报错,求助网络,这是浏览器对象,因为录制时使用的谷歌浏览器,所以我选择了保留关于谷歌的设置(其实不一定要选择谷歌相关的,只要js文件中使用同一浏览器的相关属性值即可),将不重要的直接可以注释掉,类似的还有 window;

   

 

  ②alert()在Jmeter中无法执行(会报错):直接将js中的alert()注释,并用return null; 替换,便于调试;

  ③我在调试过程中还遇到 toRadix & signum &  chunkSize & intValue未定义;继续使用F12查看自己是否有遗漏需要load的js文件,并没有找到,然后在网上搜索  toRadix 直接就出来了,O(∩_∩)O~~,于是添加属性及方法在js文件中,正确执行,耶耶耶~~~~链接:http://blog.csdn.net/huaye2007/article/details/41727921

【4】后续处理

  ①GET /public_key?t=1495537754854这里的t是Unix时间戳,在该请求中添加 JSR223前置处理器,使用如下语句完成处理:

  var timestamp=new Date().getTime();   //精确到毫秒;

  vars.put("timestamp",timestamp);

  ②依旧显示密码错误:一步步排查,注意到在POST时,“查看结果树”的“请求”中显示的内容与log中打印的不一致(密文为base64编码),具体为“+”显示不正确,再次询问网络,有人提到含有“+”的字符串在URL中传递时,需要替换加号为%2B,否则在服务器解码的时候会出错;

  后来勾选了 /ajax_login_check请求对应的参数“password”值的“编码”,在该请求的结果树中,可以看到POST的密文已经将“+”及“/”进行了转码,因此最终并未使用替换语句;

  附上替换语句:data = data.replace(/\+/g,"%2B");      data = data.replace(/\//g,"%2F");   // \g代表全部替换

  至此,完成了前端模拟RSA加密,进行登录,ajax校验用户名&密码通过;

  总结及感悟:对于前端加密,服务器应该是要返回加密方式给客户端的,否则客户端无从知晓如何加密,至于加密的方式是否可以直接识别,1在于服务端的返回内容,2在于测试人员是否有很好的观察及辨识能力,而这种辨识能力就在于平时的多涉猎多接触,一开始抓包也有看到sec.min.js,但是并没有敏锐的意识到加密就藏在这里,兜兜转转才发现,所以还是要多学习,开发知识也好,测试知识也罢O(∩_∩)O~~

  附1----------Jmeter中JSR前置处理器的javascript脚本

load("sec.min.js");

var modulus = vars.get("modulus");
log.info(modulus);
var exponent = vars.get("exponent");
log.info(exponent); function RSA(){
var rsaKey = new RSAKey();
rsaKey.setPublic(b64tohex("${modulus}"),b64tohex("${exponent}"));
var Enpassword = hex2b64(rsaKey.encrypt("${password}"));
return Enpassword
}
var data = RSA();
log.info(data);
//base64在url中的传输,要注意+ /两个符号
//data = data.replace(/\+/g,"%2B");
//data = data.replace(/\//g,"%2F");
vars.put("Password",data);
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
}
//-----摘自网络-----start
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() {
if (this.s < 0) {
if (this.t == 1) {
return this[0] - this.DV
} else {
if (this.t == 0) {
return -1
}
}
} else {
if (this.t == 1) {
return this[0]
} else {
if (this.t == 0) {
return 0
}
}
}
return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0]
}
//-----摘自网络-----end function bnpCopyTo(b) {
for (var a = this.t - 1; a >= 0; --a) {
b[a] = this[a]
}
b.t = this.t;
b.s = this.s
}
function bnpFromInt(a) {
this.t = 1;
this.s = (a < 0) ? -1 : 0;
if (a > 0) {
this[0] = a
} else {
if (a < -1) {
this[0] = a + DV
} else {
this.t = 0
}
}
}
function nbv(a) {
var b = nbi();
b.fromInt(a);
return b
}
function bnpFromString(h, c) {
var e;
if (c == 16) {
e = 4
} else {
if (c == 8) {
e = 3
} else {
if (c == 256) {
e = 8
} else {
if (c == 2) {
e = 1
} else {
if (c == 32) {
e = 5
} else {
if (c == 4) {
e = 2
} else {
this.fromRadix(h, c);
return
}
}
}
}
}
}
this.t = 0;
this.s = 0;
var g = h.length,
d = false,
f = 0;
while (--g >= 0) {
var a = (e == 8) ? h[g] & 255 : intAt(h, g);
if (a < 0) {
if (h.charAt(g) == "-") {
d = true
}
continue
}
d = false;
if (f == 0) {
this[this.t++] = a
} else {
if (f + e > this.DB) {
this[this.t - 1] |= (a & ((1 << (this.DB - f)) - 1)) << f;
this[this.t++] = (a >> (this.DB - f))
} else {
this[this.t - 1] |= a << f
}
}
f += e;
if (f >= this.DB) {
f -= this.DB
}
}
if (e == 8 && (h[0] & 128) != 0) {
this.s = -1;
if (f > 0) {
this[this.t - 1] |= ((1 << (this.DB - f)) - 1) << f
}
}
this.clamp();
if (d) {
BigInteger.ZERO.subTo(this, this)
}
}
function bnpClamp() {
var a = this.s & this.DM;
while (this.t > 0 && this[this.t - 1] == a) {
--this.t
}
}
function bnToString(c) {
if (this.s < 0) {
return "-" + this.negate().toString(c)
}
var e;
if (c == 16) {
e = 4
} else {
if (c == 8) {
e = 3
} else {
if (c == 2) {
e = 1
} else {
if (c == 32) {
e = 5
} else {
if (c == 4) {
e = 2
} else {
return this.toRadix(c)
}
}
}
}
}
var g = (1 << e) - 1,
l,
a = false,
h = "",
f = this.t;
var j = this.DB - (f * this.DB) % e;
if (f-- > 0) {
if (j < this.DB && (l = this[f] >> j) > 0) {
a = true;
h = int2char(l)
}
while (f >= 0) {
if (j < e) {
l = (this[f] & ((1 << j) - 1)) << (e - j);
l |= this[--f] >> (j += this.DB - e)
} else {
l = (this[f] >> (j -= e)) & g;
if (j <= 0) {
j += this.DB;
--f
}
}
if (l > 0) {
a = true
}
if (a) {
h += int2char(l)
}
}
}
return a ? h : "0"
}
function bnNegate() {
var a = nbi();
BigInteger.ZERO.subTo(this, a);
return a
}
function bnAbs() {
return (this.s < 0) ? this.negate() : this
}
function bnCompareTo(b) {
var d = this.s - b.s;
if (d != 0) {
return d
}
var c = this.t;
d = c - b.t;
if (d != 0) {
return (this.s < 0) ? -d : d
}
while (--c >= 0) {
if ((d = this[c] - b[c]) != 0) {
return d
}
}
return 0
}
function nbits(a) {
var c = 1,
b;
if ((b = a >>> 16) != 0) {
a = b;
c += 16
}
if ((b = a >> 8) != 0) {
a = b;
c += 8
}
if ((b = a >> 4) != 0) {
a = b;
c += 4
}
if ((b = a >> 2) != 0) {
a = b;
c += 2
}
if ((b = a >> 1) != 0) {
a = b;
c += 1
}
return c
}
function bnBitLength() {
if (this.t <= 0) {
return 0
}
return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM))
} function bnpDLShiftTo(c, b) {
var a;
for (a = this.t - 1; a >= 0; --a) {
b[a + c] = this[a]
}
for (a = c - 1; a >= 0; --a) {
b[a] = 0
}
b.t = this.t + c;
b.s = this.s
}
function bnpDRShiftTo(c, b) {
for (var a = c; a < this.t; ++a) {
b[a - c] = this[a]
}
b.t = Math.max(this.t - c, 0);
b.s = this.s
}
function bnpLShiftTo(j, e) {
var b = j % this.DB;
var a = this.DB - b;
var g = (1 << a) - 1;
var f = Math.floor(j / this.DB),
h = (this.s << b) & this.DM,
d;
for (d = this.t - 1; d >= 0; --d) {
e[d + f + 1] = (this[d] >> a) | h;
h = (this[d] & g) << b
}
for (d = f - 1; d >= 0; --d) {
e[d] = 0
}
e[f] = h;
e.t = this.t + f + 1;
e.s = this.s;
e.clamp()
}
function bnpRShiftTo(g, d) {
d.s = this.s;
var e = Math.floor(g / this.DB);
if (e >= this.t) {
d.t = 0;
return
}
var b = g % this.DB;
var a = this.DB - b;
var f = (1 << b) - 1;
d[0] = this[e] >> b;
for (var c = e + 1; c < this.t; ++c) {
d[c - e - 1] |= (this[c] & f) << a;
d[c - e] = this[c] >> b
}
if (b > 0) {
d[this.t - e - 1] |= (this.s & f) << a
}
d.t = this.t - e;
d.clamp()
}
function bnpSubTo(d, f) {
var e = 0,
g = 0,
b = Math.min(d.t, this.t);
while (e < b) {
g += this[e] - d[e];
f[e++] = g & this.DM;
g >>= this.DB
}
if (d.t < this.t) {
g -= d.s;
while (e < this.t) {
g += this[e];
f[e++] = g & this.DM;
g >>= this.DB
}
g += this.s
} else {
g += this.s;
while (e < d.t) {
g -= d[e];
f[e++] = g & this.DM;
g >>= this.DB
}
g -= d.s
}
f.s = (g < 0) ? -1 : 0;
if (g < -1) {
f[e++] = this.DV + g
} else {
if (g > 0) {
f[e++] = g
}
}
f.t = e;
f.clamp()
}
function bnpMultiplyTo(c, e) {
var b = this.abs(),
f = c.abs();
var d = b.t;
e.t = d + f.t;
while (--d >= 0) {
e[d] = 0
}
for (d = 0; d < f.t; ++d) {
e[d + b.t] = b.am(0, f[d], e, d, 0, b.t)
}
e.s = 0;
e.clamp();
if (this.s != c.s) {
BigInteger.ZERO.subTo(e, e)
}
}
function bnpSquareTo(d) {
var a = this.abs();
var b = d.t = 2 * a.t;
while (--b >= 0) {
d[b] = 0
}
for (b = 0; b < a.t - 1; ++b) {
var e = a.am(b, a[b], d, 2 * b, 0, 1);
if ((d[b + a.t] += a.am(b + 1, 2 * a[b], d, 2 * b + 1, e, a.t - b - 1)) >= a.DV) {
d[b + a.t] -= a.DV;
d[b + a.t + 1] = 1
}
}
if (d.t > 0) {
d[d.t - 1] += a.am(b, a[b], d, 2 * b, 0, 1)
}
d.s = 0;
d.clamp()
}
function bnpDivRemTo(n, h, g) {
var w = n.abs();
if (w.t <= 0) {
return
}
var k = this.abs();
if (k.t < w.t) {
if (h != null) {
h.fromInt(0)
}
if (g != null) {
this.copyTo(g)
}
return
}
if (g == null) {
g = nbi()
}
var d = nbi(),
a = this.s,
l = n.s;
var v = this.DB - nbits(w[w.t - 1]);
if (v > 0) {
w.lShiftTo(v, d);
k.lShiftTo(v, g)
} else {
w.copyTo(d);
k.copyTo(g)
}
var p = d.t;
var b = d[p - 1];
if (b == 0) {
return
}
var o = b * (1 << this.F1) + ((p > 1) ? d[p - 2] >> this.F2 : 0);
var A = this.FV / o,
z = (1 << this.F1) / o,
x = 1 << this.F2;
var u = g.t,
s = u - p,
f = (h == null) ? nbi() : h;
d.dlShiftTo(s, f);
if (g.compareTo(f) >= 0) {
g[g.t++] = 1;
g.subTo(f, g)
}
BigInteger.ONE.dlShiftTo(p, f);
f.subTo(d, d);
while (d.t < p) {
d[d.t++] = 0
}
while (--s >= 0) {
var c = (g[--u] == b) ? this.DM : Math.floor(g[u] * A + (g[u - 1] + x) * z);
if ((g[u] += d.am(0, c, g, s, 0, p)) < c) {
d.dlShiftTo(s, f);
g.subTo(f, g);
while (g[u] < --c) {
g.subTo(f, g)
}
}
}
if (h != null) {
g.drShiftTo(p, h);
if (a != l) {
BigInteger.ZERO.subTo(h, h)
}
}
g.t = p;
g.clamp();
if (v > 0) {
g.rShiftTo(v, g)
}
if (a < 0) {
BigInteger.ZERO.subTo(g, g)
}
}
function bnMod(b) {
var c = nbi();
this.abs().divRemTo(b, null, c);
if (this.s < 0 && c.compareTo(BigInteger.ZERO) > 0) {
b.subTo(c, c)
}
return c
}
function Classic(a) {
this.m = a
}
function cConvert(a) {
if (a.s < 0 || a.compareTo(this.m) >= 0) {
return a.mod(this.m)
} else {
return a
}
}
function cRevert(a) {
return a
}
function cReduce(a) {
a.divRemTo(this.m, null, a)
}
function cMulTo(a, c, b) {
a.multiplyTo(c, b);
this.reduce(b)
}
function cSqrTo(a, b) {
a.squareTo(b);
this.reduce(b)
}
Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;
function bnpInvDigit() {
if (this.t < 1) {
return 0
}
var a = this[0];
if ((a & 1) == 0) {
return 0
}
var b = a & 3;
b = (b * (2 - (a & 15) * b)) & 15;
b = (b * (2 - (a & 255) * b)) & 255;
b = (b * (2 - (((a & 65535) * b) & 65535))) & 65535;
b = (b * (2 - a * b % this.DV)) % this.DV;
return (b > 0) ? this.DV - b : -b
}
function Montgomery(a) {
this.m = a;
this.mp = a.invDigit();
this.mpl = this.mp & 32767;
this.mph = this.mp >> 15;
this.um = (1 << (a.DB - 15)) - 1;
this.mt2 = 2 * a.t
}
function montConvert(a) {
var b = nbi();
a.abs().dlShiftTo(this.m.t, b);
b.divRemTo(this.m, null, b);
if (a.s < 0 && b.compareTo(BigInteger.ZERO) > 0) {
this.m.subTo(b, b)
}
return b
}
function montRevert(a) {
var b = nbi();
a.copyTo(b);
this.reduce(b);
return b
}
function montReduce(a) {
while (a.t <= this.mt2) {
a[a.t++] = 0
}
for (var c = 0; c < this.m.t; ++c) {
var b = a[c] & 32767;
var d = (b * this.mpl + (((b * this.mph + (a[c] >> 15) * this.mpl) & this.um) << 15)) & a.DM;
b = c + this.m.t;
a[b] += this.m.am(0, d, a, c, 0, this.m.t);
while (a[b] >= a.DV) {
a[b] -= a.DV;
a[++b]++
}
}
a.clamp();
a.drShiftTo(this.m.t, a);
if (a.compareTo(this.m) >= 0) {
a.subTo(this.m, a)
}
}
function montSqrTo(a, b) {
a.squareTo(b);
this.reduce(b)
}
function montMulTo(a, c, b) {
a.multiplyTo(c, b);
this.reduce(b)
}
Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;
function bnpIsEven() {
return ((this.t > 0) ? (this[0] & 1) : this.s) == 0
}
function bnpExp(h, j) {
if (h > 4294967295 || h < 1) {
return BigInteger.ONE
}
var f = nbi(),
a = nbi(),
d = j.convert(this),
c = nbits(h) - 1;
d.copyTo(f);
while (--c >= 0) {
j.sqrTo(f, a);
if ((h & (1 << c)) > 0) {
j.mulTo(a, d, f)
} else {
var b = f;
f = a;
a = b
}
}
return j.revert(f)
}
function bnModPowInt(b, a) {
var c;
if (b < 256 || a.isEven()) {
c = new Classic(a)
} else {
c = new Montgomery(a)
}
return this.exp(b, c)
}
//-----摘自网络-----start
BigInteger.prototype.toRadix = bnpToRadix;
BigInteger.prototype.signum = bnSigNum;
BigInteger.prototype.chunkSize = bnpChunkSize;
BigInteger.prototype.intValue = bnIntValue;
//-----摘自网络-----end
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
BigInteger.prototype.squareTo = bnpSquareTo;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.exp = bnpExp;
BigInteger.prototype.toString = bnToString;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.bitLength = bnBitLength;
BigInteger.prototype.mod = bnMod;
BigInteger.prototype.modPowInt = bnModPowInt;
BigInteger.ZERO = nbv(0);
BigInteger.ONE = nbv(1);
function Arcfour() {
this.i = 0;
this.j = 0;
this.S = new Array()
}
function ARC4init(d) {
var c,
a,
b;
for (c = 0; c < 256; ++c) {
this.S[c] = c
}
a = 0;
for (c = 0; c < 256; ++c) {
a = (a + this.S[c] + d[c % d.length]) & 255;
b = this.S[c];
this.S[c] = this.S[a];
this.S[a] = b
}
this.i = 0;
this.j = 0
}
function ARC4next() {
var a;
this.i = (this.i + 1) & 255;
this.j = (this.j + this.S[this.i]) & 255;
a = this.S[this.i];
this.S[this.i] = this.S[this.j];
this.S[this.j] = a;
return this.S[(a + this.S[this.i]) & 255]
}
Arcfour.prototype.init = ARC4init;
Arcfour.prototype.next = ARC4next;
function prng_newstate() {
return new Arcfour()
}
var rng_psize = 256;
var rng_state;
var rng_pool;
var rng_pptr;
function rng_seed_int(a) {
rng_pool[rng_pptr++] ^= a & 255;
rng_pool[rng_pptr++] ^= (a >> 8) & 255;
rng_pool[rng_pptr++] ^= (a >> 16) & 255;
rng_pool[rng_pptr++] ^= (a >> 24) & 255;
if (rng_pptr >= rng_psize) {
rng_pptr -= rng_psize
}
}
function rng_seed_time() {
rng_seed_int(new Date().getTime())
}
if (rng_pool == null) { //注释
rng_pool = new Array();
rng_pptr = 0;
var t;
// if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
// var z = window.crypto.random(32);
// for (t = 0; t < z.length; ++t) {
// rng_pool[rng_pptr++] = z.charCodeAt(t) & 255
// }
// }
// while (rng_pptr < rng_psize) {
// t = Math.floor(65536 * Math.random());
// rng_pool[rng_pptr++] = t >>> 8;
// rng_pool[rng_pptr++] = t & 255
// }
// rng_pptr = 0;
// rng_seed_time()
}
function rng_get_byte() {
if (rng_state == null) {
rng_seed_time();
rng_state = prng_newstate();
rng_state.init(rng_pool);
for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) {
rng_pool[rng_pptr] = 0
}
rng_pptr = 0
}
return rng_state.next()
}
function rng_get_bytes(b) {
var a;
for (a = 0; a < b.length; ++a) {
b[a] = rng_get_byte()
}
}
function SecureRandom() {}
SecureRandom.prototype.nextBytes = rng_get_bytes;
function parseBigInt(b, a) {
return new BigInteger(b, a)
}
function linebrk(c, d) {
var a = "";
var b = 0;
while (b + d < c.length) {
a += c.substring(b, b + d) + "\n";
b += d
}
return a + c.substring(b, c.length)
}
function byte2Hex(a) {
if (a < 16) {
return "0" + a.toString(16)
} else {
return a.toString(16)
}
}
function pkcs1pad2(e, h) {
if (h < e.length + 11) {
// alert("Message too long for RSA");
return null
}
var g = new Array();
var d = e.length - 1;
while (d >= 0 && h > 0) {
var f = e.charCodeAt(d--);
if (f < 128) {
g[--h] = f
} else {
if ((f > 127) && (f < 2048)) {
g[--h] = (f & 63) | 128;
g[--h] = (f >> 6) | 192
} else {
g[--h] = (f & 63) | 128;
g[--h] = ((f >> 6) & 63) | 128;
g[--h] = (f >> 12) | 224
}
}
}
g[--h] = 0;
var b = new SecureRandom();
var a = new Array();
while (h > 2) {
a[0] = 0;
while (a[0] == 0) {
b.nextBytes(a)
}
g[--h] = a[0]
}
g[--h] = 2;
g[--h] = 0;
return new BigInteger(g)
}
function RSAKey() {
this.n = null;
this.e = 0;
this.d = null;
this.p = null;
this.q = null;
this.dmp1 = null;
this.dmq1 = null;
this.coeff = null
}
function RSASetPublic(b, a) {
if (b != null && a != null && b.length > 0 && a.length > 0) {
this.n = parseBigInt(b, 16);
this.e = parseInt(a, 16);
return this.n.toString();
} else {
// alert("Invalid RSA public key")
return 0;
}
}
function RSADoPublic(a) {
return a.modPowInt(this.e, this.n)
}
function RSAEncrypt(d) {
var a = pkcs1pad2(d, (this.n.bitLength() + 7) >> 3);
if (a == null) {
return null
}
var e = this.doPublic(a);
if (e == null) {
return null
}
var b = e.toString(16);
if ((b.length & 1) == 0) {
return b
} else {
return "0" + b
}
return a;
}
RSAKey.prototype.doPublic = RSADoPublic;
RSAKey.prototype.setPublic = RSASetPublic;
RSAKey.prototype.encrypt = RSAEncrypt;
var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64pad = "=";
function hex2b64(d) {
var b;
var e;
var a = "";
for (b = 0; b + 3 <= d.length; b += 3) {
e = parseInt(d.substring(b, b + 3), 16);
a += b64map.charAt(e >> 6) + b64map.charAt(e & 63)
}
if (b + 1 == d.length) {
e = parseInt(d.substring(b, b + 1), 16);
a += b64map.charAt(e << 2)
} else {
if (b + 2 == d.length) {
e = parseInt(d.substring(b, b + 2), 16);
a += b64map.charAt(e >> 2) + b64map.charAt((e & 3) << 4)
}
}
while ((a.length & 3) > 0) {
a += b64pad
}
return a
}
function b64tohex(e) {
var c = "";
var d;
var a = 0;
var b;
for (d = 0; d < e.length; ++d) {
if (e.charAt(d) == b64pad) {
break
}
v = b64map.indexOf(e.charAt(d));
if (v < 0) {
continue
}
if (a == 0) {
c += int2char(v >> 2);
b = v & 3;
a = 1
} else {
if (a == 1) {
c += int2char((b << 2) | (v >> 4));
b = v & 15;
a = 2
} else {
if (a == 2) {
c += int2char(b);
c += int2char(v >> 2);
b = v & 3;
a = 3
} else {
c += int2char((b << 2) | (v >> 4));
c += int2char(v & 15);
a = 0
}
}
}
}
if (a == 1) {
c += int2char(b << 2)
}
return c
}
function b64toBA(e) {
var d = b64tohex(e);
var c;
var b = new Array();
for (c = 0; 2 * c < d.length; ++c) {
b[c] = parseInt(d.substring(2 * c, 2 * c + 2), 16)
}
return b
};

感谢原作者https://www.cnblogs.com/xpp142857/p/6994763.html

Jmeter_前端RSA加密下的登陆模拟_引用js文件实现(转)的更多相关文章

  1. Jmeter_前端RSA加密下的登陆模拟_引用js文件实现

    版权声明:本文为博主原创文章,未经博主允许不得转载. 在一次项目实战中,前端登录使用了RSA加密,使用LoadRunner压测的第一步,就是模拟用户登录,可惜loadRunner11并不能录制前端的加 ...

  2. 360浏览器兼容模式下jsp页面访问不到js文件

    360浏览器兼容模式下jsp页面访问不到js文件 查看自己js中的语法问题,不要用ES6的语法,编译不了故找不到js文件 const var of 码出高效 java 比较 所有整型包装类对象之间值的 ...

  3. 个人博客制作如何选择前端模板 thinkcmf后台加载新模板 CSS js文件

    我们的博客后台已经搭建好了,接下来我就要选择一个合适的模板做自己的博客,首先要定位你的博客是做什么用的,是属于什么行业,根据自己博客的定位选择适合的模板. 如果你是设计师,又会前端设计开发,那就可以自 ...

  4. Python3 实现 JS 中 RSA 加密的 NoPadding 模式

    前因后果之哗啦啦废话连篇: 这几天本人在 Python 做某网站登陆的时候,发现其登陆时用户名和密码被加密了 F12 仔细看了一下,发现是调用了一个 js 的 rsa 加密库,页面 dom 中有 rs ...

  5. 【Python3爬虫】破解时光网登录加密参数并实现模拟登录

    一.站点分析 MTime 时光网是一个电影媒体与电商服务平台,而这次做的模拟登录则是依靠其手机端站点,站点地址为:https://m.mtime.cn/#.切换到登录页面,再分别输入账号和错误的密码, ...

  6. springmvc web-info目录下无法引入的js文件无效

    今天在联系spring的时候而然遇到了个不起眼的问题.那就是在html或者说jsp页面中引用js文件的时候总是提示找不到路径.eclipse更是抛出 No mapping to aa.js. 我就奇怪 ...

  7. RSA加密前端JS加密,后端asp.net解密,报异常

    RSA加密前端JS加密,后端asp.net解密,报异常 参考引用:http://www.ohdave.com/rsa/的JS加密库 前端JS加密代码: function GetChangeStr() ...

  8. python RSA加密解密及模拟登录cnblog

    1.公开密钥加密 又称非对称加密,需要一对密钥,一个是私人密钥,另一个则是公开密钥.公钥加密的只能私钥解密,用于加密客户上传数据.私钥加密的数据,公钥可以解密,主要用于数字签名.详细介绍可参见维基百科 ...

  9. RSA加密——前端JSEncrypt

    RSA加密--前端JSEncrypt 介绍 ​ JSEncrypt是一个RSA加密库,在没有SSL加密传输通道支持https协议的情况下,该库可以在http传输重要信息如时,保证数据的安全性.我们小组 ...

随机推荐

  1. Struts2 - 与 Servlet 耦合的访问方式访问web资源

    •       直接访问 Servlet API 将使 Action 与 Servlet 环境耦合在一起,  测试时需要有 Servlet 容器, 不便于对 Action 的单元测试. •       ...

  2. 机器学习:YOLO for Object Detection (一)

    最近看了基于CNN的目标检测另外两篇文章,YOLO v1 和 YOLO v2,与之前的 R-CNN, Fast R-CNN 和 Faster R-CNN 不同,YOLO 将目标检测这个问题重新回到了基 ...

  3. printf 小代码 大问题

    技术 对于我来说 是我前进的动力 虽然有时候感觉会枯燥乏味 不过没关系 放松一下紧张的心态 做一些你能够是你进步的事情  这样 你才会觉得  每天都过得很充实  学海无涯  坚持追求你所想要实现的梦想 ...

  4. bzoj 2565: 最长双回文串 回文自动机

    题目: Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同 ...

  5. P1030 求先序排列

    题目描述 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度<=8). 输入输出格式 输入格式: 2行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序 ...

  6. JS图表工具 ---- Highcharts

    Highcharts 是一个用纯 JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是 web 应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业用途使用. Hi ...

  7. poj 2000 Gold Coins(水题)

    一.Description The king pays his loyal knight in gold coins. On the first day of his service, the kni ...

  8. 加载某个页面(A)时实现自动跳转到某个页面(B)

    <head> <title></title> <script type="text/javascript"> function fu ...

  9. 解决启动SQL Server Management Studio 17时报Cannot find one of more components...的问题

    刚装好SSMS 17.1准备体验,弹出: 一番搜索,普遍办法都是安装VS2015独立shell.删除某个注册表项什么的,没用,首先这个shell我是装了的,然后也没有那个注册表项.我自己尝试过重装sh ...

  10. tar 排除某个目录

    tar -zcvf tomcat.tar.gz --exclude=tomcat/logs --exclude=tomcat/libs tomcat