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