今天的学习项目:沃支付:https://epay.10010.com/auth/login

  清空浏览器缓存后,打开网页,输入手机号,密码222222,按照网站要求填入验证码(sorry,我没有账号密码,反正是抓包看数据,随便填了)。

  经过多次抓包分析,发现该网站不知道干嘛了,跟小肩膀讲的内容在定位发现略有出入,但幸好,该网站开发人员给留了一条后路。

  话不多说,开始分析网站抓包情况:

  

  从返回是数据包来看,依旧是见名之意的login数据包(我以后也一定会养成这样的好习惯,一定不去写什么怪怪的变量名)

  数据包中,主要看headers和Form表单数据:

  1·其中headers中出现了sec-fetch-dest/sec-fetch-mode/sec-fetch-site/upgrade-insecure-requests这几个一般看不到的变量,考虑在请求的时候加进去;多次抓包没有变化,看来是固定值。

  2·Form表单中,多次抓取发现变量只有一个,即loginPwd,其中显示的一串密文!对loginPwd。

  在小肩膀老师的课程中,login数据包时xhr格式,他是直接通过挂钩的js函数跳到源码中,但今天我做分析的时候,发现该数据包格式变成了other!我没有办法跟前辈课程中那样直接跳转。

  实在无奈,使用老办法,变量名全局搜索,这里发现,无论我是加:,还是=,结果都是找不到数据。

     

  心一横,直接拿loginPwd来搜,出来结果了,但是没有我们熟悉的变量赋值的地方。(这里注意:我在做的时候没问题,但写笔记的时候遇到全局搜索内容不全的情况,这种情况关掉页面重新进入即可,刷新无效。)

  

  但是幸好开发人员写了一句注释“//获得密码密文,赋值给表单”!!!!!!感谢这位大佬,你让我看到了曙光。

  点进去,发现这行上面几行代码就是在处理密码,从明文转密文!

  

  按照我们不多的JS知识,我们知道pwd_val = $("#loginPwd").val(PwdResult);是通过网页标签ID来获取值,很好,打下断点,迅速开始输入账号名/密码/验证码,然后点击登录。顺利暂停流程,他的下一行:PwdResult = encryptRequest(pwd_val, mcrypt_key);根据见名知意的规则,变量即“密码结果”,用一个函数,处理密码,顺便还有个参数是加密钥。原本想先找下加密钥生成的地方,突然下想起来,login 数据包上面有个包,叫getPubKey,...........点进去看了下,好想家,基本一样,但似乎有点区别,仔细对照了一下,发现数据包返回的加密钥前面的“0--”是没用的,拿到之后去掉就是了呗~~~

  

  

  省掉一部分JS代码(开心),那么这地方生成PwdResult的难点就之剩下一个了:encryptRequest函数的具体内容!继续全局搜索,很顺利:点进去看,就四行代码。。。。。。。迅速打开鬼鬼JS调试工具,新建函数,返回加密文,然后在前面先定义下加密钥(搞JS逆向,数据包返回数据的处理基本无难度了吧,密钥我们这里直接先写死,真是模拟登录的时候再去获取,那个包里面的参数是很明显的一个时间戳)

          

  紧接着把encryptRequest加载上去。加载后发现,encryptRequest函数中又调用了一个JSEncrypt函数,好消息是这个函数没有参数,不需要找变量,那么搜一下这个函数,发现就在这个文件里面,而且,遍布了整个文件,文件的第一行有一句:“/*! JSEncrypt v2.3.1 | https://npmcdn.com/jsencrypt@2.3.1/LICENSE.txt */”;再检查下函数之间的调用问题,合着整个文件都是互相依赖的文件(以前也遇到过)。全部拿走,放在以后JS函数的最前面。

  加载会提示 navigator 未定义,这个是浏览器的数据,根据前辈们经验,定义为{},即:var navigator = {};

  再加载提示 window 未定义,这个是全局环境,根据前辈们经验,定位为this,就是当前的全局环境,即: var window = this;

  然后就是=====> 加载成功!运行成功,返回与数据包类数据格式一致的数据!python调用JS的函数基本都是一个套路。完结撒花~~~~~

  

  但事实往往很残酷,我在写python调用的时候遇到一个情况:

  

  这就很离谱!!!!这个函数我专门去抠了代码的,凭什么未定义!!!鬼鬼JS工具都正常,凭啥你这出问题?!!在多次查错未果后,我确定代码没问题~~~~那么问题在哪儿?未定义的情况无非两种,一种确实没有,一种调用的时候,该函数还没有被创建!第一条不存在,代码里面写的明明白白,那么会不会是第二条原因呢,我尝试着JSEncrypt定义函数剪到了文件最前端。好了~~~没事了......(事到如今,我还是要说一句,不科学!)

  注意:

  本代码仅针对loginPwd做出逆向,所需的加密钥未在JS中出现,而是在python代码中写死,如果需要调用,请自行通过方法获取加密钥数据。

  具体代码如下(包括思路和注释),JS文件未作特别说明(这份JS抠的简单)

  python:

 1 '''
2 今天的学习项目:沃支付:https://epay.10010.com/auth/login
3 经过多次抓包分析,发现该网站不知道干嘛了,跟小肩膀讲的内容在定位发现略有出入,但幸好,该网站开发人员给留了一条后路。
4 话不多说,开始分析网站抓包情况:
5 从返回是数据包来看,依旧是见名之意的login数据包(我以后也一定会养成这样的好习惯,一定不去写什么怪怪的变量名)
6 数据包中,主要看headers和Form表单数据:
7 1·其中headers中出现了sec-fetch-dest/sec-fetch-mode/sec-fetch-site/upgrade-insecure-requests这几个一般看不到的变量,考虑在请求的时候加进去;多次抓包没有变化,看来是固定值。
8 2·Form表单中,多次抓取发现变量只有一个,即loginPwd,其中显示的一串密文!对loginPwd。
9 在小肩膀老师的课程中,login数据包时xhr格式,他是直接通过挂钩的js函数跳到源码中,但今天我做分析的时候,发现该数据包格式变成了other!我没有办法跟前辈课程中那样直接跳转。
10 实在无奈,使用老办法,变量名全局搜索,这里发现,无论我是加:,还是=,结果都是找不到数据,心一横,直接拿loginPwd来搜,出来结果了,但是没有我们熟悉的变量赋值的地方。
11 但是幸好开发人员写了一句注释“//获得密码密文,赋值给表单”!!!!!!感谢这位大佬,你让我看到了曙光。
12 点进去,发现这行上面就是在处理密码,从明文转密文!
13 按照我们不多的JS知识,我们知道pwd_val = $("#loginPwd").val(PwdResult);是通过网页标签ID来获取值,很好,打下断点,迅速开始输入账号名/密码/验证码,然后点击登录。
14 顺利暂停流程,他的下一行:PwdResult = encryptRequest(pwd_val, mcrypt_key);根据见名知意的规则,变量即“密码结果”,用一个函数,处理密码,顺便还有个参数是加密钥
15 原本想先找下加密钥生成的地方,突然下想起来,login 数据包上面有个包,叫getPubKey,...........点进去看了下,好想家,基本一样,但似乎有点区别,仔细对照了一下,发现数据包返回的加密钥前面的“0--”是没用的,拿到之后去掉就是了呗~~~
16 省掉一部分JS代码(开心),那么这地方生成PwdResult的难点就之剩下一个了:encryptRequest函数的具体内容!
17 继续全局搜索,很顺利:点进去看,就四行代码。。。。。。。
18 迅速打开鬼鬼JS调试工具,新建函数,返回加密文,然后在前面先定义下加密钥(搞JS逆向,数据包返回数据的处理基本无难度了吧)
19
20 紧接着把encryptRequest加载上去。加载后发现,encryptRequest函数中又调用了一个JSEncrypt函数,好消息是这个函数没有参数,不需要找变量,那么搜一下这个函数,发现就在这个文件里面,而且,遍布了整个文件,文件的第一行有一句:“/*! JSEncrypt v2.3.1 | https://npmcdn.com/jsencrypt@2.3.1/LICENSE.txt */”
21 再检查下函数之间的调用问题,合着整个文件都是互相依赖的文件(前面也遇到过)。全部拿走,放在前面.
22 加载会提示 navigator 未定义,这个是浏览器的数据,根据前辈们经验,定义为{},即:var navigator = {};
23 再加载提示 window 未定义,这个是全局环境,根据前辈们经验,定位为this,就是当前的全局环境,即: var window = this;
24 然后就是=====> 加载成功!运行成功,返回与数据包类数据格式一致的数据!
25 python调用JS的函数基本都是一个套路。
26 注意:
27 本代码仅针对loginPwd做出逆向,所需的加密钥未在JS中出现,而是在python代码中写死,如果需要调用,请自行通过方法获取加密钥数据。
28 '''
29
30 import execjs
31
32
33 def read_js(file):
34 with open(file, 'r', encoding='utf8') as f:
35 js_data = f.read()
36 return js_data
37
38 if __name__ == '__main__':
39 # 先读取js文件
40
41 pubkey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCSQuMD7O2Vfh3nJgxOR7c3rKJKbqfQiSw+mqVmCaoXli2YOqI8nWstpdQFpXGfpGVfO+M8Zyekfa2rJGGtbpftqiFMhbYFak+mtfhNIxbobxLivofpfzu17plYywokresdD+tfEbd4uoyQamG7zlQzd1ZdUspw57VeB5tKbrPstQIDAQAB'
42 js_r = read_js('wopay.js')
43 # 使用execjs方法获取js文件内容
44 js_o = execjs.compile(js_r)
45
46 # call方法调用函数,参数:函数名, 参数值
47 _pwd = js_o.call('test', '222222', pubkey)
48 print(_pwd)

pyhton代码部分

  JScrapyt

   1 var navigator = {};
