JS逆向-摳程式碼的第二天【手把手學會摳程式碼】

疏樓龍宿^發表於2021-03-13

  今天的學習專案:沃支付: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:

JS逆向-摳程式碼的第二天【手把手學會摳程式碼】
 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

JS逆向-摳程式碼的第二天【手把手學會摳程式碼】
   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程式碼部分

 

 

 

 

 

 

 

相關文章