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

2023-05-10,,

  今天的学习项目:沃支付: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逆向-抠代码的第二天【手把手学会抠代码】的相关教程结束。

《JS逆向-抠代码的第二天【手把手学会抠代码】.doc》

下载本文的Word格式文档,以方便收藏与打印。