2 var window = this;
3
4
5 var JSEncrypt = function(options) {
6 options = options || {};
7 this.default_key_size = parseInt(options.default_key_size) || 1024;
8 this.default_public_exponent = options.default_public_exponent || '010001'; //65537 default openssl public exponent for rsa key type
9 this.log = options.log || false;
10 // The private and public key.
11 this.key = null;
12 };
13 /*! JSEncrypt v2.3.1 | https://npmcdn.com/jsencrypt@2.3.1/LICENSE.txt */
14 (function(root, factory) {
15 if (typeof define === 'function' && define.amd) {
16 // AMD
17 define(['exports'], factory);
18 } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
19 // Node, CommonJS-like
20 factory(module.exports);
21 } else {
22 factory(root);
23 }
24 })(this,
25 function(exports) {
26 // Copyright (c) 2005 Tom Wu
27 // All Rights Reserved.
28 // See "LICENSE" for details.
29 // Basic JavaScript BN library - subset useful for RSA encryption.
30 // Bits per digit
31 var dbits;
32
33 // JavaScript engine analysis
34 var canary = 0xdeadbeefcafe;
35 var j_lm = ((canary & 0xffffff) == 0xefcafe);
36
37 // (public) Constructor
38 function BigInteger(a, b, c) {
39 if (a != null) if ("number" == typeof a) this.fromNumber(a, b, c);
40 else if (b == null && "string" != typeof a) this.fromString(a, 256);
41 else this.fromString(a, b);
42 }
43
44 // return new, unset BigInteger
45 function nbi() {
46 return new BigInteger(null);
47 }
48
49 // am: Compute w_j += (x*this_i), propagate carries,
50 // c is initial carry, returns final carry.
51 // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
52 // We need to select the fastest one that works in this environment.
53 // am1: use a single mult and divide to get the high bits,
54 // max digit bits should be 26 because
55 // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
56 function am1(i, x, w, j, c, n) {
57 while (--n >= 0) {
58 var v = x * this[i++] + w[j] + c;
59 c = Math.floor(v / 0x4000000);
60 w[j++] = v & 0x3ffffff;
61 }
62 return c;
63 }
64 // am2 avoids a big mult-and-extract completely.
65 // Max digit bits should be <= 30 because we do bitwise ops
66 // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
67 function am2(i, x, w, j, c, n) {
68 var xl = x & 0x7fff,
69 xh = x >> 15;
70 while (--n >= 0) {
71 var l = this[i] & 0x7fff;
72 var h = this[i++] >> 15;
73 var m = xh * l + h * xl;
74 l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff);
75 c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30);
76 w[j++] = l & 0x3fffffff;
77 }
78 return c;
79 }
80 // Alternately, set max digit bits to 28 since some
81 // browsers slow down when dealing with 32-bit numbers.
82 function am3(i, x, w, j, c, n) {
83 var xl = x & 0x3fff,
84 xh = x >> 14;
85 while (--n >= 0) {
86 var l = this[i] & 0x3fff;
87 var h = this[i++] >> 14;
88 var m = xh * l + h * xl;
89 l = xl * l + ((m & 0x3fff) << 14) + w[j] + c;
90 c = (l >> 28) + (m >> 14) + xh * h;
91 w[j++] = l & 0xfffffff;
92 }
93 return c;
94 }
95 if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
96 BigInteger.prototype.am = am2;
97 dbits = 30;
98 } else if (j_lm && (navigator.appName != "Netscape")) {
99 BigInteger.prototype.am = am1;
100 dbits = 26;
101 } else { // Mozilla/Netscape seems to prefer am3
102 BigInteger.prototype.am = am3;
103 dbits = 28;
104 }
105
106 BigInteger.prototype.DB = dbits;
107 BigInteger.prototype.DM = ((1 << dbits) - 1);
108 BigInteger.prototype.DV = (1 << dbits);
109
110 var BI_FP = 52;
111 BigInteger.prototype.FV = Math.pow(2, BI_FP);
112 BigInteger.prototype.F1 = BI_FP - dbits;
113 BigInteger.prototype.F2 = 2 * dbits - BI_FP;
114
115 // Digit conversions
116 var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
117 var BI_RC = new Array();
118 var rr, vv;
119 rr = "0".charCodeAt(0);
120 for (vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
121 rr = "a".charCodeAt(0);
122 for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
123 rr = "A".charCodeAt(0);
124 for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
125
126 function int2char(n) {
127 return BI_RM.charAt(n);
128 }
129 function intAt(s, i) {
130 var c = BI_RC[s.charCodeAt(i)];
131 return (c == null) ? -1 : c;
132 }
133
134 // (protected) copy this to r
135 function bnpCopyTo(r) {
136 for (var i = this.t - 1; i >= 0; --i) r[i] = this[i];
137 r.t = this.t;
138 r.s = this.s;
139 }
140
141 // (protected) set from integer value x, -DV <= x < DV
142 function bnpFromInt(x) {
143 this.t = 1;
144 this.s = (x < 0) ? -1 : 0;
145 if (x > 0) this[0] = x;
146 else if (x < -1) this[0] = x + this.DV;
147 else this.t = 0;
148 }
149
150 // return bigint initialized to value
151 function nbv(i) {
152 var r = nbi();
153 r.fromInt(i);
154 return r;
155 }
156
157 // (protected) set from string and radix
158 function bnpFromString(s, b) {
159 var k;
160 if (b == 16) k = 4;
161 else if (b == 8) k = 3;
162 else if (b == 256) k = 8; // byte array
163 else if (b == 2) k = 1;
164 else if (b == 32) k = 5;
165 else if (b == 4) k = 2;
166 else {
167 this.fromRadix(s, b);
168 return;
169 }
170 this.t = 0;
171 this.s = 0;
172 var i = s.length,
173 mi = false,
174 sh = 0;
175 while (--i >= 0) {
176 var x = (k == 8) ? s[i] & 0xff: intAt(s, i);
177 if (x < 0) {
178 if (s.charAt(i) == "-") mi = true;
179 continue;
180 }
181 mi = false;
182 if (sh == 0) this[this.t++] = x;
183 else if (sh + k > this.DB) {
184 this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh;
185 this[this.t++] = (x >> (this.DB - sh));
186 } else this[this.t - 1] |= x << sh;
187 sh += k;
188 if (sh >= this.DB) sh -= this.DB;
189 }
190 if (k == 8 && (s[0] & 0x80) != 0) {
191 this.s = -1;
192 if (sh > 0) this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh;
193 }
194 this.clamp();
195 if (mi) BigInteger.ZERO.subTo(this, this);
196 }
197
198 // (protected) clamp off excess high words
199 function bnpClamp() {
200 var c = this.s & this.DM;
201 while (this.t > 0 && this[this.t - 1] == c)--this.t;
202 }
203
204 // (public) return string representation in given radix
205 function bnToString(b) {
206 if (this.s < 0) return "-" + this.negate().toString(b);
207 var k;
208 if (b == 16) k = 4;
209 else if (b == 8) k = 3;
210 else if (b == 2) k = 1;
211 else if (b == 32) k = 5;
212 else if (b == 4) k = 2;
213 else return this.toRadix(b);
214 var km = (1 << k) - 1,
215 d,
216 m = false,
217 r = "",
218 i = this.t;
219 var p = this.DB - (i * this.DB) % k;
220 if (i-->0) {
221 if (p < this.DB && (d = this[i] >> p) > 0) {
222 m = true;
223 r = int2char(d);
224 }
225 while (i >= 0) {
226 if (p < k) {
227 d = (this[i] & ((1 << p) - 1)) << (k - p);
228 d |= this[--i] >> (p += this.DB - k);
229 } else {
230 d = (this[i] >> (p -= k)) & km;
231 if (p <= 0) {
232 p += this.DB; --i;
233 }
234 }
235 if (d > 0) m = true;
236 if (m) r += int2char(d);
237 }
238 }
239 return m ? r: "0";
240 }
241
242 // (public) -this
243 function bnNegate() {
244 var r = nbi();
245 BigInteger.ZERO.subTo(this, r);
246 return r;
247 }
248
249 // (public) |this|
250 function bnAbs() {
251 return (this.s < 0) ? this.negate() : this;
252 }
253
254 // (public) return + if this > a, - if this < a, 0 if equal
255 function bnCompareTo(a) {
256 var r = this.s - a.s;
257 if (r != 0) return r;
258 var i = this.t;
259 r = i - a.t;
260 if (r != 0) return (this.s < 0) ? -r: r;
261 while (--i >= 0) if ((r = this[i] - a[i]) != 0) return r;
262 return 0;
263 }
264
265 // returns bit length of the integer x
266 function nbits(x) {
267 var r = 1,
268 t;
269 if ((t = x >>> 16) != 0) {
270 x = t;
271 r += 16;
272 }
273 if ((t = x >> 8) != 0) {
274 x = t;
275 r += 8;
276 }
277 if ((t = x >> 4) != 0) {
278 x = t;
279 r += 4;
280 }
281 if ((t = x >> 2) != 0) {
282 x = t;
283 r += 2;
284 }
285 if ((t = x >> 1) != 0) {
286 x = t;
287 r += 1;
288 }
289 return r;
290 }
291
292 // (public) return the number of bits in "this"
293 function bnBitLength() {
294 if (this.t <= 0) return 0;
295 return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM));
296 }
297
298 // (protected) r = this << n*DB
299 function bnpDLShiftTo(n, r) {
300 var i;
301 for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i];
302 for (i = n - 1; i >= 0; --i) r[i] = 0;
303 r.t = this.t + n;
304 r.s = this.s;
305 }
306
307 // (protected) r = this >> n*DB
308 function bnpDRShiftTo(n, r) {
309 for (var i = n; i < this.t; ++i) r[i - n] = this[i];
310 r.t = Math.max(this.t - n, 0);
311 r.s = this.s;
312 }
313
314 // (protected) r = this << n
315 function bnpLShiftTo(n, r) {
316 var bs = n % this.DB;
317 var cbs = this.DB - bs;
318 var bm = (1 << cbs) - 1;
319 var ds = Math.floor(n / this.DB),
320 c = (this.s << bs) & this.DM,
321 i;
322 for (i = this.t - 1; i >= 0; --i) {
323 r[i + ds + 1] = (this[i] >> cbs) | c;
324 c = (this[i] & bm) << bs;
325 }
326 for (i = ds - 1; i >= 0; --i) r[i] = 0;
327 r[ds] = c;
328 r.t = this.t + ds + 1;
329 r.s = this.s;
330 r.clamp();
331 }
332
333 // (protected) r = this >> n
334 function bnpRShiftTo(n, r) {
335 r.s = this.s;
336 var ds = Math.floor(n / this.DB);
337 if (ds >= this.t) {
338 r.t = 0;
339 return;
340 }
341 var bs = n % this.DB;
342 var cbs = this.DB - bs;
343 var bm = (1 << bs) - 1;
344 r[0] = this[ds] >> bs;
345 for (var i = ds + 1; i < this.t; ++i) {
346 r[i - ds - 1] |= (this[i] & bm) << cbs;
347 r[i - ds] = this[i] >> bs;
348 }
349 if (bs > 0) r[this.t - ds - 1] |= (this.s & bm) << cbs;
350 r.t = this.t - ds;
351 r.clamp();
352 }
353
354 // (protected) r = this - a
355 function bnpSubTo(a, r) {
356 var i = 0,
357 c = 0,
358 m = Math.min(a.t, this.t);
359 while (i < m) {
360 c += this[i] - a[i];
361 r[i++] = c & this.DM;
362 c >>= this.DB;
363 }
364 if (a.t < this.t) {
365 c -= a.s;
366 while (i < this.t) {
367 c += this[i];
368 r[i++] = c & this.DM;
369 c >>= this.DB;
370 }
371 c += this.s;
372 } else {
373 c += this.s;
374 while (i < a.t) {
375 c -= a[i];
376 r[i++] = c & this.DM;
377 c >>= this.DB;
378 }
379 c -= a.s;
380 }
381 r.s = (c < 0) ? -1 : 0;
382 if (c < -1) r[i++] = this.DV + c;
383 else if (c > 0) r[i++] = c;
384 r.t = i;
385 r.clamp();
386 }
387
388 // (protected) r = this * a, r != this,a (HAC 14.12)
389 // "this" should be the larger one if appropriate.
390 function bnpMultiplyTo(a, r) {
391 var x = this.abs(),
392 y = a.abs();
393 var i = x.t;
394 r.t = i + y.t;
395 while (--i >= 0) r[i] = 0;
396 for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t);
397 r.s = 0;
398 r.clamp();
399 if (this.s != a.s) BigInteger.ZERO.subTo(r, r);
400 }
401
402 // (protected) r = this^2, r != this (HAC 14.16)
403 function bnpSquareTo(r) {
404 var x = this.abs();
405 var i = r.t = 2 * x.t;
406 while (--i >= 0) r[i] = 0;
407 for (i = 0; i < x.t - 1; ++i) {
408 var c = x.am(i, x[i], r, 2 * i, 0, 1);
409 if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) {
410 r[i + x.t] -= x.DV;
411 r[i + x.t + 1] = 1;
412 }
413 }
414 if (r.t > 0) r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1);
415 r.s = 0;
416 r.clamp();
417 }
418
419 // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
420 // r != q, this != m. q or r may be null.
421 function bnpDivRemTo(m, q, r) {
422 var pm = m.abs();
423 if (pm.t <= 0) return;
424 var pt = this.abs();
425 if (pt.t < pm.t) {
426 if (q != null) q.fromInt(0);
427 if (r != null) this.copyTo(r);
428 return;
429 }
430 if (r == null) r = nbi();
431 var y = nbi(),
432 ts = this.s,
433 ms = m.s;
434 var nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus
435 if (nsh > 0) {
436 pm.lShiftTo(nsh, y);
437 pt.lShiftTo(nsh, r);
438 } else {
439 pm.copyTo(y);
440 pt.copyTo(r);
441 }
442 var ys = y.t;
443 var y0 = y[ys - 1];
444 if (y0 == 0) return;
445 var yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2: 0);
446 var d1 = this.FV / yt,
447 d2 = (1 << this.F1) / yt,
448 e = 1 << this.F2;
449 var i = r.t,
450 j = i - ys,
451 t = (q == null) ? nbi() : q;
452 y.dlShiftTo(j, t);
453 if (r.compareTo(t) >= 0) {
454 r[r.t++] = 1;
455 r.subTo(t, r);
456 }
457 BigInteger.ONE.dlShiftTo(ys, t);
458 t.subTo(y, y); // "negative" y so we can replace sub with am later
459 while (y.t < ys) y[y.t++] = 0;
460 while (--j >= 0) {
461 // Estimate quotient digit
462 var qd = (r[--i] == y0) ? this.DM: Math.floor(r[i] * d1 + (r[i - 1] + e) * d2);
463 if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out
464 y.dlShiftTo(j, t);
465 r.subTo(t, r);
466 while (r[i] < --qd) r.subTo(t, r);
467 }
468 }
469 if (q != null) {
470 r.drShiftTo(ys, q);
471 if (ts != ms) BigInteger.ZERO.subTo(q, q);
472 }
473 r.t = ys;
474 r.clamp();
475 if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder
476 if (ts < 0) BigInteger.ZERO.subTo(r, r);
477 }
478
479 // (public) this mod a
480 function bnMod(a) {
481 var r = nbi();
482 this.abs().divRemTo(a, null, r);
483 if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r);
484 return r;
485 }
486
487 // Modular reduction using "classic" algorithm
488 function Classic(m) {
489 this.m = m;
490 }
491 function cConvert(x) {
492 if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
493 else return x;
494 }
495 function cRevert(x) {
496 return x;
497 }
498 function cReduce(x) {
499 x.divRemTo(this.m, null, x);
500 }
501 function cMulTo(x, y, r) {
502 x.multiplyTo(y, r);
503 this.reduce(r);
504 }
505 function cSqrTo(x, r) {
506 x.squareTo(r);
507 this.reduce(r);
508 }
509
510 Classic.prototype.convert = cConvert;
511 Classic.prototype.revert = cRevert;
512 Classic.prototype.reduce = cReduce;
513 Classic.prototype.mulTo = cMulTo;
514 Classic.prototype.sqrTo = cSqrTo;
515
516 // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
517 // justification:
518 // xy == 1 (mod m)
519 // xy = 1+km
520 // xy(2-xy) = (1+km)(1-km)
521 // x[y(2-xy)] = 1-k^2m^2
522 // x[y(2-xy)] == 1 (mod m^2)
523 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
524 // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
525 // JS multiply "overflows" differently from C/C++, so care is needed here.
526 function bnpInvDigit() {
527 if (this.t < 1) return 0;
528 var x = this[0];
529 if ((x & 1) == 0) return 0;
530 var y = x & 3; // y == 1/x mod 2^2
531 y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
532 y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
533 y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
534 // last step - calculate inverse mod DV directly;
535 // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
536 y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits
537 // we really want the negative inverse, and -DV < y < DV
538 return (y > 0) ? this.DV - y: -y;
539 }
540
541 // Montgomery reduction
542 function Montgomery(m) {
543 this.m = m;
544 this.mp = m.invDigit();
545 this.mpl = this.mp & 0x7fff;
546 this.mph = this.mp >> 15;
547 this.um = (1 << (m.DB - 15)) - 1;
548 this.mt2 = 2 * m.t;
549 }
550
551 // xR mod m
552 function montConvert(x) {
553 var r = nbi();
554 x.abs().dlShiftTo(this.m.t, r);
555 r.divRemTo(this.m, null, r);
556 if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r);
557 return r;
558 }
559
560 // x/R mod m
561 function montRevert(x) {
562 var r = nbi();
563 x.copyTo(r);
564 this.reduce(r);
565 return r;
566 }
567
568 // x = x/R mod m (HAC 14.32)
569 function montReduce(x) {
570 while (x.t <= this.mt2) // pad x so am has enough room later
571 x[x.t++] = 0;
572 for (var i = 0; i < this.m.t; ++i) {
573 // faster way of calculating u0 = x[i]*mp mod DV
574 var j = x[i] & 0x7fff;
575 var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM;
576 // use am to combine the multiply-shift-add into one call
577 j = i + this.m.t;
578 x[j] += this.m.am(0, u0, x, i, 0, this.m.t);
579 // propagate carry
580 while (x[j] >= x.DV) {
581 x[j] -= x.DV;
582 x[++j]++;
583 }
584 }
585 x.clamp();
586 x.drShiftTo(this.m.t, x);
587 if (x.compareTo(this.m) >= 0) x.subTo(this.m, x);
588 }
589
590 // r = "x^2/R mod m"; x != r
591 function montSqrTo(x, r) {
592 x.squareTo(r);
593 this.reduce(r);
594 }
595
596 // r = "xy/R mod m"; x,y != r
597 function montMulTo(x, y, r) {
598 x.multiplyTo(y, r);
599 this.reduce(r);
600 }
601
602 Montgomery.prototype.convert = montConvert;
603 Montgomery.prototype.revert = montRevert;
604 Montgomery.prototype.reduce = montReduce;
605 Montgomery.prototype.mulTo = montMulTo;
606 Montgomery.prototype.sqrTo = montSqrTo;
607
608 // (protected) true iff this is even
609 function bnpIsEven() {
610 return ((this.t > 0) ? (this[0] & 1) : this.s) == 0;
611 }
612
613 // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
614 function bnpExp(e, z) {
615 if (e > 0xffffffff || e < 1) return BigInteger.ONE;
616 var r = nbi(),
617 r2 = nbi(),
618 g = z.convert(this),
619 i = nbits(e) - 1;
620 g.copyTo(r);
621 while (--i >= 0) {
622 z.sqrTo(r, r2);
623 if ((e & (1 << i)) > 0) z.mulTo(r2, g, r);
624 else {
625 var t = r;
626 r = r2;
627 r2 = t;
628 }
629 }
630 return z.revert(r);
631 }
632
633 // (public) this^e % m, 0 <= e < 2^32
634 function bnModPowInt(e, m) {
635 var z;
636 if (e < 256 || m.isEven()) z = new Classic(m);
637 else z = new Montgomery(m);
638 return this.exp(e, z);
639 }
640
641 // protected
642 BigInteger.prototype.copyTo = bnpCopyTo;
643 BigInteger.prototype.fromInt = bnpFromInt;
644 BigInteger.prototype.fromString = bnpFromString;
645 BigInteger.prototype.clamp = bnpClamp;
646 BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
647 BigInteger.prototype.drShiftTo = bnpDRShiftTo;
648 BigInteger.prototype.lShiftTo = bnpLShiftTo;
649 BigInteger.prototype.rShiftTo = bnpRShiftTo;
650 BigInteger.prototype.subTo = bnpSubTo;
651 BigInteger.prototype.multiplyTo = bnpMultiplyTo;
652 BigInteger.prototype.squareTo = bnpSquareTo;
653 BigInteger.prototype.divRemTo = bnpDivRemTo;
654 BigInteger.prototype.invDigit = bnpInvDigit;
655 BigInteger.prototype.isEven = bnpIsEven;
656 BigInteger.prototype.exp = bnpExp;
657
658 // public
659 BigInteger.prototype.toString = bnToString;
660 BigInteger.prototype.negate = bnNegate;
661 BigInteger.prototype.abs = bnAbs;
662 BigInteger.prototype.compareTo = bnCompareTo;
663 BigInteger.prototype.bitLength = bnBitLength;
664 BigInteger.prototype.mod = bnMod;
665 BigInteger.prototype.modPowInt = bnModPowInt;
666
667 // "constants"
668 BigInteger.ZERO = nbv(0);
669 BigInteger.ONE = nbv(1);
670
671 // Copyright (c) 2005-2009 Tom Wu
672 // All Rights Reserved.
673 // See "LICENSE" for details.
674 // Extended JavaScript BN functions, required for RSA private ops.
675 // Version 1.1: new BigInteger("0", 10) returns "proper" zero
676 // Version 1.2: square() API, isProbablePrime fix
677 // (public)
678 function bnClone() {
679 var r = nbi();
680 this.copyTo(r);
681 return r;
682 }
683
684 // (public) return value as integer
685 function bnIntValue() {
686 if (this.s < 0) {
687 if (this.t == 1) return this[0] - this.DV;
688 else if (this.t == 0) return - 1;
689 } else if (this.t == 1) return this[0];
690 else if (this.t == 0) return 0;
691 // assumes 16 < DB < 32
692 return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0];
693 }
694
695 // (public) return value as byte
696 function bnByteValue() {
697 return (this.t == 0) ? this.s: (this[0] << 24) >> 24;
698 }
699
700 // (public) return value as short (assumes DB>=16)
701 function bnShortValue() {
702 return (this.t == 0) ? this.s: (this[0] << 16) >> 16;
703 }
704
705 // (protected) return x s.t. r^x < DV
706 function bnpChunkSize(r) {
707 return Math.floor(Math.LN2 * this.DB / Math.log(r));
708 }
709
710 // (public) 0 if this == 0, 1 if this > 0
711 function bnSigNum() {
712 if (this.s < 0) return - 1;
713 else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
714 else return 1;
715 }
716
717 // (protected) convert to radix string
718 function bnpToRadix(b) {
719 if (b == null) b = 10;
720 if (this.signum() == 0 || b < 2 || b > 36) return "0";
721 var cs = this.chunkSize(b);
722 var a = Math.pow(b, cs);
723 var d = nbv(a),
724 y = nbi(),
725 z = nbi(),
726 r = "";
727 this.divRemTo(d, y, z);
728 while (y.signum() > 0) {
729 r = (a + z.intValue()).toString(b).substr(1) + r;
730 y.divRemTo(d, y, z);
731 }
732 return z.intValue().toString(b) + r;
733 }
734
735 // (protected) convert from radix string
736 function bnpFromRadix(s, b) {
737 this.fromInt(0);
738 if (b == null) b = 10;
739 var cs = this.chunkSize(b);
740 var d = Math.pow(b, cs),
741 mi = false,
742 j = 0,
743 w = 0;
744 for (var i = 0; i < s.length; ++i) {
745 var x = intAt(s, i);
746 if (x < 0) {
747 if (s.charAt(i) == "-" && this.signum() == 0) mi = true;
748 continue;
749 }
750 w = b * w + x;
751 if (++j >= cs) {
752 this.dMultiply(d);
753 this.dAddOffset(w, 0);
754 j = 0;
755 w = 0;
756 }
757 }
758 if (j > 0) {
759 this.dMultiply(Math.pow(b, j));
760 this.dAddOffset(w, 0);
761 }
762 if (mi) BigInteger.ZERO.subTo(this, this);
763 }
764
765 // (protected) alternate constructor
766 function bnpFromNumber(a, b, c) {
767 if ("number" == typeof b) {
768 // new BigInteger(int,int,RNG)
769 if (a < 2) this.fromInt(1);
770 else {
771 this.fromNumber(a, c);
772 if (!this.testBit(a - 1)) // force MSB set
773 this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this);
774 if (this.isEven()) this.dAddOffset(1, 0); // force odd
775 while (!this.isProbablePrime(b)) {
776 this.dAddOffset(2, 0);
777 if (this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a - 1), this);
778 }
779 }
780 } else {
781 // new BigInteger(int,RNG)
782 var x = new Array(),
783 t = a & 7;
784 x.length = (a >> 3) + 1;
785 b.nextBytes(x);
786 if (t > 0) x[0] &= ((1 << t) - 1);
787 else x[0] = 0;
788 this.fromString(x, 256);
789 }
790 }
791
792 // (public) convert to bigendian byte array
793 function bnToByteArray() {
794 var i = this.t,
795 r = new Array();
796 r[0] = this.s;
797 var p = this.DB - (i * this.DB) % 8,
798 d,
799 k = 0;
800 if (i-->0) {
801 if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p) r[k++] = d | (this.s << (this.DB - p));
802 while (i >= 0) {
803 if (p < 8) {
804 d = (this[i] & ((1 << p) - 1)) << (8 - p);
805 d |= this[--i] >> (p += this.DB - 8);
806 } else {
807 d = (this[i] >> (p -= 8)) & 0xff;
808 if (p <= 0) {
809 p += this.DB; --i;
810 }
811 }
812 if ((d & 0x80) != 0) d |= -256;
813 if (k == 0 && (this.s & 0x80) != (d & 0x80))++k;
814 if (k > 0 || d != this.s) r[k++] = d;
815 }
816 }
817 return r;
818 }
819
820 function bnEquals(a) {
821 return (this.compareTo(a) == 0);
822 }
823 function bnMin(a) {
824 return (this.compareTo(a) < 0) ? this: a;
825 }
826 function bnMax(a) {
827 return (this.compareTo(a) > 0) ? this: a;
828 }
829
830 // (protected) r = this op a (bitwise)
831 function bnpBitwiseTo(a, op, r) {
832 var i, f, m = Math.min(a.t, this.t);
833 for (i = 0; i < m; ++i) r[i] = op(this[i], a[i]);
834 if (a.t < this.t) {
835 f = a.s & this.DM;
836 for (i = m; i < this.t; ++i) r[i] = op(this[i], f);
837 r.t = this.t;
838 } else {
839 f = this.s & this.DM;
840 for (i = m; i < a.t; ++i) r[i] = op(f, a[i]);
841 r.t = a.t;
842 }
843 r.s = op(this.s, a.s);
844 r.clamp();
845 }
846
847 // (public) this & a
848 function op_and(x, y) {
849 return x & y;
850 }
851 function bnAnd(a) {
852 var r = nbi();
853 this.bitwiseTo(a, op_and, r);
854 return r;
855 }
856
857 // (public) this | a
858 function op_or(x, y) {
859 return x | y;
860 }
861 function bnOr(a) {
862 var r = nbi();
863 this.bitwiseTo(a, op_or, r);
864 return r;
865 }
866
867 // (public) this ^ a
868 function op_xor(x, y) {
869 return x ^ y;
870 }
871 function bnXor(a) {
872 var r = nbi();
873 this.bitwiseTo(a, op_xor, r);
874 return r;
875 }
876
877 // (public) this & ~a
878 function op_andnot(x, y) {
879 return x & ~y;
880 }
881 function bnAndNot(a) {
882 var r = nbi();
883 this.bitwiseTo(a, op_andnot, r);
884 return r;
885 }
886
887 // (public) ~this
888 function bnNot() {
889 var r = nbi();
890 for (var i = 0; i < this.t; ++i) r[i] = this.DM & ~this[i];
891 r.t = this.t;
892 r.s = ~this.s;
893 return r;
894 }
895
896 // (public) this << n
897 function bnShiftLeft(n) {
898 var r = nbi();
899 if (n < 0) this.rShiftTo( - n, r);
900 else this.lShiftTo(n, r);
901 return r;
902 }
903
904 // (public) this >> n
905 function bnShiftRight(n) {
906 var r = nbi();
907 if (n < 0) this.lShiftTo( - n, r);
908 else this.rShiftTo(n, r);
909 return r;
910 }
911
912 // return index of lowest 1-bit in x, x < 2^31
913 function lbit(x) {
914 if (x == 0) return - 1;
915 var r = 0;
916 if ((x & 0xffff) == 0) {
917 x >>= 16;
918 r += 16;
919 }
920 if ((x & 0xff) == 0) {
921 x >>= 8;
922 r += 8;
923 }
924 if ((x & 0xf) == 0) {
925 x >>= 4;
926 r += 4;
927 }
928 if ((x & 3) == 0) {
929 x >>= 2;
930 r += 2;
931 }
932 if ((x & 1) == 0)++r;
933 return r;
934 }
935
936 // (public) returns index of lowest 1-bit (or -1 if none)
937 function bnGetLowestSetBit() {
938 for (var i = 0; i < this.t; ++i) if (this[i] != 0) return i * this.DB + lbit(this[i]);
939 if (this.s < 0) return this.t * this.DB;
940 return - 1;
941 }
942
943 // return number of 1 bits in x
944 function cbit(x) {
945 var r = 0;
946 while (x != 0) {
947 x &= x - 1; ++r;
948 }
949 return r;
950 }
951
952 // (public) return number of set bits
953 function bnBitCount() {
954 var r = 0,
955 x = this.s & this.DM;
956 for (var i = 0; i < this.t; ++i) r += cbit(this[i] ^ x);
957 return r;
958 }
959
960 // (public) true iff nth bit is set
961 function bnTestBit(n) {
962 var j = Math.floor(n / this.DB);
963 if (j >= this.t) return (this.s != 0);
964 return ((this[j] & (1 << (n % this.DB))) != 0);
965 }
966
967 // (protected) this op (1<<n)
968 function bnpChangeBit(n, op) {
969 var r = BigInteger.ONE.shiftLeft(n);
970 this.bitwiseTo(r, op, r);
971 return r;
972 }
973
974 // (public) this | (1<<n)
975 function bnSetBit(n) {
976 return this.changeBit(n, op_or);
977 }
978
979 // (public) this & ~(1<<n)
980 function bnClearBit(n) {
981 return this.changeBit(n, op_andnot);
982 }
983
984 // (public) this ^ (1<<n)
985 function bnFlipBit(n) {
986 return this.changeBit(n, op_xor);
987 }
988
989 // (protected) r = this + a
990 function bnpAddTo(a, r) {
991 var i = 0,
992 c = 0,
993 m = Math.min(a.t, this.t);
994 while (i < m) {
995 c += this[i] + a[i];
996 r[i++] = c & this.DM;
997 c >>= this.DB;
998 }
999 if (a.t < this.t) {
1000 c += a.s;
1001 while (i < this.t) {
1002 c += this[i];
1003 r[i++] = c & this.DM;
1004 c >>= this.DB;
1005 }
1006 c += this.s;
1007 } else {
1008 c += this.s;
1009 while (i < a.t) {
1010 c += a[i];
1011 r[i++] = c & this.DM;
1012 c >>= this.DB;
1013 }
1014 c += a.s;
1015 }
1016 r.s = (c < 0) ? -1 : 0;
1017 if (c > 0) r[i++] = c;
1018 else if (c < -1) r[i++] = this.DV + c;
1019 r.t = i;
1020 r.clamp();
1021 }
1022
1023 // (public) this + a
1024 function bnAdd(a) {
1025 var r = nbi();
1026 this.addTo(a, r);
1027 return r;
1028 }
1029
1030 // (public) this - a
1031 function bnSubtract(a) {
1032 var r = nbi();
1033 this.subTo(a, r);
1034 return r;
1035 }
1036
1037 // (public) this * a
1038 function bnMultiply(a) {
1039 var r = nbi();
1040 this.multiplyTo(a, r);
1041 return r;
1042 }
1043
1044 // (public) this^2
1045 function bnSquare() {
1046 var r = nbi();
1047 this.squareTo(r);
1048 return r;
1049 }
1050
1051 // (public) this / a
1052 function bnDivide(a) {
1053 var r = nbi();
1054 this.divRemTo(a, r, null);
1055 return r;
1056 }
1057
1058 // (public) this % a
1059 function bnRemainder(a) {
1060 var r = nbi();
1061 this.divRemTo(a, null, r);
1062 return r;
1063 }
1064
1065 // (public) [this/a,this%a]
1066 function bnDivideAndRemainder(a) {
1067 var q = nbi(),
1068 r = nbi();
1069 this.divRemTo(a, q, r);
1070 return new Array(q, r);
1071 }
1072
1073 // (protected) this *= n, this >= 0, 1 < n < DV
1074 function bnpDMultiply(n) {
1075 this[this.t] = this.am(0, n - 1, this, 0, 0, this.t); ++this.t;
1076 this.clamp();
1077 }
1078
1079 // (protected) this += n << w words, this >= 0
1080 function bnpDAddOffset(n, w) {
1081 if (n == 0) return;
1082 while (this.t <= w) this[this.t++] = 0;
1083 this[w] += n;
1084 while (this[w] >= this.DV) {
1085 this[w] -= this.DV;
1086 if (++w >= this.t) this[this.t++] = 0; ++this[w];
1087 }
1088 }
1089
1090 // A "null" reducer
1091 function NullExp() {}
1092 function nNop(x) {
1093 return x;
1094 }
1095 function nMulTo(x, y, r) {
1096 x.multiplyTo(y, r);
1097 }
1098 function nSqrTo(x, r) {
1099 x.squareTo(r);
1100 }
1101
1102 NullExp.prototype.convert = nNop;
1103 NullExp.prototype.revert = nNop;
1104 NullExp.prototype.mulTo = nMulTo;
1105 NullExp.prototype.sqrTo = nSqrTo;
1106
1107 // (public) this^e
1108 function bnPow(e) {
1109 return this.exp(e, new NullExp());
1110 }
1111
1112 // (protected) r = lower n words of "this * a", a.t <= n
1113 // "this" should be the larger one if appropriate.
1114 function bnpMultiplyLowerTo(a, n, r) {
1115 var i = Math.min(this.t + a.t, n);
1116 r.s = 0; // assumes a,this >= 0
1117 r.t = i;
1118 while (i > 0) r[--i] = 0;
1119 var j;
1120 for (j = r.t - this.t; i < j; ++i) r[i + this.t] = this.am(0, a[i], r, i, 0, this.t);
1121 for (j = Math.min(a.t, n); i < j; ++i) this.am(0, a[i], r, i, 0, n - i);
1122 r.clamp();
1123 }
1124
1125 // (protected) r = "this * a" without lower n words, n > 0
1126 // "this" should be the larger one if appropriate.
1127 function bnpMultiplyUpperTo(a, n, r) {--n;
1128 var i = r.t = this.t + a.t - n;
1129 r.s = 0; // assumes a,this >= 0
1130 while (--i >= 0) r[i] = 0;
1131 for (i = Math.max(n - this.t, 0); i < a.t; ++i) r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n);
1132 r.clamp();
1133 r.drShiftTo(1, r);
1134 }
1135
1136 // Barrett modular reduction
1137 function Barrett(m) {
1138 // setup Barrett
1139 this.r2 = nbi();
1140 this.q3 = nbi();
1141 BigInteger.ONE.dlShiftTo(2 * m.t, this.r2);
1142 this.mu = this.r2.divide(m);
1143 this.m = m;
1144 }
1145
1146 function barrettConvert(x) {
1147 if (x.s < 0 || x.t > 2 * this.m.t) return x.mod(this.m);
1148 else if (x.compareTo(this.m) < 0) return x;
1149 else {
1150 var r = nbi();
1151 x.copyTo(r);
1152 this.reduce(r);
1153 return r;
1154 }
1155 }
1156
1157 function barrettRevert(x) {
1158 return x;
1159 }
1160
1161 // x = x mod m (HAC 14.42)
1162 function barrettReduce(x) {
1163 x.drShiftTo(this.m.t - 1, this.r2);
1164 if (x.t > this.m.t + 1) {
1165 x.t = this.m.t + 1;
1166 x.clamp();
1167 }
1168 this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3);
1169 this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2);
1170 while (x.compareTo(this.r2) < 0) x.dAddOffset(1, this.m.t + 1);
1171 x.subTo(this.r2, x);
1172 while (x.compareTo(this.m) >= 0) x.subTo(this.m, x);
1173 }
1174
1175 // r = x^2 mod m; x != r
1176 function barrettSqrTo(x, r) {
1177 x.squareTo(r);
1178 this.reduce(r);
1179 }
1180
1181 // r = x*y mod m; x,y != r
1182 function barrettMulTo(x, y, r) {
1183 x.multiplyTo(y, r);
1184 this.reduce(r);
1185 }
1186
1187 Barrett.prototype.convert = barrettConvert;
1188 Barrett.prototype.revert = barrettRevert;
1189 Barrett.prototype.reduce = barrettReduce;
1190 Barrett.prototype.mulTo = barrettMulTo;
1191 Barrett.prototype.sqrTo = barrettSqrTo;
1192
1193 // (public) this^e % m (HAC 14.85)
1194 function bnModPow(e, m) {
1195 var i = e.bitLength(),
1196 k,
1197 r = nbv(1),
1198 z;
1199 if (i <= 0) return r;
1200 else if (i < 18) k = 1;
1201 else if (i < 48) k = 3;
1202 else if (i < 144) k = 4;
1203 else if (i < 768) k = 5;
1204 else k = 6;
1205 if (i < 8) z = new Classic(m);
1206 else if (m.isEven()) z = new Barrett(m);
1207 else z = new Montgomery(m);
1208
1209 // precomputation
1210 var g = new Array(),
1211 n = 3,
1212 k1 = k - 1,
1213 km = (1 << k) - 1;
1214 g[1] = z.convert(this);
1215 if (k > 1) {
1216 var g2 = nbi();
1217 z.sqrTo(g[1], g2);
1218 while (n <= km) {
1219 g[n] = nbi();
1220 z.mulTo(g2, g[n - 2], g[n]);
1221 n += 2;
1222 }
1223 }
1224
1225 var j = e.t - 1,
1226 w, is1 = true,
1227 r2 = nbi(),
1228 t;
1229 i = nbits(e[j]) - 1;
1230 while (j >= 0) {
1231 if (i >= k1) w = (e[j] >> (i - k1)) & km;
1232 else {
1233 w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
1234 if (j > 0) w |= e[j - 1] >> (this.DB + i - k1);
1235 }
1236
1237 n = k;
1238 while ((w & 1) == 0) {
1239 w >>= 1; --n;
1240 }
1241 if ((i -= n) < 0) {
1242 i += this.DB; --j;
1243 }
1244 if (is1) { // ret == 1, don't bother squaring or multiplying it
1245 g[w].copyTo(r);
1246 is1 = false;
1247 } else {
1248 while (n > 1) {
1249 z.sqrTo(r, r2);
1250 z.sqrTo(r2, r);
1251 n -= 2;
1252 }
1253 if (n > 0) z.sqrTo(r, r2);
1254 else {
1255 t = r;
1256 r = r2;
1257 r2 = t;
1258 }
1259 z.mulTo(r2, g[w], r);
1260 }
1261
1262 while (j >= 0 && (e[j] & (1 << i)) == 0) {
1263 z.sqrTo(r, r2);
1264 t = r;
1265 r = r2;
1266 r2 = t;
1267 if (--i < 0) {
1268 i = this.DB - 1; --j;
1269 }
1270 }
1271 }
1272 return z.revert(r);
1273 }
1274
1275 // (public) gcd(this,a) (HAC 14.54)
1276 function bnGCD(a) {
1277 var x = (this.s < 0) ? this.negate() : this.clone();
1278 var y = (a.s < 0) ? a.negate() : a.clone();
1279 if (x.compareTo(y) < 0) {
1280 var t = x;
1281 x = y;
1282 y = t;
1283 }
1284 var i = x.getLowestSetBit(),
1285 g = y.getLowestSetBit();
1286 if (g < 0) return x;
1287 if (i < g) g = i;
1288 if (g > 0) {
1289 x.rShiftTo(g, x);
1290 y.rShiftTo(g, y);
1291 }
1292 while (x.signum() > 0) {
1293 if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x);
1294 if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y);
1295 if (x.compareTo(y) >= 0) {
1296 x.subTo(y, x);
1297 x.rShiftTo(1, x);
1298 } else {
1299 y.subTo(x, y);
1300 y.rShiftTo(1, y);
1301 }
1302 }
1303 if (g > 0) y.lShiftTo(g, y);
1304 return y;
1305 }
1306
1307 // (protected) this % n, n < 2^26
1308 function bnpModInt(n) {
1309 if (n <= 0) return 0;
1310 var d = this.DV % n,
1311 r = (this.s < 0) ? n - 1 : 0;
1312 if (this.t > 0) if (d == 0) r = this[0] % n;
1313 else for (var i = this.t - 1; i >= 0; --i) r = (d * r + this[i]) % n;
1314 return r;
1315 }
1316
1317 // (public) 1/this % m (HAC 14.61)
1318 function bnModInverse(m) {
1319 var ac = m.isEven();
1320 if ((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
1321 var u = m.clone(),
1322 v = this.clone();
1323 var a = nbv(1),
1324 b = nbv(0),
1325 c = nbv(0),
1326 d = nbv(1);
1327 while (u.signum() != 0) {
1328 while (u.isEven()) {
1329 u.rShiftTo(1, u);
1330 if (ac) {
1331 if (!a.isEven() || !b.isEven()) {
1332 a.addTo(this, a);
1333 b.subTo(m, b);
1334 }
1335 a.rShiftTo(1, a);
1336 } else if (!b.isEven()) b.subTo(m, b);
1337 b.rShiftTo(1, b);
1338 }
1339 while (v.isEven()) {
1340 v.rShiftTo(1, v);
1341 if (ac) {
1342 if (!c.isEven() || !d.isEven()) {
1343 c.addTo(this, c);
1344 d.subTo(m, d);
1345 }
1346 c.rShiftTo(1, c);
1347 } else if (!d.isEven()) d.subTo(m, d);
1348 d.rShiftTo(1, d);
1349 }
1350 if (u.compareTo(v) >= 0) {
1351 u.subTo(v, u);
1352 if (ac) a.subTo(c, a);
1353 b.subTo(d, b);
1354 } else {
1355 v.subTo(u, v);
1356 if (ac) c.subTo(a, c);
1357 d.subTo(b, d);
1358 }
1359 }
1360 if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
1361 if (d.compareTo(m) >= 0) return d.subtract(m);
1362 if (d.signum() < 0) d.addTo(m, d);
1363 else return d;
1364 if (d.signum() < 0) return d.add(m);
1365 else return d;
1366 }
1367
1368 var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
1369 var lplim = (1 << 26) / lowprimes[lowprimes.length - 1];
1370
1371 // (public) test primality with certainty >= 1-.5^t
1372 function bnIsProbablePrime(t) {
1373 var i, x = this.abs();
1374 if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) {
1375 for (i = 0; i < lowprimes.length; ++i) if (x[0] == lowprimes[i]) return true;
1376 return false;
1377 }
1378 if (x.isEven()) return false;
1379 i = 1;
1380 while (i < lowprimes.length) {
1381 var m = lowprimes[i],
1382 j = i + 1;
1383 while (j < lowprimes.length && m < lplim) m *= lowprimes[j++];
1384 m = x.modInt(m);
1385 while (i < j) if (m % lowprimes[i++] == 0) return false;
1386 }
1387 return x.millerRabin(t);
1388 }
1389
1390 // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
1391 function bnpMillerRabin(t) {
1392 var n1 = this.subtract(BigInteger.ONE);
1393 var k = n1.getLowestSetBit();
1394 if (k <= 0) return false;
1395 var r = n1.shiftRight(k);
1396 t = (t + 1) >> 1;
1397 if (t > lowprimes.length) t = lowprimes.length;
1398 var a = nbi();
1399 for (var i = 0; i < t; ++i) {
1400 //Pick bases at random, instead of starting at 2
1401 a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]);
1402 var y = a.modPow(r, this);
1403 if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
1404 var j = 1;
1405 while (j++<k && y.compareTo(n1) != 0) {
1406 y = y.modPowInt(2, this);
1407 if (y.compareTo(BigInteger.ONE) == 0) return false;
1408 }
1409 if (y.compareTo(n1) != 0) return false;
1410 }
1411 }
1412 return true;
1413 }
1414
1415 // protected
1416 BigInteger.prototype.chunkSize = bnpChunkSize;
1417 BigInteger.prototype.toRadix = bnpToRadix;
1418 BigInteger.prototype.fromRadix = bnpFromRadix;
1419 BigInteger.prototype.fromNumber = bnpFromNumber;
1420 BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
1421 BigInteger.prototype.changeBit = bnpChangeBit;
1422 BigInteger.prototype.addTo = bnpAddTo;
1423 BigInteger.prototype.dMultiply = bnpDMultiply;
1424 BigInteger.prototype.dAddOffset = bnpDAddOffset;
1425 BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
1426 BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
1427 BigInteger.prototype.modInt = bnpModInt;
1428 BigInteger.prototype.millerRabin = bnpMillerRabin;
1429
1430 // public
1431 BigInteger.prototype.clone = bnClone;
1432 BigInteger.prototype.intValue = bnIntValue;
1433 BigInteger.prototype.byteValue = bnByteValue;
1434 BigInteger.prototype.shortValue = bnShortValue;
1435 BigInteger.prototype.signum = bnSigNum;
1436 BigInteger.prototype.toByteArray = bnToByteArray;
1437 BigInteger.prototype.equals = bnEquals;
1438 BigInteger.prototype.min = bnMin;
1439 BigInteger.prototype.max = bnMax;
1440 BigInteger.prototype.and = bnAnd;
1441 BigInteger.prototype.or = bnOr;
1442 BigInteger.prototype.xor = bnXor;
1443 BigInteger.prototype.andNot = bnAndNot;
1444 BigInteger.prototype.not = bnNot;
1445 BigInteger.prototype.shiftLeft = bnShiftLeft;
1446 BigInteger.prototype.shiftRight = bnShiftRight;
1447 BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
1448 BigInteger.prototype.bitCount = bnBitCount;
1449 BigInteger.prototype.testBit = bnTestBit;
1450 BigInteger.prototype.setBit = bnSetBit;
1451 BigInteger.prototype.clearBit = bnClearBit;
1452 BigInteger.prototype.flipBit = bnFlipBit;
1453 BigInteger.prototype.add = bnAdd;
1454 BigInteger.prototype.subtract = bnSubtract;
1455 BigInteger.prototype.multiply = bnMultiply;
1456 BigInteger.prototype.divide = bnDivide;
1457 BigInteger.prototype.remainder = bnRemainder;
1458 BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
1459 BigInteger.prototype.modPow = bnModPow;
1460 BigInteger.prototype.modInverse = bnModInverse;
1461 BigInteger.prototype.pow = bnPow;
1462 BigInteger.prototype.gcd = bnGCD;
1463 BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
1464
1465 // JSBN-specific extension
1466 BigInteger.prototype.square = bnSquare;
1467
1468 // BigInteger interfaces not implemented in jsbn:
1469 // BigInteger(int signum, byte[] magnitude)
1470 // double doubleValue()
1471 // float floatValue()
1472 // int hashCode()
1473 // long longValue()
1474 // static BigInteger valueOf(long val)
1475 // prng4.js - uses Arcfour as a PRNG
1476 function Arcfour() {
1477 this.i = 0;
1478 this.j = 0;
1479 this.S = new Array();
1480 }
1481
1482 // Initialize arcfour context from key, an array of ints, each from [0..255]
1483 function ARC4init(key) {
1484 var i, j, t;
1485 for (i = 0; i < 256; ++i) this.S[i] = i;
1486 j = 0;
1487 for (i = 0; i < 256; ++i) {
1488 j = (j + this.S[i] + key[i % key.length]) & 255;
1489 t = this.S[i];
1490 this.S[i] = this.S[j];
1491 this.S[j] = t;
1492 }
1493 this.i = 0;
1494 this.j = 0;
1495 }
1496
1497 function ARC4next() {
1498 var t;
1499 this.i = (this.i + 1) & 255;
1500 this.j = (this.j + this.S[this.i]) & 255;
1501 t = this.S[this.i];
1502 this.S[this.i] = this.S[this.j];
1503 this.S[this.j] = t;
1504 return this.S[(t + this.S[this.i]) & 255];
1505 }
1506
1507 Arcfour.prototype.init = ARC4init;
1508 Arcfour.prototype.next = ARC4next;
1509
1510 // Plug in your RNG constructor here
1511 function prng_newstate() {
1512 return new Arcfour();
1513 }
1514
1515 // Pool size must be a multiple of 4 and greater than 32.
1516 // An array of bytes the size of the pool will be passed to init()
1517 var rng_psize = 256;
1518
1519 // Random number generator - requires a PRNG backend, e.g. prng4.js
1520 var rng_state;
1521 var rng_pool;
1522 var rng_pptr;
1523
1524 // Initialize the pool with junk if needed.
1525 if (rng_pool == null) {
1526 rng_pool = new Array();
1527 rng_pptr = 0;
1528 var t;
1529 if (window.crypto && window.crypto.getRandomValues) {
1530 // Extract entropy (2048 bits) from RNG if available
1531 var z = new Uint32Array(256);
1532 window.crypto.getRandomValues(z);
1533 for (t = 0; t < z.length; ++t) rng_pool[rng_pptr++] = z[t] & 255;
1534 }
1535
1536 // Use mouse events for entropy, if we do not have enough entropy by the time
1537 // we need it, entropy will be generated by Math.random.
1538 var onMouseMoveListener = function(ev) {
1539 this.count = this.count || 0;
1540 if (this.count >= 256 || rng_pptr >= rng_psize) {
1541 if (window.removeEventListener) window.removeEventListener("mousemove", onMouseMoveListener, false);
1542 else if (window.detachEvent) window.detachEvent("onmousemove", onMouseMoveListener);
1543 return;
1544 }
1545 try {
1546 var mouseCoordinates = ev.x + ev.y;
1547 rng_pool[rng_pptr++] = mouseCoordinates & 255;
1548 this.count += 1;
1549 } catch(e) {
1550 // Sometimes Firefox will deny permission to access event properties for some reason. Ignore.
1551 }
1552 };
1553 if (window.addEventListener) window.addEventListener("mousemove", onMouseMoveListener, false);
1554 else if (window.attachEvent) window.attachEvent("onmousemove", onMouseMoveListener);
1555
1556 }
1557
1558 function rng_get_byte() {
1559 if (rng_state == null) {
1560 rng_state = prng_newstate();
1561 // At this point, we may not have collected enough entropy. If not, fall back to Math.random
1562 while (rng_pptr < rng_psize) {
1563 var random = Math.floor(65536 * Math.random());
1564 rng_pool[rng_pptr++] = random & 255;
1565 }
1566 rng_state.init(rng_pool);
1567 for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) rng_pool[rng_pptr] = 0;
1568 rng_pptr = 0;
1569 }
1570 // TODO: allow reseeding after first request
1571 return rng_state.next();
1572 }
1573
1574 function rng_get_bytes(ba) {
1575 var i;
1576 for (i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
1577 }
1578
1579 function SecureRandom() {}
1580
1581 SecureRandom.prototype.nextBytes = rng_get_bytes;
1582
1583 // Depends on jsbn.js and rng.js
1584 // Version 1.1: support utf-8 encoding in pkcs1pad2
1585 // convert a (hex) string to a bignum object
1586 function parseBigInt(str, r) {
1587 return new BigInteger(str, r);
1588 }
1589
1590 function linebrk(s, n) {
1591 var ret = "";
1592 var i = 0;
1593 while (i + n < s.length) {
1594 ret += s.substring(i, i + n) + "\n";
1595 i += n;
1596 }
1597 return ret + s.substring(i, s.length);
1598 }
1599
1600 function byte2Hex(b) {
1601 if (b < 0x10) return "0" + b.toString(16);
1602 else return b.toString(16);
1603 }
1604
1605 // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
1606 function pkcs1pad2(s, n) {
1607 if (n < s.length + 11) { // TODO: fix for utf-8
1608 console.error("Message too long for RSA");
1609 return null;
1610 }
1611 var ba = new Array();
1612 var i = s.length - 1;
1613 while (i >= 0 && n > 0) {
1614 var c = s.charCodeAt(i--);
1615 if (c < 128) { // encode using utf-8
1616 ba[--n] = c;
1617 } else if ((c > 127) && (c < 2048)) {
1618 ba[--n] = (c & 63) | 128;
1619 ba[--n] = (c >> 6) | 192;
1620 } else {
1621 ba[--n] = (c & 63) | 128;
1622 ba[--n] = ((c >> 6) & 63) | 128;
1623 ba[--n] = (c >> 12) | 224;
1624 }
1625 }
1626 ba[--n] = 0;
1627 var rng = new SecureRandom();
1628 var x = new Array();
1629 while (n > 2) { // random non-zero pad
1630 x[0] = 0;
1631 while (x[0] == 0) rng.nextBytes(x);
1632 ba[--n] = x[0];
1633 }
1634 ba[--n] = 2;
1635 ba[--n] = 0;
1636 return new BigInteger(ba);
1637 }
1638
1639 // "empty" RSA key constructor
1640 function RSAKey() {
1641 this.n = null;
1642 this.e = 0;
1643 this.d = null;
1644 this.p = null;
1645 this.q = null;
1646 this.dmp1 = null;
1647 this.dmq1 = null;
1648 this.coeff = null;
1649 }
1650
1651 // Set the public key fields N and e from hex strings
1652 function RSASetPublic(N, E) {
1653 if (N != null && E != null && N.length > 0 && E.length > 0) {
1654 this.n = parseBigInt(N, 16);
1655 this.e = parseInt(E, 16);
1656 } else console.error("Invalid RSA public key");
1657 }
1658
1659 // Perform raw public operation on "x": return x^e (mod n)
1660 function RSADoPublic(x) {
1661 return x.modPowInt(this.e, this.n);
1662 }
1663
1664 // Return the PKCS#1 RSA encryption of "text" as an even-length hex string
1665 function RSAEncrypt(text) {
1666 var m = pkcs1pad2(text, (this.n.bitLength() + 7) >> 3);
1667 if (m == null) return null;
1668 var c = this.doPublic(m);
1669 if (c == null) return null;
1670 var h = c.toString(16);
1671 if ((h.length & 1) == 0) return h;
1672 else return "0" + h;
1673 }
1674
1675 // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
1676 //function RSAEncryptB64(text) {
1677 // var h = this.encrypt(text);
1678 // if(h) return hex2b64(h); else return null;
1679 //}
1680 // protected
1681 RSAKey.prototype.doPublic = RSADoPublic;
1682
1683 // public
1684 RSAKey.prototype.setPublic = RSASetPublic;
1685 RSAKey.prototype.encrypt = RSAEncrypt;
1686 //RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
1687 // Depends on rsa.js and jsbn2.js
1688 // Version 1.1: support utf-8 decoding in pkcs1unpad2
1689 // Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
1690 function pkcs1unpad2(d, n) {
1691 var b = d.toByteArray();
1692 var i = 0;
1693 while (i < b.length && b[i] == 0)++i;
1694 if (b.length - i != n - 1 || b[i] != 2) return null; ++i;
1695 while (b[i] != 0) if (++i >= b.length) return null;
1696 var ret = "";
1697 while (++i < b.length) {
1698 var c = b[i] & 255;
1699 if (c < 128) { // utf-8 decode
1700 ret += String.fromCharCode(c);
1701 } else if ((c > 191) && (c < 224)) {
1702 ret += String.fromCharCode(((c & 31) << 6) | (b[i + 1] & 63)); ++i;
1703 } else {
1704 ret += String.fromCharCode(((c & 15) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63));
1705 i += 2;
1706 }
1707 }
1708 return ret;
1709 }
1710
1711 // Set the private key fields N, e, and d from hex strings
1712 function RSASetPrivate(N, E, D) {
1713 if (N != null && E != null && N.length > 0 && E.length > 0) {
1714 this.n = parseBigInt(N, 16);
1715 this.e = parseInt(E, 16);
1716 this.d = parseBigInt(D, 16);
1717 } else console.error("Invalid RSA private key");
1718 }
1719
1720 // Set the private key fields N, e, d and CRT params from hex strings
1721 function RSASetPrivateEx(N, E, D, P, Q, DP, DQ, C) {
1722 if (N != null && E != null && N.length > 0 && E.length > 0) {
1723 this.n = parseBigInt(N, 16);
1724 this.e = parseInt(E, 16);
1725 this.d = parseBigInt(D, 16);
1726 this.p = parseBigInt(P, 16);
1727 this.q = parseBigInt(Q, 16);
1728 this.dmp1 = parseBigInt(DP, 16);
1729 this.dmq1 = parseBigInt(DQ, 16);
1730 this.coeff = parseBigInt(C, 16);
1731 } else console.error("Invalid RSA private key");
1732 }
1733
1734 // Generate a new random private key B bits long, using public expt E
1735 function RSAGenerate(B, E) {
1736 var rng = new SecureRandom();
1737 var qs = B >> 1;
1738 this.e = parseInt(E, 16);
1739 var ee = new BigInteger(E, 16);
1740 for (;;) {
1741 for (;;) {
1742 this.p = new BigInteger(B - qs, 1, rng);
1743 if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
1744 }
1745 for (;;) {
1746 this.q = new BigInteger(qs, 1, rng);
1747 if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
1748 }
1749 if (this.p.compareTo(this.q) <= 0) {
1750 var t = this.p;
1751 this.p = this.q;
1752 this.q = t;
1753 }
1754 var p1 = this.p.subtract(BigInteger.ONE);
1755 var q1 = this.q.subtract(BigInteger.ONE);
1756 var phi = p1.multiply(q1);
1757 if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
1758 this.n = this.p.multiply(this.q);
1759 this.d = ee.modInverse(phi);
1760 this.dmp1 = this.d.mod(p1);
1761 this.dmq1 = this.d.mod(q1);
1762 this.coeff = this.q.modInverse(this.p);
1763 break;
1764 }
1765 }
1766 }
1767
1768 // Perform raw private operation on "x": return x^d (mod n)
1769 function RSADoPrivate(x) {
1770 if (this.p == null || this.q == null) return x.modPow(this.d, this.n);
1771
1772 // TODO: re-calculate any missing CRT params
1773 var xp = x.mod(this.p).modPow(this.dmp1, this.p);
1774 var xq = x.mod(this.q).modPow(this.dmq1, this.q);
1775
1776 while (xp.compareTo(xq) < 0) xp = xp.add(this.p);
1777 return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
1778 }
1779
1780 // Return the PKCS#1 RSA decryption of "ctext".
1781 // "ctext" is an even-length hex string and the output is a plain string.
1782 function RSADecrypt(ctext) {
1783 var c = parseBigInt(ctext, 16);
1784 var m = this.doPrivate(c);
1785 if (m == null) return null;
1786 return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3);
1787 }
1788
1789 // Return the PKCS#1 RSA decryption of "ctext".
1790 // "ctext" is a Base64-encoded string and the output is a plain string.
1791 //function RSAB64Decrypt(ctext) {
1792 // var h = b64tohex(ctext);
1793 // if(h) return this.decrypt(h); else return null;
1794 //}
1795 // protected
1796 RSAKey.prototype.doPrivate = RSADoPrivate;
1797
1798 // public
1799 RSAKey.prototype.setPrivate = RSASetPrivate;
1800 RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
1801 RSAKey.prototype.generate = RSAGenerate;
1802 RSAKey.prototype.decrypt = RSADecrypt;
1803 //RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
1804 // Copyright (c) 2011 Kevin M Burns Jr.
1805 // All Rights Reserved.
1806 // See "LICENSE" for details.
1807 //
1808 // Extension to jsbn which adds facilities for asynchronous RSA key generation
1809 // Primarily created to avoid execution timeout on mobile devices
1810 //
1811 // http://www-cs-students.stanford.edu/~tjw/jsbn/
1812 //
1813 // ---
1814 (function() {
1815
1816 // Generate a new random private key B bits long, using public expt E
1817 var RSAGenerateAsync = function(B, E, callback) {
1818 //var rng = new SeededRandom();
1819 var rng = new SecureRandom();
1820 var qs = B >> 1;
1821 this.e = parseInt(E, 16);
1822 var ee = new BigInteger(E, 16);
1823 var rsa = this;
1824 // These functions have non-descript names because they were originally for(;;) loops.
1825 // I don't know about cryptography to give them better names than loop1-4.
1826 var loop1 = function() {
1827 var loop4 = function() {
1828 if (rsa.p.compareTo(rsa.q) <= 0) {
1829 var t = rsa.p;
1830 rsa.p = rsa.q;
1831 rsa.q = t;
1832 }
1833 var p1 = rsa.p.subtract(BigInteger.ONE);
1834 var q1 = rsa.q.subtract(BigInteger.ONE);
1835 var phi = p1.multiply(q1);
1836 if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
1837 rsa.n = rsa.p.multiply(rsa.q);
1838 rsa.d = ee.modInverse(phi);
1839 rsa.dmp1 = rsa.d.mod(p1);
1840 rsa.dmq1 = rsa.d.mod(q1);
1841 rsa.coeff = rsa.q.modInverse(rsa.p);
1842 setTimeout(function() {
1843 callback()
1844 },
1845 0); // escape
1846 } else {
1847 setTimeout(loop1, 0);
1848 }
1849 };
1850 var loop3 = function() {
1851 rsa.q = nbi();
1852 rsa.q.fromNumberAsync(qs, 1, rng,
1853 function() {
1854 rsa.q.subtract(BigInteger.ONE).gcda(ee,
1855 function(r) {
1856 if (r.compareTo(BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) {
1857 setTimeout(loop4, 0);
1858 } else {
1859 setTimeout(loop3, 0);
1860 }
1861 });
1862 });
1863 };
1864 var loop2 = function() {
1865 rsa.p = nbi();
1866 rsa.p.fromNumberAsync(B - qs, 1, rng,
1867 function() {
1868 rsa.p.subtract(BigInteger.ONE).gcda(ee,
1869 function(r) {
1870 if (r.compareTo(BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) {
1871 setTimeout(loop3, 0);
1872 } else {
1873 setTimeout(loop2, 0);
1874 }
1875 });
1876 });
1877 };
1878 setTimeout(loop2, 0);
1879 };
1880 setTimeout(loop1, 0);
1881 };
1882 RSAKey.prototype.generateAsync = RSAGenerateAsync;
1883
1884 // Public API method
1885 var bnGCDAsync = function(a, callback) {
1886 var x = (this.s < 0) ? this.negate() : this.clone();
1887 var y = (a.s < 0) ? a.negate() : a.clone();
1888 if (x.compareTo(y) < 0) {
1889 var t = x;
1890 x = y;
1891 y = t;
1892 }
1893 var i = x.getLowestSetBit(),
1894 g = y.getLowestSetBit();
1895 if (g < 0) {
1896 callback(x);
1897 return;
1898 }
1899 if (i < g) g = i;
1900 if (g > 0) {
1901 x.rShiftTo(g, x);
1902 y.rShiftTo(g, y);
1903 }
1904 // Workhorse of the algorithm, gets called 200 - 800 times per 512 bit keygen.
1905 var gcda1 = function() {
1906 if ((i = x.getLowestSetBit()) > 0) {
1907 x.rShiftTo(i, x);
1908 }
1909 if ((i = y.getLowestSetBit()) > 0) {
1910 y.rShiftTo(i, y);
1911 }
1912 if (x.compareTo(y) >= 0) {
1913 x.subTo(y, x);
1914 x.rShiftTo(1, x);
1915 } else {
1916 y.subTo(x, y);
1917 y.rShiftTo(1, y);
1918 }
1919 if (! (x.signum() > 0)) {
1920 if (g > 0) y.lShiftTo(g, y);
1921 setTimeout(function() {
1922 callback(y)
1923 },
1924 0); // escape
1925 } else {
1926 setTimeout(gcda1, 0);
1927 }
1928 };
1929 setTimeout(gcda1, 10);
1930 };
1931 BigInteger.prototype.gcda = bnGCDAsync;
1932
1933 // (protected) alternate constructor
1934 var bnpFromNumberAsync = function(a, b, c, callback) {
1935 if ("number" == typeof b) {
1936 if (a < 2) {
1937 this.fromInt(1);
1938 } else {
1939 this.fromNumber(a, c);
1940 if (!this.testBit(a - 1)) {
1941 this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this);
1942 }
1943 if (this.isEven()) {
1944 this.dAddOffset(1, 0);
1945 }
1946 var bnp = this;
1947 var bnpfn1 = function() {
1948 bnp.dAddOffset(2, 0);
1949 if (bnp.bitLength() > a) bnp.subTo(BigInteger.ONE.shiftLeft(a - 1), bnp);
1950 if (bnp.isProbablePrime(b)) {
1951 setTimeout(function() {
1952 callback()
1953 },
1954 0); // escape
1955 } else {
1956 setTimeout(bnpfn1, 0);
1957 }
1958 };
1959 setTimeout(bnpfn1, 0);
1960 }
1961 } else {
1962 var x = new Array(),
1963 t = a & 7;
1964 x.length = (a >> 3) + 1;
1965 b.nextBytes(x);
1966 if (t > 0) x[0] &= ((1 << t) - 1);
1967 else x[0] = 0;
1968 this.fromString(x, 256);
1969 }
1970 };
1971 BigInteger.prototype.fromNumberAsync = bnpFromNumberAsync;
1972
1973 })();
1974 var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1975 var b64pad = "=";
1976
1977 function hex2b64(h) {
1978 var i;
1979 var c;
1980 var ret = "";
1981 for (i = 0; i + 3 <= h.length; i += 3) {
1982 c = parseInt(h.substring(i, i + 3), 16);
1983 ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
1984 }
1985 if (i + 1 == h.length) {
1986 c = parseInt(h.substring(i, i + 1), 16);
1987 ret += b64map.charAt(c << 2);
1988 } else if (i + 2 == h.length) {
1989 c = parseInt(h.substring(i, i + 2), 16);
1990 ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
1991 }
1992 while ((ret.length & 3) > 0) ret += b64pad;
1993 return ret;
1994 }
1995
1996 // convert a base64 string to hex
1997 function b64tohex(s) {
1998 var ret = ""
1999 var i;
2000 var k = 0; // b64 state, 0-3
2001 var slop;
2002 for (i = 0; i < s.length; ++i) {
2003 if (s.charAt(i) == b64pad) break;
2004 v = b64map.indexOf(s.charAt(i));
2005 if (v < 0) continue;
2006 if (k == 0) {
2007 ret += int2char(v >> 2);
2008 slop = v & 3;
2009 k = 1;
2010 } else if (k == 1) {
2011 ret += int2char((slop << 2) | (v >> 4));
2012 slop = v & 0xf;
2013 k = 2;
2014 } else if (k == 2) {
2015 ret += int2char(slop);
2016 ret += int2char(v >> 2);
2017 slop = v & 3;
2018 k = 3;
2019 } else {
2020 ret += int2char((slop << 2) | (v >> 4));
2021 ret += int2char(v & 0xf);
2022 k = 0;
2023 }
2024 }
2025 if (k == 1) ret += int2char(slop << 2);
2026 return ret;
2027 }
2028
2029 // convert a base64 string to a byte/number array
2030 function b64toBA(s) {
2031 //piggyback on b64tohex for now, optimize later
2032 var h = b64tohex(s);
2033 var i;
2034 var a = new Array();
2035 for (i = 0; 2 * i < h.length; ++i) {
2036 a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16);
2037 }
2038 return a;
2039 }
2040
2041 /*! asn1-1.0.2.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
2042 */
2043
2044 var JSX = JSX || {};
2045 JSX.env = JSX.env || {};
2046
2047 var L = JSX,
2048 OP = Object.prototype,
2049 FUNCTION_TOSTRING = '[object Function]',
2050 ADD = ["toString", "valueOf"];
2051
2052 JSX.env.parseUA = function(agent) {
2053
2054 var numberify = function(s) {
2055 var c = 0;
2056 return parseFloat(s.replace(/\./g,
2057 function() {
2058 return (c++==1) ? '': '.';
2059 }));
2060 },
2061
2062 nav = navigator,
2063 o = {
2064 ie: 0,
2065 opera: 0,
2066 gecko: 0,
2067 webkit: 0,
2068 chrome: 0,
2069 mobile: null,
2070 air: 0,
2071 ipad: 0,
2072 iphone: 0,
2073 ipod: 0,
2074 ios: null,
2075 android: 0,
2076 webos: 0,
2077 caja: nav && nav.cajaVersion,
2078 secure: false,
2079 os: null
2080
2081 },
2082
2083 ua = agent || (navigator && navigator.userAgent),
2084 loc = window && window.location,
2085 href = loc && loc.href,
2086 m;
2087
2088 o.secure = href && (href.toLowerCase().indexOf("https") === 0);
2089
2090 if (ua) {
2091
2092 if ((/windows|win32/i).test(ua)) {
2093 o.os = 'windows';
2094 } else if ((/macintosh/i).test(ua)) {
2095 o.os = 'macintosh';
2096 } else if ((/rhino/i).test(ua)) {
2097 o.os = 'rhino';
2098 }
2099 if ((/KHTML/).test(ua)) {
2100 o.webkit = 1;
2101 }
2102 m = ua.match(/AppleWebKit\/([^\s]*)/);
2103 if (m && m[1]) {
2104 o.webkit = numberify(m[1]);
2105 if (/ Mobile\//.test(ua)) {
2106 o.mobile = 'Apple'; // iPhone or iPod Touch
2107 m = ua.match(/OS ([^\s]*)/);
2108 if (m && m[1]) {
2109 m = numberify(m[1].replace('_', '.'));
2110 }
2111 o.ios = m;
2112 o.ipad = o.ipod = o.iphone = 0;
2113 m = ua.match(/iPad|iPod|iPhone/);
2114 if (m && m[0]) {
2115 o[m[0].toLowerCase()] = o.ios;
2116 }
2117 } else {
2118 m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/);
2119 if (m) {
2120 o.mobile = m[0];
2121 }
2122 if (/webOS/.test(ua)) {
2123 o.mobile = 'WebOS';
2124 m = ua.match(/webOS\/([^\s]*);/);
2125 if (m && m[1]) {
2126 o.webos = numberify(m[1]);
2127 }
2128 }
2129 if (/ Android/.test(ua)) {
2130 o.mobile = 'Android';
2131 m = ua.match(/Android ([^\s]*);/);
2132 if (m && m[1]) {
2133 o.android = numberify(m[1]);
2134 }
2135 }
2136 }
2137 m = ua.match(/Chrome\/([^\s]*)/);
2138 if (m && m[1]) {
2139 o.chrome = numberify(m[1]); // Chrome
2140 } else {
2141 m = ua.match(/AdobeAIR\/([^\s]*)/);
2142 if (m) {
2143 o.air = m[0]; // Adobe AIR 1.0 or better
2144 }
2145 }
2146 }
2147 if (!o.webkit) {
2148 m = ua.match(/Opera[\s\/]([^\s]*)/);
2149 if (m && m[1]) {
2150 o.opera = numberify(m[1]);
2151 m = ua.match(/Version\/([^\s]*)/);
2152 if (m && m[1]) {
2153 o.opera = numberify(m[1]); // opera 10+
2154 }
2155 m = ua.match(/Opera Mini[^;]*/);
2156 if (m) {
2157 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
2158 }
2159 } else { // not opera or webkit
2160 m = ua.match(/MSIE\s([^;]*)/);
2161 if (m && m[1]) {
2162 o.ie = numberify(m[1]);
2163 } else { // not opera, webkit, or ie
2164 m = ua.match(/Gecko\/([^\s]*)/);
2165 if (m) {
2166 o.gecko = 1; // Gecko detected, look for revision
2167 m = ua.match(/rv:([^\s\)]*)/);
2168 if (m && m[1]) {
2169 o.gecko = numberify(m[1]);
2170 }
2171 }
2172 }
2173 }
2174 }
2175 }
2176 return o;
2177 };
2178
2179 JSX.env.ua = JSX.env.parseUA();
2180
2181 JSX.isFunction = function(o) {
2182 return (typeof o === 'function') || OP.toString.apply(o) === FUNCTION_TOSTRING;
2183 };
2184
2185 JSX._IEEnumFix = (JSX.env.ua.ie) ?
2186 function(r, s) {
2187 var i, fname, f;
2188 for (i = 0; i < ADD.length; i = i + 1) {
2189
2190 fname = ADD[i];
2191 f = s[fname];
2192
2193 if (L.isFunction(f) && f != OP[fname]) {
2194 r[fname] = f;
2195 }
2196 }
2197 }: function() {};
2198
2199 JSX.extend = function(subc, superc, overrides) {
2200 if (!superc || !subc) {
2201 throw new Error("extend failed, please check that " + "all dependencies are included.");
2202 }
2203 var F = function() {},
2204 i;
2205 F.prototype = superc.prototype;
2206 subc.prototype = new F();
2207 subc.prototype.constructor = subc;
2208 subc.superclass = superc.prototype;
2209 if (superc.prototype.constructor == OP.constructor) {
2210 superc.prototype.constructor = superc;
2211 }
2212
2213 if (overrides) {
2214 for (i in overrides) {
2215 if (L.hasOwnProperty(overrides, i)) {
2216 subc.prototype[i] = overrides[i];
2217 }
2218 }
2219
2220 L._IEEnumFix(subc.prototype, overrides);
2221 }
2222 };
2223
2224 /*
2225 * asn1.js - ASN.1 DER encoder classes
2226 *
2227 * Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
2228 *
2229 * This software is licensed under the terms of the MIT License.
2230 * http://kjur.github.com/jsrsasign/license
2231 *
2232 * The above copyright and license notice shall be
2233 * included in all copies or substantial portions of the Software.
2234 */
2235
2236 /**
2237 * @fileOverview
2238 * @name asn1-1.0.js
2239 * @author Kenji Urushima kenji.urushima@gmail.com
2240 * @version 1.0.2 (2013-May-30)
2241 * @since 2.1
2242 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
2243 */
2244
2245 /**
2246 * kjur's class library name space
2247 * <p>
2248 * This name space provides following name spaces:
2249 * <ul>
2250 * <li>{@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder</li>
2251 * <li>{@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL</li>
2252 * <li>{@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature
2253 * class and utilities</li>
2254 * </ul>
2255 * </p>
2256 * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
2257 * @name KJUR
2258 * @namespace kjur's class library name space
2259 */
2260 if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
2261
2262 /**
2263 * kjur's ASN.1 class library name space
2264 * <p>
2265 * This is ITU-T X.690 ASN.1 DER encoder class library and
2266 * class structure and methods is very similar to
2267 * org.bouncycastle.asn1 package of
2268 * well known BouncyCaslte Cryptography Library.
2269 *
2270 * <h4>PROVIDING ASN.1 PRIMITIVES</h4>
2271 * Here are ASN.1 DER primitive classes.
2272 * <ul>
2273 * <li>{@link KJUR.asn1.DERBoolean}</li>
2274 * <li>{@link KJUR.asn1.DERInteger}</li>
2275 * <li>{@link KJUR.asn1.DERBitString}</li>
2276 * <li>{@link KJUR.asn1.DEROctetString}</li>
2277 * <li>{@link KJUR.asn1.DERNull}</li>
2278 * <li>{@link KJUR.asn1.DERObjectIdentifier}</li>
2279 * <li>{@link KJUR.asn1.DERUTF8String}</li>
2280 * <li>{@link KJUR.asn1.DERNumericString}</li>
2281 * <li>{@link KJUR.asn1.DERPrintableString}</li>
2282 * <li>{@link KJUR.asn1.DERTeletexString}</li>
2283 * <li>{@link KJUR.asn1.DERIA5String}</li>
2284 * <li>{@link KJUR.asn1.DERUTCTime}</li>
2285 * <li>{@link KJUR.asn1.DERGeneralizedTime}</li>
2286 * <li>{@link KJUR.asn1.DERSequence}</li>
2287 * <li>{@link KJUR.asn1.DERSet}</li>
2288 * </ul>
2289 *
2290 * <h4>OTHER ASN.1 CLASSES</h4>
2291 * <ul>
2292 * <li>{@link KJUR.asn1.ASN1Object}</li>
2293 * <li>{@link KJUR.asn1.DERAbstractString}</li>
2294 * <li>{@link KJUR.asn1.DERAbstractTime}</li>
2295 * <li>{@link KJUR.asn1.DERAbstractStructured}</li>
2296 * <li>{@link KJUR.asn1.DERTaggedObject}</li>
2297 * </ul>
2298 * </p>
2299 * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
2300 * @name KJUR.asn1
2301 * @namespace
2302 */
2303 if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {};
2304
2305 /**
2306 * ASN1 utilities class
2307 * @name KJUR.asn1.ASN1Util
2308 * @classs ASN1 utilities class
2309 * @since asn1 1.0.2
2310 */
2311 KJUR.asn1.ASN1Util = new
2312 function() {
2313 this.integerToByteHex = function(i) {
2314 var h = i.toString(16);
2315 if ((h.length % 2) == 1) h = '0' + h;
2316 return h;
2317 };
2318 this.bigIntToMinTwosComplementsHex = function(bigIntegerValue) {
2319 var h = bigIntegerValue.toString(16);
2320 if (h.substr(0, 1) != '-') {
2321 if (h.length % 2 == 1) {
2322 h = '0' + h;
2323 } else {
2324 if (!h.match(/^[0-7]/)) {
2325 h = '00' + h;
2326 }
2327 }
2328 } else {
2329 var hPos = h.substr(1);
2330 var xorLen = hPos.length;
2331 if (xorLen % 2 == 1) {
2332 xorLen += 1;
2333 } else {
2334 if (!h.match(/^[0-7]/)) {
2335 xorLen += 2;
2336 }
2337 }
2338 var hMask = '';
2339 for (var i = 0; i < xorLen; i++) {
2340 hMask += 'f';
2341 }
2342 var biMask = new BigInteger(hMask, 16);
2343 var biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE);
2344 h = biNeg.toString(16).replace(/^-/, '');
2345 }
2346 return h;
2347 };
2348 /**
2349 * get PEM string from hexadecimal data and header string
2350 * @name getPEMStringFromHex
2351 * @memberOf KJUR.asn1.ASN1Util
2352 * @function
2353 * @param {String} dataHex hexadecimal string of PEM body
2354 * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY')
2355 * @return {String} PEM formatted string of input data
2356 * @description
2357 * @example
2358 * var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex('616161', 'RSA PRIVATE KEY');
2359 * // value of pem will be:
2360 * -----BEGIN PRIVATE KEY-----
2361 * YWFh
2362 * -----END PRIVATE KEY-----
2363 */
2364 this.getPEMStringFromHex = function(dataHex, pemHeader) {
2365 var dataWA = CryptoJS.enc.Hex.parse(dataHex);
2366 var dataB64 = CryptoJS.enc.Base64.stringify(dataWA);
2367 var pemBody = dataB64.replace(/(.{64})/g, "$1\r\n");
2368 pemBody = pemBody.replace(/\r\n$/, '');
2369 return "-----BEGIN " + pemHeader + "-----\r\n" + pemBody + "\r\n-----END " + pemHeader + "-----\r\n";
2370 };
2371 };
2372
2373 // ********************************************************************
2374 // Abstract ASN.1 Classes
2375 // ********************************************************************
2376 // ********************************************************************
2377 /**
2378 * base class for ASN.1 DER encoder object
2379 * @name KJUR.asn1.ASN1Object
2380 * @class base class for ASN.1 DER encoder object
2381 * @property {Boolean} isModified flag whether internal data was changed
2382 * @property {String} hTLV hexadecimal string of ASN.1 TLV
2383 * @property {String} hT hexadecimal string of ASN.1 TLV tag(T)
2384 * @property {String} hL hexadecimal string of ASN.1 TLV length(L)
2385 * @property {String} hV hexadecimal string of ASN.1 TLV value(V)
2386 * @description
2387 */
2388 KJUR.asn1.ASN1Object = function() {
2389 var isModified = true;
2390 var hTLV = null;
2391 var hT = '00'
2392 var hL = '00';
2393 var hV = '';
2394
2395 /**
2396 * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V)
2397 * @name getLengthHexFromValue
2398 * @memberOf KJUR.asn1.ASN1Object
2399 * @function
2400 * @return {String} hexadecimal string of ASN.1 TLV length(L)
2401 */
2402 this.getLengthHexFromValue = function() {
2403 if (typeof this.hV == "undefined" || this.hV == null) {
2404 throw "this.hV is null or undefined.";
2405 }
2406 if (this.hV.length % 2 == 1) {
2407 throw "value hex must be even length: n=" + hV.length + ",v=" + this.hV;
2408 }
2409 var n = this.hV.length / 2;
2410 var hN = n.toString(16);
2411 if (hN.length % 2 == 1) {
2412 hN = "0" + hN;
2413 }
2414 if (n < 128) {
2415 return hN;
2416 } else {
2417 var hNlen = hN.length / 2;
2418 if (hNlen > 15) {
2419 throw "ASN.1 length too long to represent by 8x: n = " + n.toString(16);
2420 }
2421 var head = 128 + hNlen;
2422 return head.toString(16) + hN;
2423 }
2424 };
2425
2426 /**
2427 * get hexadecimal string of ASN.1 TLV bytes
2428 * @name getEncodedHex
2429 * @memberOf KJUR.asn1.ASN1Object
2430 * @function
2431 * @return {String} hexadecimal string of ASN.1 TLV
2432 */
2433 this.getEncodedHex = function() {
2434 if (this.hTLV == null || this.isModified) {
2435 this.hV = this.getFreshValueHex();
2436 this.hL = this.getLengthHexFromValue();
2437 this.hTLV = this.hT + this.hL + this.hV;
2438 this.isModified = false;
2439 //console.error("first time: " + this.hTLV);
2440 }
2441 return this.hTLV;
2442 };
2443
2444 /**
2445 * get hexadecimal string of ASN.1 TLV value(V) bytes
2446 * @name getValueHex
2447 * @memberOf KJUR.asn1.ASN1Object
2448 * @function
2449 * @return {String} hexadecimal string of ASN.1 TLV value(V) bytes
2450 */
2451 this.getValueHex = function() {
2452 this.getEncodedHex();
2453 return this.hV;
2454 }
2455
2456 this.getFreshValueHex = function() {
2457 return '';
2458 };
2459 };
2460
2461 // == BEGIN DERAbstractString ================================================
2462 /**
2463 * base class for ASN.1 DER string classes
2464 * @name KJUR.asn1.DERAbstractString
2465 * @class base class for ASN.1 DER string classes
2466 * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
2467 * @property {String} s internal string of value
2468 * @extends KJUR.asn1.ASN1Object
2469 * @description
2470 * <br/>
2471 * As for argument 'params' for constructor, you can specify one of
2472 * following properties:
2473 * <ul>
2474 * <li>str - specify initial ASN.1 value(V) by a string</li>
2475 * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
2476 * </ul>
2477 * NOTE: 'params' can be omitted.
2478 */
2479 KJUR.asn1.DERAbstractString = function(params) {
2480 KJUR.asn1.DERAbstractString.superclass.constructor.call(this);
2481 var s = null;
2482 var hV = null;
2483
2484 /**
2485 * get string value of this string object
2486 * @name getString
2487 * @memberOf KJUR.asn1.DERAbstractString
2488 * @function
2489 * @return {String} string value of this string object
2490 */
2491 this.getString = function() {
2492 return this.s;
2493 };
2494
2495 /**
2496 * set value by a string
2497 * @name setString
2498 * @memberOf KJUR.asn1.DERAbstractString
2499 * @function
2500 * @param {String} newS value by a string to set
2501 */
2502 this.setString = function(newS) {
2503 this.hTLV = null;
2504 this.isModified = true;
2505 this.s = newS;
2506 this.hV = stohex(this.s);
2507 };
2508
2509 /**
2510 * set value by a hexadecimal string
2511 * @name setStringHex
2512 * @memberOf KJUR.asn1.DERAbstractString
2513 * @function
2514 * @param {String} newHexString value by a hexadecimal string to set
2515 */
2516 this.setStringHex = function(newHexString) {
2517 this.hTLV = null;
2518 this.isModified = true;
2519 this.s = null;
2520 this.hV = newHexString;
2521 };
2522
2523 this.getFreshValueHex = function() {
2524 return this.hV;
2525 };
2526
2527 if (typeof params != "undefined") {
2528 if (typeof params['str'] != "undefined") {
2529 this.setString(params['str']);
2530 } else if (typeof params['hex'] != "undefined") {
2531 this.setStringHex(params['hex']);
2532 }
2533 }
2534 };
2535 JSX.extend(KJUR.asn1.DERAbstractString, KJUR.asn1.ASN1Object);
2536 // == END DERAbstractString ================================================
2537 // == BEGIN DERAbstractTime ==================================================
2538 /**
2539 * base class for ASN.1 DER Generalized/UTCTime class
2540 * @name KJUR.asn1.DERAbstractTime
2541 * @class base class for ASN.1 DER Generalized/UTCTime class
2542 * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'})
2543 * @extends KJUR.asn1.ASN1Object
2544 * @description
2545 * @see KJUR.asn1.ASN1Object - superclass
2546 */
2547 KJUR.asn1.DERAbstractTime = function(params) {
2548 KJUR.asn1.DERAbstractTime.superclass.constructor.call(this);
2549 var s = null;
2550 var date = null;
2551
2552 // --- PRIVATE METHODS --------------------
2553 this.localDateToUTC = function(d) {
2554 utc = d.getTime() + (d.getTimezoneOffset() * 60000);
2555 var utcDate = new Date(utc);
2556 return utcDate;
2557 };
2558
2559 this.formatDate = function(dateObject, type) {
2560 var pad = this.zeroPadding;
2561 var d = this.localDateToUTC(dateObject);
2562 var year = String(d.getFullYear());
2563 if (type == 'utc') year = year.substr(2, 2);
2564 var month = pad(String(d.getMonth() + 1), 2);
2565 var day = pad(String(d.getDate()), 2);
2566 var hour = pad(String(d.getHours()), 2);
2567 var min = pad(String(d.getMinutes()), 2);
2568 var sec = pad(String(d.getSeconds()), 2);
2569 return year + month + day + hour + min + sec + 'Z';
2570 };
2571
2572 this.zeroPadding = function(s, len) {
2573 if (s.length >= len) return s;
2574 return new Array(len - s.length + 1).join('0') + s;
2575 };
2576
2577 // --- PUBLIC METHODS --------------------
2578 /**
2579 * get string value of this string object
2580 * @name getString
2581 * @memberOf KJUR.asn1.DERAbstractTime
2582 * @function
2583 * @return {String} string value of this time object
2584 */
2585 this.getString = function() {
2586 return this.s;
2587 };
2588
2589 /**
2590 * set value by a string
2591 * @name setString
2592 * @memberOf KJUR.asn1.DERAbstractTime
2593 * @function
2594 * @param {String} newS value by a string to set such like "130430235959Z"
2595 */
2596 this.setString = function(newS) {
2597 this.hTLV = null;
2598 this.isModified = true;
2599 this.s = newS;
2600 this.hV = stohex(this.s);
2601 };
2602
2603 /**
2604 * set value by a Date object
2605 * @name setByDateValue
2606 * @memberOf KJUR.asn1.DERAbstractTime
2607 * @function
2608 * @param {Integer} year year of date (ex. 2013)
2609 * @param {Integer} month month of date between 1 and 12 (ex. 12)
2610 * @param {Integer} day day of month
2611 * @param {Integer} hour hours of date
2612 * @param {Integer} min minutes of date
2613 * @param {Integer} sec seconds of date
2614 */
2615 this.setByDateValue = function(year, month, day, hour, min, sec) {
2616 var dateObject = new Date(Date.UTC(year, month - 1, day, hour, min, sec, 0));
2617 this.setByDate(dateObject);
2618 };
2619
2620 this.getFreshValueHex = function() {
2621 return this.hV;
2622 };
2623 };
2624 JSX.extend(KJUR.asn1.DERAbstractTime, KJUR.asn1.ASN1Object);
2625 // == END DERAbstractTime ==================================================
2626 // == BEGIN DERAbstractStructured ============================================
2627 /**
2628 * base class for ASN.1 DER structured class
2629 * @name KJUR.asn1.DERAbstractStructured
2630 * @class base class for ASN.1 DER structured class
2631 * @property {Array} asn1Array internal array of ASN1Object
2632 * @extends KJUR.asn1.ASN1Object
2633 * @description
2634 * @see KJUR.asn1.ASN1Object - superclass
2635 */
2636 KJUR.asn1.DERAbstractStructured = function(params) {
2637 KJUR.asn1.DERAbstractString.superclass.constructor.call(this);
2638 var asn1Array = null;
2639
2640 /**
2641 * set value by array of ASN1Object
2642 * @name setByASN1ObjectArray
2643 * @memberOf KJUR.asn1.DERAbstractStructured
2644 * @function
2645 * @param {array} asn1ObjectArray array of ASN1Object to set
2646 */
2647 this.setByASN1ObjectArray = function(asn1ObjectArray) {
2648 this.hTLV = null;
2649 this.isModified = true;
2650 this.asn1Array = asn1ObjectArray;
2651 };
2652
2653 /**
2654 * append an ASN1Object to internal array
2655 * @name appendASN1Object
2656 * @memberOf KJUR.asn1.DERAbstractStructured
2657 * @function
2658 * @param {ASN1Object} asn1Object to add
2659 */
2660 this.appendASN1Object = function(asn1Object) {
2661 this.hTLV = null;
2662 this.isModified = true;
2663 this.asn1Array.push(asn1Object);
2664 };
2665
2666 this.asn1Array = new Array();
2667 if (typeof params != "undefined") {
2668 if (typeof params['array'] != "undefined") {
2669 this.asn1Array = params['array'];
2670 }
2671 }
2672 };
2673 JSX.extend(KJUR.asn1.DERAbstractStructured, KJUR.asn1.ASN1Object);
2674
2675 // ********************************************************************
2676 // ASN.1 Object Classes
2677 // ********************************************************************
2678 // ********************************************************************
2679 /**
2680 * class for ASN.1 DER Boolean
2681 * @name KJUR.asn1.DERBoolean
2682 * @class class for ASN.1 DER Boolean
2683 * @extends KJUR.asn1.ASN1Object
2684 * @description
2685 * @see KJUR.asn1.ASN1Object - superclass
2686 */
2687 KJUR.asn1.DERBoolean = function() {
2688 KJUR.asn1.DERBoolean.superclass.constructor.call(this);
2689 this.hT = "01";
2690 this.hTLV = "0101ff";
2691 };
2692 JSX.extend(KJUR.asn1.DERBoolean, KJUR.asn1.ASN1Object);
2693
2694 // ********************************************************************
2695 /**
2696 * class for ASN.1 DER Integer
2697 * @name KJUR.asn1.DERInteger
2698 * @class class for ASN.1 DER Integer
2699 * @extends KJUR.asn1.ASN1Object
2700 * @description
2701 * <br/>
2702 * As for argument 'params' for constructor, you can specify one of
2703 * following properties:
2704 * <ul>
2705 * <li>int - specify initial ASN.1 value(V) by integer value</li>
2706 * <li>bigint - specify initial ASN.1 value(V) by BigInteger object</li>
2707 * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
2708 * </ul>
2709 * NOTE: 'params' can be omitted.
2710 */
2711 KJUR.asn1.DERInteger = function(params) {
2712 KJUR.asn1.DERInteger.superclass.constructor.call(this);
2713 this.hT = "02";
2714
2715 /**
2716 * set value by Tom Wu's BigInteger object
2717 * @name setByBigInteger
2718 * @memberOf KJUR.asn1.DERInteger
2719 * @function
2720 * @param {BigInteger} bigIntegerValue to set
2721 */
2722 this.setByBigInteger = function(bigIntegerValue) {
2723 this.hTLV = null;
2724 this.isModified = true;
2725 this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue);
2726 };
2727
2728 /**
2729 * set value by integer value
2730 * @name setByInteger
2731 * @memberOf KJUR.asn1.DERInteger
2732 * @function
2733 * @param {Integer} integer value to set
2734 */
2735 this.setByInteger = function(intValue) {
2736 var bi = new BigInteger(String(intValue), 10);
2737 this.setByBigInteger(bi);
2738 };
2739
2740 /**
2741 * set value by integer value
2742 * @name setValueHex
2743 * @memberOf KJUR.asn1.DERInteger
2744 * @function
2745 * @param {String} hexadecimal string of integer value
2746 * @description
2747 * <br/>
2748 * NOTE: Value shall be represented by minimum octet length of
2749 * two's complement representation.
2750 */
2751 this.setValueHex = function(newHexString) {
2752 this.hV = newHexString;
2753 };
2754
2755 this.getFreshValueHex = function() {
2756 return this.hV;
2757 };
2758
2759 if (typeof params != "undefined") {
2760 if (typeof params['bigint'] != "undefined") {
2761 this.setByBigInteger(params['bigint']);
2762 } else if (typeof params['int'] != "undefined") {
2763 this.setByInteger(params['int']);
2764 } else if (typeof params['hex'] != "undefined") {
2765 this.setValueHex(params['hex']);
2766 }
2767 }
2768 };
2769 JSX.extend(KJUR.asn1.DERInteger, KJUR.asn1.ASN1Object);
2770
2771 // ********************************************************************
2772 /**
2773 * class for ASN.1 DER encoded BitString primitive
2774 * @name KJUR.asn1.DERBitString
2775 * @class class for ASN.1 DER encoded BitString primitive
2776 * @extends KJUR.asn1.ASN1Object
2777 * @description
2778 * <br/>
2779 * As for argument 'params' for constructor, you can specify one of
2780 * following properties:
2781 * <ul>
2782 * <li>bin - specify binary string (ex. '10111')</li>
2783 * <li>array - specify array of boolean (ex. [true,false,true,true])</li>
2784 * <li>hex - specify hexadecimal string of ASN.1 value(V) including unused bits</li>
2785 * </ul>
2786 * NOTE: 'params' can be omitted.
2787 */
2788 KJUR.asn1.DERBitString = function(params) {
2789 KJUR.asn1.DERBitString.superclass.constructor.call(this);
2790 this.hT = "03";
2791
2792 /**
2793 * set ASN.1 value(V) by a hexadecimal string including unused bits
2794 * @name setHexValueIncludingUnusedBits
2795 * @memberOf KJUR.asn1.DERBitString
2796 * @function
2797 * @param {String} newHexStringIncludingUnusedBits
2798 */
2799 this.setHexValueIncludingUnusedBits = function(newHexStringIncludingUnusedBits) {
2800 this.hTLV = null;
2801 this.isModified = true;
2802 this.hV = newHexStringIncludingUnusedBits;
2803 };
2804
2805 /**
2806 * set ASN.1 value(V) by unused bit and hexadecimal string of value
2807 * @name setUnusedBitsAndHexValue
2808 * @memberOf KJUR.asn1.DERBitString
2809 * @function
2810 * @param {Integer} unusedBits
2811 * @param {String} hValue
2812 */
2813 this.setUnusedBitsAndHexValue = function(unusedBits, hValue) {
2814 if (unusedBits < 0 || 7 < unusedBits) {
2815 throw "unused bits shall be from 0 to 7: u = " + unusedBits;
2816 }
2817 var hUnusedBits = "0" + unusedBits;
2818 this.hTLV = null;
2819 this.isModified = true;
2820 this.hV = hUnusedBits + hValue;
2821 };
2822
2823 /**
2824 * set ASN.1 DER BitString by binary string
2825 * @name setByBinaryString
2826 * @memberOf KJUR.asn1.DERBitString
2827 * @function
2828 * @param {String} binaryString binary value string (i.e. '10111')
2829 * @description
2830 * Its unused bits will be calculated automatically by length of
2831 * 'binaryValue'. <br/>
2832 * NOTE: Trailing zeros '0' will be ignored.
2833 */
2834 this.setByBinaryString = function(binaryString) {
2835 binaryString = binaryString.replace(/0+$/, '');
2836 var unusedBits = 8 - binaryString.length % 8;
2837 if (unusedBits == 8) unusedBits = 0;
2838 for (var i = 0; i <= unusedBits; i++) {
2839 binaryString += '0';
2840 }
2841 var h = '';
2842 for (var i = 0; i < binaryString.length - 1; i += 8) {
2843 var b = binaryString.substr(i, 8);
2844 var x = parseInt(b, 2).toString(16);
2845 if (x.length == 1) x = '0' + x;
2846 h += x;
2847 }
2848 this.hTLV = null;
2849 this.isModified = true;
2850 this.hV = '0' + unusedBits + h;
2851 };
2852
2853 /**
2854 * set ASN.1 TLV value(V) by an array of boolean
2855 * @name setByBooleanArray
2856 * @memberOf KJUR.asn1.DERBitString
2857 * @function
2858 * @param {array} booleanArray array of boolean (ex. [true, false, true])
2859 * @description
2860 * NOTE: Trailing falses will be ignored.
2861 */
2862 this.setByBooleanArray = function(booleanArray) {
2863 var s = '';
2864 for (var i = 0; i < booleanArray.length; i++) {
2865 if (booleanArray[i] == true) {
2866 s += '1';
2867 } else {
2868 s += '0';
2869 }
2870 }
2871 this.setByBinaryString(s);
2872 };
2873
2874 /**
2875 * generate an array of false with specified length
2876 * @name newFalseArray
2877 * @memberOf KJUR.asn1.DERBitString
2878 * @function
2879 * @param {Integer} nLength length of array to generate
2880 * @return {array} array of boolean faluse
2881 * @description
2882 * This static method may be useful to initialize boolean array.
2883 */
2884 this.newFalseArray = function(nLength) {
2885 var a = new Array(nLength);
2886 for (var i = 0; i < nLength; i++) {
2887 a[i] = false;
2888 }
2889 return a;
2890 };
2891
2892 this.getFreshValueHex = function() {
2893 return this.hV;
2894 };
2895
2896 if (typeof params != "undefined") {
2897 if (typeof params['hex'] != "undefined") {
2898 this.setHexValueIncludingUnusedBits(params['hex']);
2899 } else if (typeof params['bin'] != "undefined") {
2900 this.setByBinaryString(params['bin']);
2901 } else if (typeof params['array'] != "undefined") {
2902 this.setByBooleanArray(params['array']);
2903 }
2904 }
2905 };
2906 JSX.extend(KJUR.asn1.DERBitString, KJUR.asn1.ASN1Object);
2907
2908 // ********************************************************************
2909 /**
2910 * class for ASN.1 DER OctetString
2911 * @name KJUR.asn1.DEROctetString
2912 * @class class for ASN.1 DER OctetString
2913 * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
2914 * @extends KJUR.asn1.DERAbstractString
2915 * @description
2916 * @see KJUR.asn1.DERAbstractString - superclass
2917 */
2918 KJUR.asn1.DEROctetString = function(params) {
2919 KJUR.asn1.DEROctetString.superclass.constructor.call(this, params);
2920 this.hT = "04";
2921 };
2922 JSX.extend(KJUR.asn1.DEROctetString, KJUR.asn1.DERAbstractString);
2923
2924 // ********************************************************************
2925 /**
2926 * class for ASN.1 DER Null
2927 * @name KJUR.asn1.DERNull
2928 * @class class for ASN.1 DER Null
2929 * @extends KJUR.asn1.ASN1Object
2930 * @description
2931 * @see KJUR.asn1.ASN1Object - superclass
2932 */
2933 KJUR.asn1.DERNull = function() {
2934 KJUR.asn1.DERNull.superclass.constructor.call(this);
2935 this.hT = "05";
2936 this.hTLV = "0500";
2937 };
2938 JSX.extend(KJUR.asn1.DERNull, KJUR.asn1.ASN1Object);
2939
2940 // ********************************************************************
2941 /**
2942 * class for ASN.1 DER ObjectIdentifier
2943 * @name KJUR.asn1.DERObjectIdentifier
2944 * @class class for ASN.1 DER ObjectIdentifier
2945 * @param {Array} params associative array of parameters (ex. {'oid': '2.5.4.5'})
2946 * @extends KJUR.asn1.ASN1Object
2947 * @description
2948 * <br/>
2949 * As for argument 'params' for constructor, you can specify one of
2950 * following properties:
2951 * <ul>
2952 * <li>oid - specify initial ASN.1 value(V) by a oid string (ex. 2.5.4.13)</li>
2953 * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
2954 * </ul>
2955 * NOTE: 'params' can be omitted.
2956 */
2957 KJUR.asn1.DERObjectIdentifier = function(params) {
2958 var itox = function(i) {
2959 var h = i.toString(16);
2960 if (h.length == 1) h = '0' + h;
2961 return h;
2962 };
2963 var roidtox = function(roid) {
2964 var h = '';
2965 var bi = new BigInteger(roid, 10);
2966 var b = bi.toString(2);
2967 var padLen = 7 - b.length % 7;
2968 if (padLen == 7) padLen = 0;
2969 var bPad = '';
2970 for (var i = 0; i < padLen; i++) bPad += '0';
2971 b = bPad + b;
2972 for (var i = 0; i < b.length - 1; i += 7) {
2973 var b8 = b.substr(i, 7);
2974 if (i != b.length - 7) b8 = '1' + b8;
2975 h += itox(parseInt(b8, 2));
2976 }
2977 return h;
2978 }
2979
2980 KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this);
2981 this.hT = "06";
2982
2983 /**
2984 * set value by a hexadecimal string
2985 * @name setValueHex
2986 * @memberOf KJUR.asn1.DERObjectIdentifier
2987 * @function
2988 * @param {String} newHexString hexadecimal value of OID bytes
2989 */
2990 this.setValueHex = function(newHexString) {
2991 this.hTLV = null;
2992 this.isModified = true;
2993 this.s = null;
2994 this.hV = newHexString;
2995 };
2996
2997 /**
2998 * set value by a OID string
2999 * @name setValueOidString
3000 * @memberOf KJUR.asn1.DERObjectIdentifier
3001 * @function
3002 * @param {String} oidString OID string (ex. 2.5.4.13)
3003 */
3004 this.setValueOidString = function(oidString) {
3005 if (!oidString.match(/^[0-9.]+$/)) {
3006 throw "malformed oid string: " + oidString;
3007 }
3008 var h = '';
3009 var a = oidString.split('.');
3010 var i0 = parseInt(a[0]) * 40 + parseInt(a[1]);
3011 h += itox(i0);
3012 a.splice(0, 2);
3013 for (var i = 0; i < a.length; i++) {
3014 h += roidtox(a[i]);
3015 }
3016 this.hTLV = null;
3017 this.isModified = true;
3018 this.s = null;
3019 this.hV = h;
3020 };
3021
3022 /**
3023 * set value by a OID name
3024 * @name setValueName
3025 * @memberOf KJUR.asn1.DERObjectIdentifier
3026 * @function
3027 * @param {String} oidName OID name (ex. 'serverAuth')
3028 * @since 1.0.1
3029 * @description
3030 * OID name shall be defined in 'KJUR.asn1.x509.OID.name2oidList'.
3031 * Otherwise raise error.
3032 */
3033 this.setValueName = function(oidName) {
3034 if (typeof KJUR.asn1.x509.OID.name2oidList[oidName] != "undefined") {
3035 var oid = KJUR.asn1.x509.OID.name2oidList[oidName];
3036 this.setValueOidString(oid);
3037 } else {
3038 throw "DERObjectIdentifier oidName undefined: " + oidName;
3039 }
3040 };
3041
3042 this.getFreshValueHex = function() {
3043 return this.hV;
3044 };
3045
3046 if (typeof params != "undefined") {
3047 if (typeof params['oid'] != "undefined") {
3048 this.setValueOidString(params['oid']);
3049 } else if (typeof params['hex'] != "undefined") {
3050 this.setValueHex(params['hex']);
3051 } else if (typeof params['name'] != "undefined") {
3052 this.setValueName(params['name']);
3053 }
3054 }
3055 };
3056 JSX.extend(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object);
3057
3058 // ********************************************************************
3059 /**
3060 * class for ASN.1 DER UTF8String
3061 * @name KJUR.asn1.DERUTF8String
3062 * @class class for ASN.1 DER UTF8String
3063 * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
3064 * @extends KJUR.asn1.DERAbstractString
3065 * @description
3066 * @see KJUR.asn1.DERAbstractString - superclass
3067 */
3068 KJUR.asn1.DERUTF8String = function(params) {
3069 KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params);
3070 this.hT = "0c";
3071 };
3072 JSX.extend(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString);
3073
3074 // ********************************************************************
3075 /**
3076 * class for ASN.1 DER NumericString
3077 * @name KJUR.asn1.DERNumericString
3078 * @class class for ASN.1 DER NumericString
3079 * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
3080 * @extends KJUR.asn1.DERAbstractString
3081 * @description
3082 * @see KJUR.asn1.DERAbstractString - superclass
3083 */
3084 KJUR.asn1.DERNumericString = function(params) {
3085 KJUR.asn1.DERNumericString.superclass.constructor.call(this, params);
3086 this.hT = "12";
3087 };
3088 JSX.extend(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString);
3089
3090 // ********************************************************************
3091 /**
3092 * class for ASN.1 DER PrintableString
3093 * @name KJUR.asn1.DERPrintableString
3094 * @class class for ASN.1 DER PrintableString
3095 * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
3096 * @extends KJUR.asn1.DERAbstractString
3097 * @description
3098 * @see KJUR.asn1.DERAbstractString - superclass
3099 */
3100 KJUR.asn1.DERPrintableString = function(params) {
3101 KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params);
3102 this.hT = "13";
3103 };
3104 JSX.extend(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString);
3105
3106 // ********************************************************************
3107 /**
3108 * class for ASN.1 DER TeletexString
3109 * @name KJUR.asn1.DERTeletexString
3110 * @class class for ASN.1 DER TeletexString
3111 * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
3112 * @extends KJUR.asn1.DERAbstractString
3113 * @description
3114 * @see KJUR.asn1.DERAbstractString - superclass
3115 */
3116 KJUR.asn1.DERTeletexString = function(params) {
3117 KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params);
3118 this.hT = "14";
3119 };
3120 JSX.extend(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString);
3121
3122 // ********************************************************************
3123 /**
3124 * class for ASN.1 DER IA5String
3125 * @name KJUR.asn1.DERIA5String
3126 * @class class for ASN.1 DER IA5String
3127 * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
3128 * @extends KJUR.asn1.DERAbstractString
3129 * @description
3130 * @see KJUR.asn1.DERAbstractString - superclass
3131 */
3132 KJUR.asn1.DERIA5String = function(params) {
3133 KJUR.asn1.DERIA5String.superclass.constructor.call(this, params);
3134 this.hT = "16";
3135 };
3136 JSX.extend(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString);
3137
3138 // ********************************************************************
3139 /**
3140 * class for ASN.1 DER UTCTime
3141 * @name KJUR.asn1.DERUTCTime
3142 * @class class for ASN.1 DER UTCTime
3143 * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'})
3144 * @extends KJUR.asn1.DERAbstractTime
3145 * @description
3146 * <br/>
3147 * As for argument 'params' for constructor, you can specify one of
3148 * following properties:
3149 * <ul>
3150 * <li>str - specify initial ASN.1 value(V) by a string (ex.'130430235959Z')</li>
3151 * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
3152 * <li>date - specify Date object.</li>
3153 * </ul>
3154 * NOTE: 'params' can be omitted.
3155 * <h4>EXAMPLES</h4>
3156 * @example
3157 * var d1 = new KJUR.asn1.DERUTCTime();
3158 * d1.setString('130430125959Z');
3159 *
3160 * var d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'});
3161 *
3162 * var d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))});
3163 */
3164 KJUR.asn1.DERUTCTime = function(params) {
3165 KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params);
3166 this.hT = "17";
3167
3168 /**
3169 * set value by a Date object
3170 * @name setByDate
3171 * @memberOf KJUR.asn1.DERUTCTime
3172 * @function
3173 * @param {Date} dateObject Date object to set ASN.1 value(V)
3174 */
3175 this.setByDate = function(dateObject) {
3176 this.hTLV = null;
3177 this.isModified = true;
3178 this.date = dateObject;
3179 this.s = this.formatDate(this.date, 'utc');
3180 this.hV = stohex(this.s);
3181 };
3182
3183 if (typeof params != "undefined") {
3184 if (typeof params['str'] != "undefined") {
3185 this.setString(params['str']);
3186 } else if (typeof params['hex'] != "undefined") {
3187 this.setStringHex(params['hex']);
3188 } else if (typeof params['date'] != "undefined") {
3189 this.setByDate(params['date']);
3190 }
3191 }
3192 };
3193 JSX.extend(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime);
3194
3195 // ********************************************************************
3196 /**
3197 * class for ASN.1 DER GeneralizedTime
3198 * @name KJUR.asn1.DERGeneralizedTime
3199 * @class class for ASN.1 DER GeneralizedTime
3200 * @param {Array} params associative array of parameters (ex. {'str': '20130430235959Z'})
3201 * @extends KJUR.asn1.DERAbstractTime
3202 * @description
3203 * <br/>
3204 * As for argument 'params' for constructor, you can specify one of
3205 * following properties:
3206 * <ul>
3207 * <li>str - specify initial ASN.1 value(V) by a string (ex.'20130430235959Z')</li>
3208 * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
3209 * <li>date - specify Date object.</li>
3210 * </ul>
3211 * NOTE: 'params' can be omitted.
3212 */
3213 KJUR.asn1.DERGeneralizedTime = function(params) {
3214 KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params);
3215 this.hT = "18";
3216
3217 /**
3218 * set value by a Date object
3219 * @name setByDate
3220 * @memberOf KJUR.asn1.DERGeneralizedTime
3221 * @function
3222 * @param {Date} dateObject Date object to set ASN.1 value(V)
3223 * @example
3224 * When you specify UTC time, use 'Date.UTC' method like this:<br/>
3225 * var o = new DERUTCTime();
3226 * var date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59
3227 * o.setByDate(date);
3228 */
3229 this.setByDate = function(dateObject) {
3230 this.hTLV = null;
3231 this.isModified = true;
3232 this.date = dateObject;
3233 this.s = this.formatDate(this.date, 'gen');
3234 this.hV = stohex(this.s);
3235 };
3236
3237 if (typeof params != "undefined") {
3238 if (typeof params['str'] != "undefined") {
3239 this.setString(params['str']);
3240 } else if (typeof params['hex'] != "undefined") {
3241 this.setStringHex(params['hex']);
3242 } else if (typeof params['date'] != "undefined") {
3243 this.setByDate(params['date']);
3244 }
3245 }
3246 };
3247 JSX.extend(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime);
3248
3249 // ********************************************************************
3250 /**
3251 * class for ASN.1 DER Sequence
3252 * @name KJUR.asn1.DERSequence
3253 * @class class for ASN.1 DER Sequence
3254 * @extends KJUR.asn1.DERAbstractStructured
3255 * @description
3256 * <br/>
3257 * As for argument 'params' for constructor, you can specify one of
3258 * following properties:
3259 * <ul>
3260 * <li>array - specify array of ASN1Object to set elements of content</li>
3261 * </ul>
3262 * NOTE: 'params' can be omitted.
3263 */
3264 KJUR.asn1.DERSequence = function(params) {
3265 KJUR.asn1.DERSequence.superclass.constructor.call(this, params);
3266 this.hT = "30";
3267 this.getFreshValueHex = function() {
3268 var h = '';
3269 for (var i = 0; i < this.asn1Array.length; i++) {
3270 var asn1Obj = this.asn1Array[i];
3271 h += asn1Obj.getEncodedHex();
3272 }
3273 this.hV = h;
3274 return this.hV;
3275 };
3276 };
3277 JSX.extend(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured);
3278
3279 // ********************************************************************
3280 /**
3281 * class for ASN.1 DER Set
3282 * @name KJUR.asn1.DERSet
3283 * @class class for ASN.1 DER Set
3284 * @extends KJUR.asn1.DERAbstractStructured
3285 * @description
3286 * <br/>
3287 * As for argument 'params' for constructor, you can specify one of
3288 * following properties:
3289 * <ul>
3290 * <li>array - specify array of ASN1Object to set elements of content</li>
3291 * </ul>
3292 * NOTE: 'params' can be omitted.
3293 */
3294 KJUR.asn1.DERSet = function(params) {
3295 KJUR.asn1.DERSet.superclass.constructor.call(this, params);
3296 this.hT = "31";
3297 this.getFreshValueHex = function() {
3298 var a = new Array();
3299 for (var i = 0; i < this.asn1Array.length; i++) {
3300 var asn1Obj = this.asn1Array[i];
3301 a.push(asn1Obj.getEncodedHex());
3302 }
3303 a.sort();
3304 this.hV = a.join('');
3305 return this.hV;
3306 };
3307 };
3308 JSX.extend(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured);
3309
3310 // ********************************************************************
3311 /**
3312 * class for ASN.1 DER TaggedObject
3313 * @name KJUR.asn1.DERTaggedObject
3314 * @class class for ASN.1 DER TaggedObject
3315 * @extends KJUR.asn1.ASN1Object
3316 * @description
3317 * <br/>
3318 * Parameter 'tagNoNex' is ASN.1 tag(T) value for this object.
3319 * For example, if you find '[1]' tag in a ASN.1 dump,
3320 * 'tagNoHex' will be 'a1'.
3321 * <br/>
3322 * As for optional argument 'params' for constructor, you can specify *ANY* of
3323 * following properties:
3324 * <ul>
3325 * <li>explicit - specify true if this is explicit tag otherwise false
3326 * (default is 'true').</li>
3327 * <li>tag - specify tag (default is 'a0' which means [0])</li>
3328 * <li>obj - specify ASN1Object which is tagged</li>
3329 * </ul>
3330 * @example
3331 * d1 = new KJUR.asn1.DERUTF8String({'str':'a'});
3332 * d2 = new KJUR.asn1.DERTaggedObject({'obj': d1});
3333 * hex = d2.getEncodedHex();
3334 */
3335 KJUR.asn1.DERTaggedObject = function(params) {
3336 KJUR.asn1.DERTaggedObject.superclass.constructor.call(this);
3337 this.hT = "a0";
3338 this.hV = '';
3339 this.isExplicit = true;
3340 this.asn1Object = null;
3341
3342 /**
3343 * set value by an ASN1Object
3344 * @name setString
3345 * @memberOf KJUR.asn1.DERTaggedObject
3346 * @function
3347 * @param {Boolean} isExplicitFlag flag for explicit/implicit tag
3348 * @param {Integer} tagNoHex hexadecimal string of ASN.1 tag
3349 * @param {ASN1Object} asn1Object ASN.1 to encapsulate
3350 */
3351 this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) {
3352 this.hT = tagNoHex;
3353 this.isExplicit = isExplicitFlag;
3354 this.asn1Object = asn1Object;
3355 if (this.isExplicit) {
3356 this.hV = this.asn1Object.getEncodedHex();
3357 this.hTLV = null;
3358 this.isModified = true;
3359 } else {
3360 this.hV = null;
3361 this.hTLV = asn1Object.getEncodedHex();
3362 this.hTLV = this.hTLV.replace(/^../, tagNoHex);
3363 this.isModified = false;
3364 }
3365 };
3366
3367 this.getFreshValueHex = function() {
3368 return this.hV;
3369 };
3370
3371 if (typeof params != "undefined") {
3372 if (typeof params['tag'] != "undefined") {
3373 this.hT = params['tag'];
3374 }
3375 if (typeof params['explicit'] != "undefined") {
3376 this.isExplicit = params['explicit'];
3377 }
3378 if (typeof params['obj'] != "undefined") {
3379 this.asn1Object = params['obj'];
3380 this.setASN1Object(this.isExplicit, this.hT, this.asn1Object);
3381 }
3382 }
3383 };
3384 JSX.extend(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object);
3385 // Hex JavaScript decoder
3386 // Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
3387 // Permission to use, copy, modify, and/or distribute this software for any
3388 // purpose with or without fee is hereby granted, provided that the above
3389 // copyright notice and this permission notice appear in all copies.
3390 //
3391 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3392 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3393 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3394 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3395 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3396 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3397 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3398 /*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
3399 (function(undefined) {
3400 "use strict";
3401
3402 var Hex = {},
3403 decoder;
3404
3405 Hex.decode = function(a) {
3406 var i;
3407 if (decoder === undefined) {
3408 var hex = "0123456789ABCDEF",
3409 ignore = " \f\n\r\t\u00A0\u2028\u2029";
3410 decoder = [];
3411 for (i = 0; i < 16; ++i) decoder[hex.charAt(i)] = i;
3412 hex = hex.toLowerCase();
3413 for (i = 10; i < 16; ++i) decoder[hex.charAt(i)] = i;
3414 for (i = 0; i < ignore.length; ++i) decoder[ignore.charAt(i)] = -1;
3415 }
3416 var out = [],
3417 bits = 0,
3418 char_count = 0;
3419 for (i = 0; i < a.length; ++i) {
3420 var c = a.charAt(i);
3421 if (c == '=') break;
3422 c = decoder[c];
3423 if (c == -1) continue;
3424 if (c === undefined) throw 'Illegal character at offset ' + i;
3425 bits |= c;
3426 if (++char_count >= 2) {
3427 out[out.length] = bits;
3428 bits = 0;
3429 char_count = 0;
3430 } else {
3431 bits <<= 4;
3432 }
3433 }
3434 if (char_count) throw "Hex encoding incomplete: 4 bits missing";
3435 return out;
3436 };
3437
3438 // export globals
3439 window.Hex = Hex;
3440 })();
3441 // Base64 JavaScript decoder
3442 // Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
3443 // Permission to use, copy, modify, and/or distribute this software for any
3444 // purpose with or without fee is hereby granted, provided that the above
3445 // copyright notice and this permission notice appear in all copies.
3446 //
3447 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3448 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3449 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3450 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3451 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3452 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3453 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3454 /*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
3455 (function(undefined) {
3456 "use strict";
3457
3458 var Base64 = {},
3459 decoder;
3460
3461 Base64.decode = function(a) {
3462 var i;
3463 if (decoder === undefined) {
3464 var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
3465 ignore = "= \f\n\r\t\u00A0\u2028\u2029";
3466 decoder = [];
3467 for (i = 0; i < 64; ++i) decoder[b64.charAt(i)] = i;
3468 for (i = 0; i < ignore.length; ++i) decoder[ignore.charAt(i)] = -1;
3469 }
3470 var out = [];
3471 var bits = 0,
3472 char_count = 0;
3473 for (i = 0; i < a.length; ++i) {
3474 var c = a.charAt(i);
3475 if (c == '=') break;
3476 c = decoder[c];
3477 if (c == -1) continue;
3478 if (c === undefined) throw 'Illegal character at offset ' + i;
3479 bits |= c;
3480 if (++char_count >= 4) {
3481 out[out.length] = (bits >> 16);
3482 out[out.length] = (bits >> 8) & 0xFF;
3483 out[out.length] = bits & 0xFF;
3484 bits = 0;
3485 char_count = 0;
3486 } else {
3487 bits <<= 6;
3488 }
3489 }
3490 switch (char_count) {
3491 case 1:
3492 throw "Base64 encoding incomplete: at least 2 bits missing";
3493 case 2:
3494 out[out.length] = (bits >> 10);
3495 break;
3496 case 3:
3497 out[out.length] = (bits >> 16);
3498 out[out.length] = (bits >> 8) & 0xFF;
3499 break;
3500 }
3501 return out;
3502 };
3503
3504 Base64.re = /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/;
3505 Base64.unarmor = function(a) {
3506 var m = Base64.re.exec(a);
3507 if (m) {
3508 if (m[1]) a = m[1];
3509 else if (m[2]) a = m[2];
3510 else throw "RegExp out of sync";
3511 }
3512 return Base64.decode(a);
3513 };
3514
3515 // export globals
3516 window.Base64 = Base64;
3517 })();
3518 // ASN.1 JavaScript decoder
3519 // Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
3520 // Permission to use, copy, modify, and/or distribute this software for any
3521 // purpose with or without fee is hereby granted, provided that the above
3522 // copyright notice and this permission notice appear in all copies.
3523 //
3524 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
3525 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
3526 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
3527 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
3528 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
3529 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
3530 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3531 /*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
3532 /*global oids */
3533 (function(undefined) {
3534 "use strict";
3535
3536 var hardLimit = 100,
3537 ellipsis = "\u2026",
3538 DOM = {
3539 tag: function(tagName, className) {
3540 var t = document.createElement(tagName);
3541 t.className = className;
3542 return t;
3543 },
3544 text: function(str) {
3545 return document.createTextNode(str);
3546 }
3547 };
3548
3549 function Stream(enc, pos) {
3550 if (enc instanceof Stream) {
3551 this.enc = enc.enc;
3552 this.pos = enc.pos;
3553 } else {
3554 this.enc = enc;
3555 this.pos = pos;
3556 }
3557 }
3558 Stream.prototype.get = function(pos) {
3559 if (pos === undefined) pos = this.pos++;
3560 if (pos >= this.enc.length) throw 'Requesting byte offset ' + pos + ' on a stream of length ' + this.enc.length;
3561 return this.enc[pos];
3562 };
3563 Stream.prototype.hexDigits = "0123456789ABCDEF";
3564 Stream.prototype.hexByte = function(b) {
3565 return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF);
3566 };
3567 Stream.prototype.hexDump = function(start, end, raw) {
3568 var s = "";
3569 for (var i = start; i < end; ++i) {
3570 s += this.hexByte(this.get(i));
3571 if (raw !== true) switch (i & 0xF) {
3572 case 0x7:
3573 s += " ";
3574 break;
3575 case 0xF:
3576 s += "\n";
3577 break;
3578 default:
3579 s += " ";
3580 }
3581 }
3582 return s;
3583 };
3584 Stream.prototype.parseStringISO = function(start, end) {
3585 var s = "";
3586 for (var i = start; i < end; ++i) s += String.fromCharCode(this.get(i));
3587 return s;
3588 };
3589 Stream.prototype.parseStringUTF = function(start, end) {
3590 var s = "";
3591 for (var i = start; i < end;) {
3592 var c = this.get(i++);
3593 if (c < 128) s += String.fromCharCode(c);
3594 else if ((c > 191) && (c < 224)) s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F));
3595 else s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F));
3596 }
3597 return s;
3598 };
3599 Stream.prototype.parseStringBMP = function(start, end) {
3600 var str = ""
3601 for (var i = start; i < end; i += 2) {
3602 var high_byte = this.get(i);
3603 var low_byte = this.get(i + 1);
3604 str += String.fromCharCode((high_byte << 8) + low_byte);
3605 }
3606
3607 return str;
3608 };
3609 Stream.prototype.reTime = /^((?:1[89]|2\d)?\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
3610 Stream.prototype.parseTime = function(start, end) {
3611 var s = this.parseStringISO(start, end),
3612 m = this.reTime.exec(s);
3613 if (!m) return "Unrecognized time: " + s;
3614 s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4];
3615 if (m[5]) {
3616 s += ":" + m[5];
3617 if (m[6]) {
3618 s += ":" + m[6];
3619 if (m[7]) s += "." + m[7];
3620 }
3621 }
3622 if (m[8]) {
3623 s += " UTC";
3624 if (m[8] != 'Z') {
3625 s += m[8];
3626 if (m[9]) s += ":" + m[9];
3627 }
3628 }
3629 return s;
3630 };
3631 Stream.prototype.parseInteger = function(start, end) {
3632 //TODO support negative numbers
3633 var len = end - start;
3634 if (len > 4) {
3635 len <<= 3;
3636 var s = this.get(start);
3637 if (s === 0) len -= 8;
3638 else while (s < 128) {
3639 s <<= 1; --len;
3640 }
3641 return "(" + len + " bit)";
3642 }
3643 var n = 0;
3644 for (var i = start; i < end; ++i) n = (n << 8) | this.get(i);
3645 return n;
3646 };
3647 Stream.prototype.parseBitString = function(start, end) {
3648 var unusedBit = this.get(start),
3649 lenBit = ((end - start - 1) << 3) - unusedBit,
3650 s = "(" + lenBit + " bit)";
3651 if (lenBit <= 20) {
3652 var skip = unusedBit;
3653 s += " ";
3654 for (var i = end - 1; i > start; --i) {
3655 var b = this.get(i);
3656 for (var j = skip; j < 8; ++j) s += (b >> j) & 1 ? "1": "0";
3657 skip = 0;
3658 }
3659 }
3660 return s;
3661 };
3662 Stream.prototype.parseOctetString = function(start, end) {
3663 var len = end - start,
3664 s = "(" + len + " byte) ";
3665 if (len > hardLimit) end = start + hardLimit;
3666 for (var i = start; i < end; ++i) s += this.hexByte(this.get(i)); //TODO: also try Latin1?
3667 if (len > hardLimit) s += ellipsis;
3668 return s;
3669 };
3670 Stream.prototype.parseOID = function(start, end) {
3671 var s = '',
3672 n = 0,
3673 bits = 0;
3674 for (var i = start; i < end; ++i) {
3675 var v = this.get(i);
3676 n = (n << 7) | (v & 0x7F);
3677 bits += 7;
3678 if (! (v & 0x80)) { // finished
3679 if (s === '') {
3680 var m = n < 80 ? n < 40 ? 0 : 1 : 2;
3681 s = m + "." + (n - m * 40);
3682 } else s += "." + ((bits >= 31) ? "bigint": n);
3683 n = bits = 0;
3684 }
3685 }
3686 return s;
3687 };
3688
3689 function ASN1(stream, header, length, tag, sub) {
3690 this.stream = stream;
3691 this.header = header;
3692 this.length = length;
3693 this.tag = tag;
3694 this.sub = sub;
3695 }
3696 ASN1.prototype.typeName = function() {
3697 if (this.tag === undefined) return "unknown";
3698 var tagClass = this.tag >> 6,
3699 tagConstructed = (this.tag >> 5) & 1,
3700 tagNumber = this.tag & 0x1F;
3701 switch (tagClass) {
3702 case 0:
3703 // universal
3704 switch (tagNumber) {
3705 case 0x00:
3706 return "EOC";
3707 case 0x01:
3708 return "BOOLEAN";
3709 case 0x02:
3710 return "INTEGER";
3711 case 0x03:
3712 return "BIT_STRING";
3713 case 0x04:
3714 return "OCTET_STRING";
3715 case 0x05:
3716 return "NULL";
3717 case 0x06:
3718 return "OBJECT_IDENTIFIER";
3719 case 0x07:
3720 return "ObjectDescriptor";
3721 case 0x08:
3722 return "EXTERNAL";
3723 case 0x09:
3724 return "REAL";
3725 case 0x0A:
3726 return "ENUMERATED";
3727 case 0x0B:
3728 return "EMBEDDED_PDV";
3729 case 0x0C:
3730 return "UTF8String";
3731 case 0x10:
3732 return "SEQUENCE";
3733 case 0x11:
3734 return "SET";
3735 case 0x12:
3736 return "NumericString";
3737 case 0x13:
3738 return "PrintableString"; // ASCII subset
3739 case 0x14:
3740 return "TeletexString"; // aka T61String
3741 case 0x15:
3742 return "VideotexString";
3743 case 0x16:
3744 return "IA5String"; // ASCII
3745 case 0x17:
3746 return "UTCTime";
3747 case 0x18:
3748 return "GeneralizedTime";
3749 case 0x19:
3750 return "GraphicString";
3751 case 0x1A:
3752 return "VisibleString"; // ASCII subset
3753 case 0x1B:
3754 return "GeneralString";
3755 case 0x1C:
3756 return "UniversalString";
3757 case 0x1E:
3758 return "BMPString";
3759 default:
3760 return "Universal_" + tagNumber.toString(16);
3761 }
3762 case 1:
3763 return "Application_" + tagNumber.toString(16);
3764 case 2:
3765 return "[" + tagNumber + "]"; // Context
3766 case 3:
3767 return "Private_" + tagNumber.toString(16);
3768 }
3769 };
3770 ASN1.prototype.reSeemsASCII = /^[ -~]+$/;
3771 ASN1.prototype.content = function() {
3772 if (this.tag === undefined) return null;
3773 var tagClass = this.tag >> 6,
3774 tagNumber = this.tag & 0x1F,
3775 content = this.posContent(),
3776 len = Math.abs(this.length);
3777 if (tagClass !== 0) { // universal
3778 if (this.sub !== null) return "(" + this.sub.length + " elem)";
3779 //TODO: TRY TO PARSE ASCII STRING
3780 var s = this.stream.parseStringISO(content, content + Math.min(len, hardLimit));
3781 if (this.reSeemsASCII.test(s)) return s.substring(0, 2 * hardLimit) + ((s.length > 2 * hardLimit) ? ellipsis: "");
3782 else return this.stream.parseOctetString(content, content + len);
3783 }
3784 switch (tagNumber) {
3785 case 0x01:
3786 // BOOLEAN
3787 return (this.stream.get(content) === 0) ? "false": "true";
3788 case 0x02:
3789 // INTEGER
3790 return this.stream.parseInteger(content, content + len);
3791 case 0x03:
3792 // BIT_STRING
3793 return this.sub ? "(" + this.sub.length + " elem)": this.stream.parseBitString(content, content + len);
3794 case 0x04:
3795 // OCTET_STRING
3796 return this.sub ? "(" + this.sub.length + " elem)": this.stream.parseOctetString(content, content + len);
3797 //case 0x05: // NULL
3798 case 0x06:
3799 // OBJECT_IDENTIFIER
3800 return this.stream.parseOID(content, content + len);
3801 //case 0x07: // ObjectDescriptor
3802 //case 0x08: // EXTERNAL
3803 //case 0x09: // REAL
3804 //case 0x0A: // ENUMERATED
3805 //case 0x0B: // EMBEDDED_PDV
3806 case 0x10:
3807 // SEQUENCE
3808 case 0x11:
3809 // SET
3810 return "(" + this.sub.length + " elem)";
3811 case 0x0C:
3812 // UTF8String
3813 return this.stream.parseStringUTF(content, content + len);
3814 case 0x12:
3815 // NumericString
3816 case 0x13:
3817 // PrintableString
3818 case 0x14:
3819 // TeletexString
3820 case 0x15:
3821 // VideotexString
3822 case 0x16:
3823 // IA5String
3824 //case 0x19: // GraphicString
3825 case 0x1A:
3826 // VisibleString
3827 //case 0x1B: // GeneralString
3828 //case 0x1C: // UniversalString
3829 return this.stream.parseStringISO(content, content + len);
3830 case 0x1E:
3831 // BMPString
3832 return this.stream.parseStringBMP(content, content + len);
3833 case 0x17:
3834 // UTCTime
3835 case 0x18:
3836 // GeneralizedTime
3837 return this.stream.parseTime(content, content + len);
3838 }
3839 return null;
3840 };
3841 ASN1.prototype.toString = function() {
3842 return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? 'null': this.sub.length) + "]";
3843 };
3844 ASN1.prototype.print = function(indent) {
3845 if (indent === undefined) indent = '';
3846 document.writeln(indent + this);
3847 if (this.sub !== null) {
3848 indent += ' ';
3849 for (var i = 0,
3850 max = this.sub.length; i < max; ++i) this.sub[i].print(indent);
3851 }
3852 };
3853 ASN1.prototype.toPrettyString = function(indent) {
3854 if (indent === undefined) indent = '';
3855 var s = indent + this.typeName() + " @" + this.stream.pos;
3856 if (this.length >= 0) s += "+";
3857 s += this.length;
3858 if (this.tag & 0x20) s += " (constructed)";
3859 else if (((this.tag == 0x03) || (this.tag == 0x04)) && (this.sub !== null)) s += " (encapsulates)";
3860 s += "\n";
3861 if (this.sub !== null) {
3862 indent += ' ';
3863 for (var i = 0,
3864 max = this.sub.length; i < max; ++i) s += this.sub[i].toPrettyString(indent);
3865 }
3866 return s;
3867 };
3868 ASN1.prototype.toDOM = function() {
3869 var node = DOM.tag("div", "node");
3870 node.asn1 = this;
3871 var head = DOM.tag("div", "head");
3872 var s = this.typeName().replace(/_/g, " ");
3873 head.innerHTML = s;
3874 var content = this.content();
3875 if (content !== null) {
3876 content = String(content).replace(/</g, "&lt;");
3877 var preview = DOM.tag("span", "preview");
3878 preview.appendChild(DOM.text(content));
3879 head.appendChild(preview);
3880 }
3881 node.appendChild(head);
3882 this.node = node;
3883 this.head = head;
3884 var value = DOM.tag("div", "value");
3885 s = "Offset: " + this.stream.pos + "<br/>";
3886 s += "Length: " + this.header + "+";
3887 if (this.length >= 0) s += this.length;
3888 else s += ( - this.length) + " (undefined)";
3889 if (this.tag & 0x20) s += "<br/>(constructed)";
3890 else if (((this.tag == 0x03) || (this.tag == 0x04)) && (this.sub !== null)) s += "<br/>(encapsulates)";
3891 //TODO if (this.tag == 0x03) s += "Unused bits: "
3892 if (content !== null) {
3893 s += "<br/>Value:<br/><b>" + content + "</b>";
3894 if ((typeof oids === 'object') && (this.tag == 0x06)) {
3895 var oid = oids[content];
3896 if (oid) {
3897 if (oid.d) s += "<br/>" + oid.d;
3898 if (oid.c) s += "<br/>" + oid.c;
3899 if (oid.w) s += "<br/>(warning!)";
3900 }
3901 }
3902 }
3903 value.innerHTML = s;
3904 node.appendChild(value);
3905 var sub = DOM.tag("div", "sub");
3906 if (this.sub !== null) {
3907 for (var i = 0,
3908 max = this.sub.length; i < max; ++i) sub.appendChild(this.sub[i].toDOM());
3909 }
3910 node.appendChild(sub);
3911 head.onclick = function() {
3912 node.className = (node.className == "node collapsed") ? "node": "node collapsed";
3913 };
3914 return node;
3915 };
3916 ASN1.prototype.posStart = function() {
3917 return this.stream.pos;
3918 };
3919 ASN1.prototype.posContent = function() {
3920 return this.stream.pos + this.header;
3921 };
3922 ASN1.prototype.posEnd = function() {
3923 return this.stream.pos + this.header + Math.abs(this.length);
3924 };
3925 ASN1.prototype.fakeHover = function(current) {
3926 this.node.className += " hover";
3927 if (current) this.head.className += " hover";
3928 };
3929 ASN1.prototype.fakeOut = function(current) {
3930 var re = / ?hover/;
3931 this.node.className = this.node.className.replace(re, "");
3932 if (current) this.head.className = this.head.className.replace(re, "");
3933 };
3934 ASN1.prototype.toHexDOM_sub = function(node, className, stream, start, end) {
3935 if (start >= end) return;
3936 var sub = DOM.tag("span", className);
3937 sub.appendChild(DOM.text(stream.hexDump(start, end)));
3938 node.appendChild(sub);
3939 };
3940 ASN1.prototype.toHexDOM = function(root) {
3941 var node = DOM.tag("span", "hex");
3942 if (root === undefined) root = node;
3943 this.head.hexNode = node;
3944 this.head.onmouseover = function() {
3945 this.hexNode.className = "hexCurrent";
3946 };
3947 this.head.onmouseout = function() {
3948 this.hexNode.className = "hex";
3949 };
3950 node.asn1 = this;
3951 node.onmouseover = function() {
3952 var current = !root.selected;
3953 if (current) {
3954 root.selected = this.asn1;
3955 this.className = "hexCurrent";
3956 }
3957 this.asn1.fakeHover(current);
3958 };
3959 node.onmouseout = function() {
3960 var current = (root.selected == this.asn1);
3961 this.asn1.fakeOut(current);
3962 if (current) {
3963 root.selected = null;
3964 this.className = "hex";
3965 }
3966 };
3967 this.toHexDOM_sub(node, "tag", this.stream, this.posStart(), this.posStart() + 1);
3968 this.toHexDOM_sub(node, (this.length >= 0) ? "dlen": "ulen", this.stream, this.posStart() + 1, this.posContent());
3969 if (this.sub === null) node.appendChild(DOM.text(this.stream.hexDump(this.posContent(), this.posEnd())));
3970 else if (this.sub.length > 0) {
3971 var first = this.sub[0];
3972 var last = this.sub[this.sub.length - 1];
3973 this.toHexDOM_sub(node, "intro", this.stream, this.posContent(), first.posStart());
3974 for (var i = 0,
3975 max = this.sub.length; i < max; ++i) node.appendChild(this.sub[i].toHexDOM(root));
3976 this.toHexDOM_sub(node, "outro", this.stream, last.posEnd(), this.posEnd());
3977 }
3978 return node;
3979 };
3980 ASN1.prototype.toHexString = function(root) {
3981 return this.stream.hexDump(this.posStart(), this.posEnd(), true);
3982 };
3983 ASN1.decodeLength = function(stream) {
3984 var buf = stream.get(),
3985 len = buf & 0x7F;
3986 if (len == buf) return len;
3987 if (len > 3) throw "Length over 24 bits not supported at position " + (stream.pos - 1);
3988 if (len === 0) return - 1; // undefined
3989 buf = 0;
3990 for (var i = 0; i < len; ++i) buf = (buf << 8) | stream.get();
3991 return buf;
3992 };
3993 ASN1.hasContent = function(tag, len, stream) {
3994 if (tag & 0x20) // constructed
3995 return true;
3996 if ((tag < 0x03) || (tag > 0x04)) return false;
3997 var p = new Stream(stream);
3998 if (tag == 0x03) p.get(); // BitString unused bits, must be in [0, 7]
3999 var subTag = p.get();
4000 if ((subTag >> 6) & 0x01) // not (universal or context)
4001 return false;
4002 try {
4003 var subLength = ASN1.decodeLength(p);
4004 return ((p.pos - stream.pos) + subLength == len);
4005 } catch(exception) {
4006 return false;
4007 }
4008 };
4009 ASN1.decode = function(stream) {
4010 if (! (stream instanceof Stream)) stream = new Stream(stream, 0);
4011 var streamStart = new Stream(stream),
4012 tag = stream.get(),
4013 len = ASN1.decodeLength(stream),
4014 header = stream.pos - streamStart.pos,
4015 sub = null;
4016 if (ASN1.hasContent(tag, len, stream)) {
4017 // it has content, so we decode it
4018 var start = stream.pos;
4019 if (tag == 0x03) stream.get(); // skip BitString unused bits, must be in [0, 7]
4020 sub = [];
4021 if (len >= 0) {
4022 // definite length
4023 var end = start + len;
4024 while (stream.pos < end) sub[sub.length] = ASN1.decode(stream);
4025 if (stream.pos != end) throw "Content size is not correct for container starting at offset " + start;
4026 } else {
4027 // undefined length
4028 try {
4029 for (;;) {
4030 var s = ASN1.decode(stream);
4031 if (s.tag === 0) break;
4032 sub[sub.length] = s;
4033 }
4034 len = start - stream.pos;
4035 } catch(e) {
4036 throw "Exception while decoding undefined length content: " + e;
4037 }
4038 }
4039 } else stream.pos += len; // skip content
4040 return new ASN1(streamStart, header, len, tag, sub);
4041 };
4042 ASN1.test = function() {
4043 var test = [{
4044 value: [0x27],
4045 expected: 0x27
4046 },
4047 {
4048 value: [0x81, 0xC9],
4049 expected: 0xC9
4050 },
4051 {
4052 value: [0x83, 0xFE, 0xDC, 0xBA],
4053 expected: 0xFEDCBA
4054 }];
4055 for (var i = 0,
4056 max = test.length; i < max; ++i) {
4057 var pos = 0,
4058 stream = new Stream(test[i].value, 0),
4059 res = ASN1.decodeLength(stream);
4060 if (res != test[i].expected) document.write("In test[" + i + "] expected " + test[i].expected + " got " + res + "\n");
4061 }
4062 };
4063
4064 // export globals
4065 window.ASN1 = ASN1;
4066 })();
4067 /**
4068 * Retrieve the hexadecimal value (as a string) of the current ASN.1 element
4069 * @returns {string}
4070 * @public
4071 */
4072 ASN1.prototype.getHexStringValue = function() {
4073 var hexString = this.toHexString();
4074 var offset = this.header * 2;
4075 var length = this.length * 2;
4076 return hexString.substr(offset, length);
4077 };
4078
4079 /**
4080 * Method to parse a pem encoded string containing both a public or private key.
4081 * The method will translate the pem encoded string in a der encoded string and
4082 * will parse private key and public key parameters. This method accepts public key
4083 * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
4084 *
4085 * @todo Check how many rsa formats use the same format of pkcs #1.
4086 *
4087 * The format is defined as:
4088 * PublicKeyInfo ::= SEQUENCE {
4089 * algorithm AlgorithmIdentifier,
4090 * PublicKey BIT STRING
4091 * }
4092 * Where AlgorithmIdentifier is:
4093 * AlgorithmIdentifier ::= SEQUENCE {
4094 * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
4095 * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
4096 * }
4097 * and PublicKey is a SEQUENCE encapsulated in a BIT STRING
4098 * RSAPublicKey ::= SEQUENCE {
4099 * modulus INTEGER, -- n
4100 * publicExponent INTEGER -- e
4101 * }
4102 * it's possible to examine the structure of the keys obtained from openssl using
4103 * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/
4104 * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer
4105 * @private
4106 */
4107 RSAKey.prototype.parseKey = function(pem) {
4108 try {
4109 var modulus = 0;
4110 var public_exponent = 0;
4111 var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
4112 var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
4113 var asn1 = ASN1.decode(der);
4114
4115 //Fixes a bug with OpenSSL 1.0+ private keys
4116 if (asn1.sub.length === 3) {
4117 asn1 = asn1.sub[2].sub[0];
4118 }
4119 if (asn1.sub.length === 9) {
4120
4121 // Parse the private key.
4122 modulus = asn1.sub[1].getHexStringValue(); //bigint
4123 this.n = parseBigInt(modulus, 16);
4124
4125 public_exponent = asn1.sub[2].getHexStringValue(); //int
4126 this.e = parseInt(public_exponent, 16);
4127
4128 var private_exponent = asn1.sub[3].getHexStringValue(); //bigint
4129 this.d = parseBigInt(private_exponent, 16);
4130
4131 var prime1 = asn1.sub[4].getHexStringValue(); //bigint
4132 this.p = parseBigInt(prime1, 16);
4133
4134 var prime2 = asn1.sub[5].getHexStringValue(); //bigint
4135 this.q = parseBigInt(prime2, 16);
4136
4137 var exponent1 = asn1.sub[6].getHexStringValue(); //bigint
4138 this.dmp1 = parseBigInt(exponent1, 16);
4139
4140 var exponent2 = asn1.sub[7].getHexStringValue(); //bigint
4141 this.dmq1 = parseBigInt(exponent2, 16);
4142
4143 var coefficient = asn1.sub[8].getHexStringValue(); //bigint
4144 this.coeff = parseBigInt(coefficient, 16);
4145
4146 } else if (asn1.sub.length === 2) {
4147
4148 // Parse the public key.
4149 var bit_string = asn1.sub[1];
4150 var sequence = bit_string.sub[0];
4151
4152 modulus = sequence.sub[0].getHexStringValue();
4153 this.n = parseBigInt(modulus, 16);
4154 public_exponent = sequence.sub[1].getHexStringValue();
4155 this.e = parseInt(public_exponent, 16);
4156
4157 } else {
4158 return false;
4159 }
4160 return true;
4161 } catch(ex) {
4162 return false;
4163 }
4164 };
4165
4166 /**
4167 * Translate rsa parameters in a hex encoded string representing the rsa key.
4168 *
4169 * The translation follow the ASN.1 notation :
4170 * RSAPrivateKey ::= SEQUENCE {
4171 * version Version,
4172 * modulus INTEGER, -- n
4173 * publicExponent INTEGER, -- e
4174 * privateExponent INTEGER, -- d
4175 * prime1 INTEGER, -- p
4176 * prime2 INTEGER, -- q
4177 * exponent1 INTEGER, -- d mod (p1)
4178 * exponent2 INTEGER, -- d mod (q-1)
4179 * coefficient INTEGER, -- (inverse of q) mod p
4180 * }
4181 * @returns {string} DER Encoded String representing the rsa private key
4182 * @private
4183 */
4184 RSAKey.prototype.getPrivateBaseKey = function() {
4185 var options = {
4186 'array': [new KJUR.asn1.DERInteger({
4187 'int': 0
4188 }), new KJUR.asn1.DERInteger({
4189 'bigint': this.n
4190 }), new KJUR.asn1.DERInteger({
4191 'int': this.e
4192 }), new KJUR.asn1.DERInteger({
4193 'bigint': this.d
4194 }), new KJUR.asn1.DERInteger({
4195 'bigint': this.p
4196 }), new KJUR.asn1.DERInteger({
4197 'bigint': this.q
4198 }), new KJUR.asn1.DERInteger({
4199 'bigint': this.dmp1
4200 }), new KJUR.asn1.DERInteger({
4201 'bigint': this.dmq1
4202 }), new KJUR.asn1.DERInteger({
4203 'bigint': this.coeff
4204 })]
4205 };
4206 var seq = new KJUR.asn1.DERSequence(options);
4207 return seq.getEncodedHex();
4208 };
4209
4210 /**
4211 * base64 (pem) encoded version of the DER encoded representation
4212 * @returns {string} pem encoded representation without header and footer
4213 * @public
4214 */
4215 RSAKey.prototype.getPrivateBaseKeyB64 = function() {
4216 return hex2b64(this.getPrivateBaseKey());
4217 };
4218
4219 /**
4220 * Translate rsa parameters in a hex encoded string representing the rsa public key.
4221 * The representation follow the ASN.1 notation :
4222 * PublicKeyInfo ::= SEQUENCE {
4223 * algorithm AlgorithmIdentifier,
4224 * PublicKey BIT STRING
4225 * }
4226 * Where AlgorithmIdentifier is:
4227 * AlgorithmIdentifier ::= SEQUENCE {
4228 * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
4229 * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
4230 * }
4231 * and PublicKey is a SEQUENCE encapsulated in a BIT STRING
4232 * RSAPublicKey ::= SEQUENCE {
4233 * modulus INTEGER, -- n
4234 * publicExponent INTEGER -- e
4235 * }
4236 * @returns {string} DER Encoded String representing the rsa public key
4237 * @private
4238 */
4239 RSAKey.prototype.getPublicBaseKey = function() {
4240 var options = {
4241 'array': [new KJUR.asn1.DERObjectIdentifier({
4242 'oid': '1.2.840.113549.1.1.1'
4243 }), //RSA Encryption pkcs #1 oid
4244 new KJUR.asn1.DERNull()]
4245 };
4246 var first_sequence = new KJUR.asn1.DERSequence(options);
4247
4248 options = {
4249 'array': [new KJUR.asn1.DERInteger({
4250 'bigint': this.n
4251 }), new KJUR.asn1.DERInteger({
4252 'int': this.e
4253 })]
4254 };
4255 var second_sequence = new KJUR.asn1.DERSequence(options);
4256
4257 options = {
4258 'hex': '00' + second_sequence.getEncodedHex()
4259 };
4260 var bit_string = new KJUR.asn1.DERBitString(options);
4261
4262 options = {
4263 'array': [first_sequence, bit_string]
4264 };
4265 var seq = new KJUR.asn1.DERSequence(options);
4266 return seq.getEncodedHex();
4267 };
4268
4269 /**
4270 * base64 (pem) encoded version of the DER encoded representation
4271 * @returns {string} pem encoded representation without header and footer
4272 * @public
4273 */
4274 RSAKey.prototype.getPublicBaseKeyB64 = function() {
4275 return hex2b64(this.getPublicBaseKey());
4276 };
4277
4278 /**
4279 * wrap the string in block of width chars. The default value for rsa keys is 64
4280 * characters.
4281 * @param {string} str the pem encoded string without header and footer
4282 * @param {Number} [width=64] - the length the string has to be wrapped at
4283 * @returns {string}
4284 * @private
4285 */
4286 RSAKey.prototype.wordwrap = function(str, width) {
4287 width = width || 64;
4288 if (!str) {
4289 return str;
4290 }
4291 var regex = '(.{1,' + width + '})( +|$\n?)|(.{1,' + width + '})';
4292 return str.match(RegExp(regex, 'g')).join('\n');
4293 };
4294
4295 /**
4296 * Retrieve the pem encoded private key
4297 * @returns {string} the pem encoded private key with header/footer
4298 * @public
4299 */
4300 RSAKey.prototype.getPrivateKey = function() {
4301 var key = "-----BEGIN RSA PRIVATE KEY-----\n";
4302 key += this.wordwrap(this.getPrivateBaseKeyB64()) + "\n";
4303 key += "-----END RSA PRIVATE KEY-----";
4304 return key;
4305 };
4306
4307 /**
4308 * Retrieve the pem encoded public key
4309 * @returns {string} the pem encoded public key with header/footer
4310 * @public
4311 */
4312 RSAKey.prototype.getPublicKey = function() {
4313 var key = "-----BEGIN PUBLIC KEY-----\n";
4314 key += this.wordwrap(this.getPublicBaseKeyB64()) + "\n";
4315 key += "-----END PUBLIC KEY-----";
4316 return key;
4317 };
4318
4319 /**
4320 * Check if the object contains the necessary parameters to populate the rsa modulus
4321 * and public exponent parameters.
4322 * @param {Object} [obj={}] - An object that may contain the two public key
4323 * parameters
4324 * @returns {boolean} true if the object contains both the modulus and the public exponent
4325 * properties (n and e)
4326 * @todo check for types of n and e. N should be a parseable bigInt object, E should
4327 * be a parseable integer number
4328 * @private
4329 */
4330 RSAKey.prototype.hasPublicKeyProperty = function(obj) {
4331 obj = obj || {};
4332 return (obj.hasOwnProperty('n') && obj.hasOwnProperty('e'));
4333 };
4334
4335 /**
4336 * Check if the object contains ALL the parameters of an RSA key.
4337 * @param {Object} [obj={}] - An object that may contain nine rsa key
4338 * parameters
4339 * @returns {boolean} true if the object contains all the parameters needed
4340 * @todo check for types of the parameters all the parameters but the public exponent
4341 * should be parseable bigint objects, the public exponent should be a parseable integer number
4342 * @private
4343 */
4344 RSAKey.prototype.hasPrivateKeyProperty = function(obj) {
4345 obj = obj || {};
4346 return (obj.hasOwnProperty('n') && obj.hasOwnProperty('e') && obj.hasOwnProperty('d') && obj.hasOwnProperty('p') && obj.hasOwnProperty('q') && obj.hasOwnProperty('dmp1') && obj.hasOwnProperty('dmq1') && obj.hasOwnProperty('coeff'));
4347 };
4348
4349 /**
4350 * Parse the properties of obj in the current rsa object. Obj should AT LEAST
4351 * include the modulus and public exponent (n, e) parameters.
4352 * @param {Object} obj - the object containing rsa parameters
4353 * @private
4354 */
4355 RSAKey.prototype.parsePropertiesFrom = function(obj) {
4356 this.n = obj.n;
4357 this.e = obj.e;
4358
4359 if (obj.hasOwnProperty('d')) {
4360 this.d = obj.d;
4361 this.p = obj.p;
4362 this.q = obj.q;
4363 this.dmp1 = obj.dmp1;
4364 this.dmq1 = obj.dmq1;
4365 this.coeff = obj.coeff;
4366 }
4367 };
4368
4369 /**
4370 * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object.
4371 * This object is just a decorator for parsing the key parameter
4372 * @param {string|Object} key - The key in string format, or an object containing
4373 * the parameters needed to build a RSAKey object.
4374 * @constructor
4375 */
4376 var JSEncryptRSAKey = function(key) {
4377 // Call the super constructor.
4378 RSAKey.call(this);
4379 // If a key key was provided.
4380 if (key) {
4381 // If this is a string...
4382 if (typeof key === 'string') {
4383 this.parseKey(key);
4384 } else if (this.hasPrivateKeyProperty(key) || this.hasPublicKeyProperty(key)) {
4385 // Set the values for the key.
4386 this.parsePropertiesFrom(key);
4387 }
4388 }
4389 };
4390
4391 // Derive from RSAKey.
4392 JSEncryptRSAKey.prototype = new RSAKey();
4393
4394 // Reset the contructor.
4395 JSEncryptRSAKey.prototype.constructor = JSEncryptRSAKey;
4396
4397 /**
4398 *
4399 * @param {Object} [options = {}] - An object to customize JSEncrypt behaviour
4400 * possible parameters are:
4401 * - default_key_size {number} default: 1024 the key size in bit
4402 * - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent
4403 * - log {boolean} default: false whether log warn/error or not
4404 * @constructor
4405 */
4406
4407
4408 /**
4409 * Method to set the rsa key parameter (one method is enough to set both the public
4410 * and the private key, since the private key contains the public key paramenters)
4411 * Log a warning if logs are enabled
4412 * @param {Object|string} key the pem encoded string or an object (with or without header/footer)
4413 * @public
4414 */
4415 JSEncrypt.prototype.setKey = function(key) {
4416 if (this.log && this.key) {
4417 console.warn('A key was already set, overriding existing.');
4418 }
4419 this.key = new JSEncryptRSAKey(key);
4420 };
4421
4422 /**
4423 * Proxy method for setKey, for api compatibility
4424 * @see setKey
4425 * @public
4426 */
4427 JSEncrypt.prototype.setPrivateKey = function(privkey) {
4428 // Create the key.
4429 this.setKey(privkey);
4430 };
4431
4432 /**
4433 * Proxy method for setKey, for api compatibility
4434 * @see setKey
4435 * @public
4436 */
4437 JSEncrypt.prototype.setPublicKey = function(pubkey) {
4438 // Sets the public key.
4439 this.setKey(pubkey);
4440 };
4441
4442 /**
4443 * Proxy method for RSAKey object's decrypt, decrypt the string using the private
4444 * components of the rsa key object. Note that if the object was not set will be created
4445 * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
4446 * @param {string} string base64 encoded crypted string to decrypt
4447 * @return {string} the decrypted string
4448 * @public
4449 */
4450 JSEncrypt.prototype.decrypt = function(string) {
4451 // Return the decrypted string.
4452 try {
4453 return this.getKey().decrypt(b64tohex(string));
4454 } catch(ex) {
4455 return false;
4456 }
4457 };
4458
4459 /**
4460 * Proxy method for RSAKey object's encrypt, encrypt the string using the public
4461 * components of the rsa key object. Note that if the object was not set will be created
4462 * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
4463 * @param {string} string the string to encrypt
4464 * @return {string} the encrypted string encoded in base64
4465 * @public
4466 */
4467 JSEncrypt.prototype.encrypt = function(string) {
4468 // Return the encrypted string.
4469 try {
4470 return hex2b64(this.getKey().encrypt(string));
4471 } catch(ex) {
4472 return false;
4473 }
4474 };
4475
4476 /**
4477 * Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object
4478 * will be created and returned
4479 * @param {callback} [cb] the callback to be called if we want the key to be generated
4480 * in an async fashion
4481 * @returns {JSEncryptRSAKey} the JSEncryptRSAKey object
4482 * @public
4483 */
4484 JSEncrypt.prototype.getKey = function(cb) {
4485 // Only create new if it does not exist.
4486 if (!this.key) {
4487 // Get a new private key.
4488 this.key = new JSEncryptRSAKey();
4489 if (cb && {}.toString.call(cb) === '[object Function]') {
4490 this.key.generateAsync(this.default_key_size, this.default_public_exponent, cb);
4491 return;
4492 }
4493 // Generate the key.
4494 this.key.generate(this.default_key_size, this.default_public_exponent);
4495 }
4496 return this.key;
4497 };
4498
4499 /**
4500 * Returns the pem encoded representation of the private key
4501 * If the key doesn't exists a new key will be created
4502 * @returns {string} pem encoded representation of the private key WITH header and footer
4503 * @public
4504 */
4505 JSEncrypt.prototype.getPrivateKey = function() {
4506 // Return the private representation of this key.
4507 return this.getKey().getPrivateKey();
4508 };
4509
4510 /**
4511 * Returns the pem encoded representation of the private key
4512 * If the key doesn't exists a new key will be created
4513 * @returns {string} pem encoded representation of the private key WITHOUT header and footer
4514 * @public
4515 */
4516 JSEncrypt.prototype.getPrivateKeyB64 = function() {
4517 // Return the private representation of this key.
4518 return this.getKey().getPrivateBaseKeyB64();
4519 };
4520
4521 /**
4522 * Returns the pem encoded representation of the public key
4523 * If the key doesn't exists a new key will be created
4524 * @returns {string} pem encoded representation of the public key WITH header and footer
4525 * @public
4526 */
4527 JSEncrypt.prototype.getPublicKey = function() {
4528 // Return the private representation of this key.
4529 return this.getKey().getPublicKey();
4530 };
4531
4532 /**
4533 * Returns the pem encoded representation of the public key
4534 * If the key doesn't exists a new key will be created
4535 * @returns {string} pem encoded representation of the public key WITHOUT header and footer
4536 * @public
4537 */
4538 JSEncrypt.prototype.getPublicKeyB64 = function() {
4539 // Return the private representation of this key.
4540 return this.getKey().getPublicBaseKeyB64();
4541 };
4542
4543 JSEncrypt.version = '2.3.1';
4544 exports.JSEncrypt = JSEncrypt;
4545 });
4546
4547 // function encryptRequest(data, publicKey) {
4548 // var encrypt = new JSEncrypt();
4549 // encrypt.setPublicKey(publicKey);
4550 // // ajax请求发送的数据对象
4551 // var sendData = new Object();
4552 // // 将data数组赋给ajax对象
4553 // for (var key in data) {
4554 // sendData[key] = encrypt.encrypt(data[key]);
4555 // }
4556 // return sendData;
4557 // }//encryptRequest函数结束
4558 function encryptRequest(data, publicKey) {
4559 var encrypt = new JSEncrypt();
4560 encrypt.setPublicKey(publicKey);
4561 return encrypt.encrypt(data);
4562 }
4563
4564 // var mcrypt_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCSQuMD7O2Vfh3nJgxOR7c3rKJKbqfQiSw+mqVmCaoXli2YOqI8nWstpdQFpXGfpGVfO+M8Zyekfa2rJGGtbpftqiFMhbYFak+mtfhNIxbobxLivofpfzu17plYywokresdD+tfEbd4uoyQamG7zlQzd1ZdUspw57VeB5tKbrPstQIDAQAB'
4565
4566 function test(pwd_val, mcrypt_key) {
4567 var PwdResult = encryptRequest(pwd_val, mcrypt_key);
4568 return PwdResult;
4569 }

