热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

  版权声明:本文为博主原创文章,未经博主允许不得转载。


 

  在一次项目实战中,前端登录使用了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;

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

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

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

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

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

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

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

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

Jmeter_前端RSA加密下的登陆模拟_引用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中加密的调用实现如下:

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

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

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

【4】调试js文件

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

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

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

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

  ②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的密文已经将“+”及“/”进行了转码,因此最终并未使用替换语句;

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

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

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

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

  总结及感悟:对于前端加密,服务器应该是要返回加密方式给客户端的,否则客户端无从知晓如何加密,至于加密的方式是否可以直接识别,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);

  附2----------sec.min.js修改后的js文件

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 <);
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 <,
 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);
    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 <;
 var f = Math.floor(j / this.DB),
 h = (this.s <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 <;
 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 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 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 < 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 
 //    rng_pool[rng_pptr++] = z.charCodeAt(t) & 255
 //    }
 // }
 // while (rng_pptr 
 //    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_pptr) {
   rng_pool[rng_pptr] = 0
  }
  rng_pptr = 0
 }
 return rng_state.next()
}
function rng_get_bytes(b) {
 var a;
 for (a = 0; a 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 ) {
//    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 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 c) {
  b[c] = parseInt(d.substring(2 * c, 2 * c + 2), 16)
 }
 return b
};

 

  

 


推荐阅读
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
author-avatar
丨丶皓月_261
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有