JS代码部分

JS逆向-抠代码的第二天【手把手学会抠代码】的更多相关文章

  1. JS逆向-抠代码的第一天【手把手学会抠代码】

    首先声明,本人经过无数次摸爬滚打及翻阅各类资料,理论知识极其丰富,但是抠代码怎么都抠不会. 无奈之下,只能承认:这个活,需要熟练度. 本文仅对部分参数进行解析,有需要调用,请自行根据现实情况调整. 第 ...

  2. JS逆向-抠代码的第四天【手把手学会抠代码】

    今天是md5巩固项目,该项目比昨天的复杂一些,但方法思路是一样的. 今天的目标:https://www.webportal.top/ 打开网站,填入账号密码(密码项目以123456做测试).点击登录抓 ...

  3. 兄弟,你爬虫基础这么好,需要研究js逆向了,一起吧(有完整JS代码)

    这几天的确有空了,看更新多快,专门研究了一下几个网站登录中密码加密方法,比起滑块验证码来说都相对简单,适合新手js逆向入门,大家可以自己试一下,试不出来了再参考我的js代码.篇幅有限,完整的js代码在 ...

  4. 网络爬虫之记一次js逆向解密经历

    1 引言 数月前写过某网站(请原谅我的掩耳盗铃)的爬虫,这两天需要重新采集一次,用的是scrapy-redis框架,本以为二次爬取可以轻松完成的,可没想到爬虫启动没几秒,出现了大堆的重试提示,心里顿时 ...

  5. 这个爬虫JS逆向加密任务,你还不来试试?逆向入门级,适合一定爬虫基础的人

    友情提示:在博客园更新比较慢,有兴趣的关注知识图谱与大数据公众号吧.这次选择苏宁易购登录密码加密,如能调试出来代表你具备了一定的JS逆向能力,初学者建议跟着内容调试一波,尽量独自将JS代码抠出来,实在 ...

  6. 爬虫必看,每日JS逆向之爱奇艺密码加密,今天你练了吗?

    友情提示:优先在公众号更新,在博客园更新较慢,有兴趣的关注一下知识图谱与大数据公众号,本次目标是抠出爱奇艺passwd加密JS代码,如果你看到了这一篇,说明你对JS逆向感兴趣,如果是初学者,那不妨再看 ...

  7. Python反爬:利用js逆向和woff文件爬取猫眼电影评分信息

    首先:看看运行结果效果如何! 1. 实现思路 小编基本实现思路如下: 利用js逆向模拟请求得到电影评分的页面(就是猫眼电影的评分信息并不是我们上述看到的那个页面上,应该它的实现是在一个页面上插入另外一 ...

  8. python爬虫之JS逆向

    Python爬虫之JS逆向案例 由于在爬取数据时,遇到请求头限制属性为动态生成,现将解决方式整理如下: JS逆向有两种思路: 一种是整理出js文件在Python中直接使用execjs调用js文件(可见 ...

  9. 爬虫05 /js加密/js逆向、常用抓包工具、移动端数据爬取

    爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 目录 爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 1. js加密.js逆向:案例1 2. js加密.js逆向:案例2 3 ...

随机推荐

  1. MySQL 多实例及其主从复制

    目录 Mysql 实例 Mysql 多实例 创建多实例目录 编辑配置文件 初始化多实例数据目录 授权目录 启动多实例 连接多实例并验证 Mysql 多实例设置密码 设置密码后连接 Mysql 多实例主 ...

  2. Redis面试常见问题(一)

    一.redis 简介简单来说 redis 就是一个数据库,不过与传统数据库不同的是 redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向.另外,redis 也经 ...

  3. TweenMax & GSAP & SVG Animation

    TweenMax & GSAP & SVG Animation svg animation https://greensock.com/tweenmax GSAP https://ww ...

  4. how to copy to clipboard using windows cmd

    how to copy to clipboard using windows cmd Windows clipboard command line https://www.labnol.org/sof ...

  5. 「NGK每日快讯」2021.2.11日NGK公链第100期官方快讯!

  6. [Python] 茎叶图和复合饼图的画法

    目录 茎叶图 复合饼图 茎叶图 from itertools import groupby nums2=[225, 232,232,245,235,245,270,225,240,240,217,19 ...

  7. 一次 MySQL 线上死锁分析实战

    关键词:MySQL Index Merge 前言 MySQL 的锁机制相信大家在学习 MySQL 的时候都有简单的了解过,那既然有锁就必定绕不开死锁这个问题.其实 MySQL 在大部分场景下是不会存在 ...

  8. 死磕以太坊源码分析之EVM如何调用ABI编码的外部方法

    死磕以太坊源码分析之EVM如何调用ABI编码的外部方法 配合以下代码进行阅读:https://github.com/blockchainGuide/ 写文不易,给个小关注,有什么问题可以指出,便于大家 ...

  9. JS判断年份是否为闰年

    //闰年能被4整除且不能被100整除,或能被400整除.function year(){ if(year%4==0&&year%100!=0||year%400==0){        ...

  10. C# 处理PPT水印(三)—— 在PPT中添加多行(平铺)文本水印效果

    在PPT幻灯片中,可通过添加形状的方式,来实现类似水印的效果,可添加单一文本水印效果,即幻灯片中只有一个文本水印:也可以添加多行(平铺)文本水印效果,即幻灯片中以一定方式平铺排列多个文本水印效果.本文 ...