├── README.md ├── index.html ├── app.js ├── LICENSE └── jsencrypt.js /README.md: -------------------------------------------------------------------------------- 1 | # [travis-encrypt](https://erikdesjardins.github.io/travis-encrypt) 2 | Encrypt strings for Travis CI public repos. 3 | 4 | They can then be used in your `.travis.yml`, e.g. 5 | 6 | ```yml 7 | deploy: 8 | provider: npm 9 | api_key: 10 | secure: 11 | ``` 12 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
Encrypts a string with the public RSA key available at https://api.travis-ci.org/repos/user/repo/key
9 |
10 |
Repo
11 |
12 |
13 |
Input
14 |
15 |
16 |
Output
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const repo = document.getElementById('repo'); 2 | const input = document.getElementById('input'); 3 | const output = document.getElementById('output'); 4 | 5 | let key, lastFetch; 6 | 7 | function update() { 8 | repo.style.borderColor = 'red'; 9 | input.style.borderColor = 'red'; 10 | output.style.borderColor = 'red'; 11 | 12 | if (lastFetch !== repo.value) { 13 | key = undefined; 14 | lastFetch = repo.value; 15 | fetch(`https://api.travis-ci.org/repos/${repo.value}/key`) 16 | .then(r => r.json()) 17 | .then(val => { 18 | key = val.key; 19 | update(); 20 | }); 21 | } else if (key) { 22 | repo.style.borderColor = 'green'; 23 | } 24 | 25 | if (input.value) { 26 | input.style.borderColor = 'green'; 27 | } 28 | 29 | if (key && input.value) { 30 | const enc = new JSEncrypt(); 31 | enc.setKey(key); 32 | output.value = enc.encrypt(input.value); 33 | output.style.borderColor = 'green'; 34 | } 35 | } 36 | 37 | repo.addEventListener('change', update); 38 | input.addEventListener('input', update); 39 | 40 | update(); 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Erik Desjardins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /jsencrypt.js: -------------------------------------------------------------------------------- 1 | var JSEncryptExports = {}; 2 | (function(exports) { 3 | // Copyright (c) 2005 Tom Wu 4 | // All Rights Reserved. 5 | // See "LICENSE" for details. 6 | 7 | // Basic JavaScript BN library - subset useful for RSA encryption. 8 | 9 | // Bits per digit 10 | var dbits; 11 | 12 | // JavaScript engine analysis 13 | var canary = 0xdeadbeefcafe; 14 | var j_lm = ((canary&0xffffff)==0xefcafe); 15 | 16 | // (public) Constructor 17 | function BigInteger(a,b,c) { 18 | if(a != null) 19 | if("number" == typeof a) this.fromNumber(a,b,c); 20 | else if(b == null && "string" != typeof a) this.fromString(a,256); 21 | else this.fromString(a,b); 22 | } 23 | 24 | // return new, unset BigInteger 25 | function nbi() { return new BigInteger(null); } 26 | 27 | // am: Compute w_j += (x*this_i), propagate carries, 28 | // c is initial carry, returns final carry. 29 | // c < 3*dvalue, x < 2*dvalue, this_i < dvalue 30 | // We need to select the fastest one that works in this environment. 31 | 32 | // am1: use a single mult and divide to get the high bits, 33 | // max digit bits should be 26 because 34 | // max internal value = 2*dvalue^2-2*dvalue (< 2^53) 35 | function am1(i,x,w,j,c,n) { 36 | while(--n >= 0) { 37 | var v = x*this[i++]+w[j]+c; 38 | c = Math.floor(v/0x4000000); 39 | w[j++] = v&0x3ffffff; 40 | } 41 | return c; 42 | } 43 | // am2 avoids a big mult-and-extract completely. 44 | // Max digit bits should be <= 30 because we do bitwise ops 45 | // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) 46 | function am2(i,x,w,j,c,n) { 47 | var xl = x&0x7fff, xh = x>>15; 48 | while(--n >= 0) { 49 | var l = this[i]&0x7fff; 50 | var h = this[i++]>>15; 51 | var m = xh*l+h*xl; 52 | l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); 53 | c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); 54 | w[j++] = l&0x3fffffff; 55 | } 56 | return c; 57 | } 58 | // Alternately, set max digit bits to 28 since some 59 | // browsers slow down when dealing with 32-bit numbers. 60 | function am3(i,x,w,j,c,n) { 61 | var xl = x&0x3fff, xh = x>>14; 62 | while(--n >= 0) { 63 | var l = this[i]&0x3fff; 64 | var h = this[i++]>>14; 65 | var m = xh*l+h*xl; 66 | l = xl*l+((m&0x3fff)<<14)+w[j]+c; 67 | c = (l>>28)+(m>>14)+xh*h; 68 | w[j++] = l&0xfffffff; 69 | } 70 | return c; 71 | } 72 | if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { 73 | BigInteger.prototype.am = am2; 74 | dbits = 30; 75 | } 76 | else if(j_lm && (navigator.appName != "Netscape")) { 77 | BigInteger.prototype.am = am1; 78 | dbits = 26; 79 | } 80 | else { // Mozilla/Netscape seems to prefer am3 81 | BigInteger.prototype.am = am3; 82 | dbits = 28; 83 | } 84 | 85 | BigInteger.prototype.DB = dbits; 86 | BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; 114 | r.t = this.t; 115 | r.s = this.s; 116 | } 117 | 118 | // (protected) set from integer value x, -DV <= x < DV 119 | function bnpFromInt(x) { 120 | this.t = 1; 121 | this.s = (x<0)?-1:0; 122 | if(x > 0) this[0] = x; 123 | else if(x < -1) this[0] = x+this.DV; 124 | else this.t = 0; 125 | } 126 | 127 | // return bigint initialized to value 128 | function nbv(i) { var r = nbi(); r.fromInt(i); return r; } 129 | 130 | // (protected) set from string and radix 131 | function bnpFromString(s,b) { 132 | var k; 133 | if(b == 16) k = 4; 134 | else if(b == 8) k = 3; 135 | else if(b == 256) k = 8; // byte array 136 | else if(b == 2) k = 1; 137 | else if(b == 32) k = 5; 138 | else if(b == 4) k = 2; 139 | else { this.fromRadix(s,b); return; } 140 | this.t = 0; 141 | this.s = 0; 142 | var i = s.length, mi = false, sh = 0; 143 | while(--i >= 0) { 144 | var x = (k==8)?s[i]&0xff:intAt(s,i); 145 | if(x < 0) { 146 | if(s.charAt(i) == "-") mi = true; 147 | continue; 148 | } 149 | mi = false; 150 | if(sh == 0) 151 | this[this.t++] = x; 152 | else if(sh+k > this.DB) { 153 | this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); 155 | } 156 | else 157 | this[this.t-1] |= x<= this.DB) sh -= this.DB; 160 | } 161 | if(k == 8 && (s[0]&0x80) != 0) { 162 | this.s = -1; 163 | if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; 173 | } 174 | 175 | // (public) return string representation in given radix 176 | function bnToString(b) { 177 | if(this.s < 0) return "-"+this.negate().toString(b); 178 | var k; 179 | if(b == 16) k = 4; 180 | else if(b == 8) k = 3; 181 | else if(b == 2) k = 1; 182 | else if(b == 32) k = 5; 183 | else if(b == 4) k = 2; 184 | else return this.toRadix(b); 185 | var km = (1< 0) { 188 | if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } 189 | while(i >= 0) { 190 | if(p < k) { 191 | d = (this[i]&((1<>(p+=this.DB-k); 193 | } 194 | else { 195 | d = (this[i]>>(p-=k))&km; 196 | if(p <= 0) { p += this.DB; --i; } 197 | } 198 | if(d > 0) m = true; 199 | if(m) r += int2char(d); 200 | } 201 | } 202 | return m?r:"0"; 203 | } 204 | 205 | // (public) -this 206 | function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } 207 | 208 | // (public) |this| 209 | function bnAbs() { return (this.s<0)?this.negate():this; } 210 | 211 | // (public) return + if this > a, - if this < a, 0 if equal 212 | function bnCompareTo(a) { 213 | var r = this.s-a.s; 214 | if(r != 0) return r; 215 | var i = this.t; 216 | r = i-a.t; 217 | if(r != 0) return (this.s<0)?-r:r; 218 | while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; 219 | return 0; 220 | } 221 | 222 | // returns bit length of the integer x 223 | function nbits(x) { 224 | var r = 1, t; 225 | if((t=x>>>16) != 0) { x = t; r += 16; } 226 | if((t=x>>8) != 0) { x = t; r += 8; } 227 | if((t=x>>4) != 0) { x = t; r += 4; } 228 | if((t=x>>2) != 0) { x = t; r += 2; } 229 | if((t=x>>1) != 0) { x = t; r += 1; } 230 | return r; 231 | } 232 | 233 | // (public) return the number of bits in "this" 234 | function bnBitLength() { 235 | if(this.t <= 0) return 0; 236 | return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); 237 | } 238 | 239 | // (protected) r = this << n*DB 240 | function bnpDLShiftTo(n,r) { 241 | var i; 242 | for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; 243 | for(i = n-1; i >= 0; --i) r[i] = 0; 244 | r.t = this.t+n; 245 | r.s = this.s; 246 | } 247 | 248 | // (protected) r = this >> n*DB 249 | function bnpDRShiftTo(n,r) { 250 | for(var i = n; i < this.t; ++i) r[i-n] = this[i]; 251 | r.t = Math.max(this.t-n,0); 252 | r.s = this.s; 253 | } 254 | 255 | // (protected) r = this << n 256 | function bnpLShiftTo(n,r) { 257 | var bs = n%this.DB; 258 | var cbs = this.DB-bs; 259 | var bm = (1<= 0; --i) { 262 | r[i+ds+1] = (this[i]>>cbs)|c; 263 | c = (this[i]&bm)<= 0; --i) r[i] = 0; 266 | r[ds] = c; 267 | r.t = this.t+ds+1; 268 | r.s = this.s; 269 | r.clamp(); 270 | } 271 | 272 | // (protected) r = this >> n 273 | function bnpRShiftTo(n,r) { 274 | r.s = this.s; 275 | var ds = Math.floor(n/this.DB); 276 | if(ds >= this.t) { r.t = 0; return; } 277 | var bs = n%this.DB; 278 | var cbs = this.DB-bs; 279 | var bm = (1<>bs; 281 | for(var i = ds+1; i < this.t; ++i) { 282 | r[i-ds-1] |= (this[i]&bm)<>bs; 284 | } 285 | if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; 297 | } 298 | if(a.t < this.t) { 299 | c -= a.s; 300 | while(i < this.t) { 301 | c += this[i]; 302 | r[i++] = c&this.DM; 303 | c >>= this.DB; 304 | } 305 | c += this.s; 306 | } 307 | else { 308 | c += this.s; 309 | while(i < a.t) { 310 | c -= a[i]; 311 | r[i++] = c&this.DM; 312 | c >>= this.DB; 313 | } 314 | c -= a.s; 315 | } 316 | r.s = (c<0)?-1:0; 317 | if(c < -1) r[i++] = this.DV+c; 318 | else if(c > 0) r[i++] = c; 319 | r.t = i; 320 | r.clamp(); 321 | } 322 | 323 | // (protected) r = this * a, r != this,a (HAC 14.12) 324 | // "this" should be the larger one if appropriate. 325 | function bnpMultiplyTo(a,r) { 326 | var x = this.abs(), y = a.abs(); 327 | var i = x.t; 328 | r.t = i+y.t; 329 | while(--i >= 0) r[i] = 0; 330 | for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); 331 | r.s = 0; 332 | r.clamp(); 333 | if(this.s != a.s) BigInteger.ZERO.subTo(r,r); 334 | } 335 | 336 | // (protected) r = this^2, r != this (HAC 14.16) 337 | function bnpSquareTo(r) { 338 | var x = this.abs(); 339 | var i = r.t = 2*x.t; 340 | while(--i >= 0) r[i] = 0; 341 | for(i = 0; i < x.t-1; ++i) { 342 | var c = x.am(i,x[i],r,2*i,0,1); 343 | if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { 344 | r[i+x.t] -= x.DV; 345 | r[i+x.t+1] = 1; 346 | } 347 | } 348 | if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); 349 | r.s = 0; 350 | r.clamp(); 351 | } 352 | 353 | // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) 354 | // r != q, this != m. q or r may be null. 355 | function bnpDivRemTo(m,q,r) { 356 | var pm = m.abs(); 357 | if(pm.t <= 0) return; 358 | var pt = this.abs(); 359 | if(pt.t < pm.t) { 360 | if(q != null) q.fromInt(0); 361 | if(r != null) this.copyTo(r); 362 | return; 363 | } 364 | if(r == null) r = nbi(); 365 | var y = nbi(), ts = this.s, ms = m.s; 366 | var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus 367 | if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } 368 | else { pm.copyTo(y); pt.copyTo(r); } 369 | var ys = y.t; 370 | var y0 = y[ys-1]; 371 | if(y0 == 0) return; 372 | var yt = y0*(1<1)?y[ys-2]>>this.F2:0); 373 | var d1 = this.FV/yt, d2 = (1<= 0) { 377 | r[r.t++] = 1; 378 | r.subTo(t,r); 379 | } 380 | BigInteger.ONE.dlShiftTo(ys,t); 381 | t.subTo(y,y); // "negative" y so we can replace sub with am later 382 | while(y.t < ys) y[y.t++] = 0; 383 | while(--j >= 0) { 384 | // Estimate quotient digit 385 | var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); 386 | if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out 387 | y.dlShiftTo(j,t); 388 | r.subTo(t,r); 389 | while(r[i] < --qd) r.subTo(t,r); 390 | } 391 | } 392 | if(q != null) { 393 | r.drShiftTo(ys,q); 394 | if(ts != ms) BigInteger.ZERO.subTo(q,q); 395 | } 396 | r.t = ys; 397 | r.clamp(); 398 | if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder 399 | if(ts < 0) BigInteger.ZERO.subTo(r,r); 400 | } 401 | 402 | // (public) this mod a 403 | function bnMod(a) { 404 | var r = nbi(); 405 | this.abs().divRemTo(a,null,r); 406 | if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); 407 | return r; 408 | } 409 | 410 | // Modular reduction using "classic" algorithm 411 | function Classic(m) { this.m = m; } 412 | function cConvert(x) { 413 | if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); 414 | else return x; 415 | } 416 | function cRevert(x) { return x; } 417 | function cReduce(x) { x.divRemTo(this.m,null,x); } 418 | function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 419 | function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 420 | 421 | Classic.prototype.convert = cConvert; 422 | Classic.prototype.revert = cRevert; 423 | Classic.prototype.reduce = cReduce; 424 | Classic.prototype.mulTo = cMulTo; 425 | Classic.prototype.sqrTo = cSqrTo; 426 | 427 | // (protected) return "-1/this % 2^DB"; useful for Mont. reduction 428 | // justification: 429 | // xy == 1 (mod m) 430 | // xy = 1+km 431 | // xy(2-xy) = (1+km)(1-km) 432 | // x[y(2-xy)] = 1-k^2m^2 433 | // x[y(2-xy)] == 1 (mod m^2) 434 | // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 435 | // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. 436 | // JS multiply "overflows" differently from C/C++, so care is needed here. 437 | function bnpInvDigit() { 438 | if(this.t < 1) return 0; 439 | var x = this[0]; 440 | if((x&1) == 0) return 0; 441 | var y = x&3; // y == 1/x mod 2^2 442 | y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 443 | y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 444 | y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 445 | // last step - calculate inverse mod DV directly; 446 | // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints 447 | y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits 448 | // we really want the negative inverse, and -DV < y < DV 449 | return (y>0)?this.DV-y:-y; 450 | } 451 | 452 | // Montgomery reduction 453 | function Montgomery(m) { 454 | this.m = m; 455 | this.mp = m.invDigit(); 456 | this.mpl = this.mp&0x7fff; 457 | this.mph = this.mp>>15; 458 | this.um = (1<<(m.DB-15))-1; 459 | this.mt2 = 2*m.t; 460 | } 461 | 462 | // xR mod m 463 | function montConvert(x) { 464 | var r = nbi(); 465 | x.abs().dlShiftTo(this.m.t,r); 466 | r.divRemTo(this.m,null,r); 467 | if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); 468 | return r; 469 | } 470 | 471 | // x/R mod m 472 | function montRevert(x) { 473 | var r = nbi(); 474 | x.copyTo(r); 475 | this.reduce(r); 476 | return r; 477 | } 478 | 479 | // x = x/R mod m (HAC 14.32) 480 | function montReduce(x) { 481 | while(x.t <= this.mt2) // pad x so am has enough room later 482 | x[x.t++] = 0; 483 | for(var i = 0; i < this.m.t; ++i) { 484 | // faster way of calculating u0 = x[i]*mp mod DV 485 | var j = x[i]&0x7fff; 486 | var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; 487 | // use am to combine the multiply-shift-add into one call 488 | j = i+this.m.t; 489 | x[j] += this.m.am(0,u0,x,i,0,this.m.t); 490 | // propagate carry 491 | while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } 492 | } 493 | x.clamp(); 494 | x.drShiftTo(this.m.t,x); 495 | if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 496 | } 497 | 498 | // r = "x^2/R mod m"; x != r 499 | function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 500 | 501 | // r = "xy/R mod m"; x,y != r 502 | function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 503 | 504 | Montgomery.prototype.convert = montConvert; 505 | Montgomery.prototype.revert = montRevert; 506 | Montgomery.prototype.reduce = montReduce; 507 | Montgomery.prototype.mulTo = montMulTo; 508 | Montgomery.prototype.sqrTo = montSqrTo; 509 | 510 | // (protected) true iff this is even 511 | function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } 512 | 513 | // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) 514 | function bnpExp(e,z) { 515 | if(e > 0xffffffff || e < 1) return BigInteger.ONE; 516 | var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; 517 | g.copyTo(r); 518 | while(--i >= 0) { 519 | z.sqrTo(r,r2); 520 | if((e&(1< 0) z.mulTo(r2,g,r); 521 | else { var t = r; r = r2; r2 = t; } 522 | } 523 | return z.revert(r); 524 | } 525 | 526 | // (public) this^e % m, 0 <= e < 2^32 527 | function bnModPowInt(e,m) { 528 | var z; 529 | if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); 530 | return this.exp(e,z); 531 | } 532 | 533 | // protected 534 | BigInteger.prototype.copyTo = bnpCopyTo; 535 | BigInteger.prototype.fromInt = bnpFromInt; 536 | BigInteger.prototype.fromString = bnpFromString; 537 | BigInteger.prototype.clamp = bnpClamp; 538 | BigInteger.prototype.dlShiftTo = bnpDLShiftTo; 539 | BigInteger.prototype.drShiftTo = bnpDRShiftTo; 540 | BigInteger.prototype.lShiftTo = bnpLShiftTo; 541 | BigInteger.prototype.rShiftTo = bnpRShiftTo; 542 | BigInteger.prototype.subTo = bnpSubTo; 543 | BigInteger.prototype.multiplyTo = bnpMultiplyTo; 544 | BigInteger.prototype.squareTo = bnpSquareTo; 545 | BigInteger.prototype.divRemTo = bnpDivRemTo; 546 | BigInteger.prototype.invDigit = bnpInvDigit; 547 | BigInteger.prototype.isEven = bnpIsEven; 548 | BigInteger.prototype.exp = bnpExp; 549 | 550 | // public 551 | BigInteger.prototype.toString = bnToString; 552 | BigInteger.prototype.negate = bnNegate; 553 | BigInteger.prototype.abs = bnAbs; 554 | BigInteger.prototype.compareTo = bnCompareTo; 555 | BigInteger.prototype.bitLength = bnBitLength; 556 | BigInteger.prototype.mod = bnMod; 557 | BigInteger.prototype.modPowInt = bnModPowInt; 558 | 559 | // "constants" 560 | BigInteger.ZERO = nbv(0); 561 | BigInteger.ONE = nbv(1); 562 | // Copyright (c) 2005-2009 Tom Wu 563 | // All Rights Reserved. 564 | // See "LICENSE" for details. 565 | 566 | // Extended JavaScript BN functions, required for RSA private ops. 567 | 568 | // Version 1.1: new BigInteger("0", 10) returns "proper" zero 569 | // Version 1.2: square() API, isProbablePrime fix 570 | 571 | // (public) 572 | function bnClone() { var r = nbi(); this.copyTo(r); return r; } 573 | 574 | // (public) return value as integer 575 | function bnIntValue() { 576 | if(this.s < 0) { 577 | if(this.t == 1) return this[0]-this.DV; 578 | else if(this.t == 0) return -1; 579 | } 580 | else if(this.t == 1) return this[0]; 581 | else if(this.t == 0) return 0; 582 | // assumes 16 < DB < 32 583 | return ((this[1]&((1<<(32-this.DB))-1))<>24; } 588 | 589 | // (public) return value as short (assumes DB>=16) 590 | function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } 591 | 592 | // (protected) return x s.t. r^x < DV 593 | function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } 594 | 595 | // (public) 0 if this == 0, 1 if this > 0 596 | function bnSigNum() { 597 | if(this.s < 0) return -1; 598 | else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; 599 | else return 1; 600 | } 601 | 602 | // (protected) convert to radix string 603 | function bnpToRadix(b) { 604 | if(b == null) b = 10; 605 | if(this.signum() == 0 || b < 2 || b > 36) return "0"; 606 | var cs = this.chunkSize(b); 607 | var a = Math.pow(b,cs); 608 | var d = nbv(a), y = nbi(), z = nbi(), r = ""; 609 | this.divRemTo(d,y,z); 610 | while(y.signum() > 0) { 611 | r = (a+z.intValue()).toString(b).substr(1) + r; 612 | y.divRemTo(d,y,z); 613 | } 614 | return z.intValue().toString(b) + r; 615 | } 616 | 617 | // (protected) convert from radix string 618 | function bnpFromRadix(s,b) { 619 | this.fromInt(0); 620 | if(b == null) b = 10; 621 | var cs = this.chunkSize(b); 622 | var d = Math.pow(b,cs), mi = false, j = 0, w = 0; 623 | for(var i = 0; i < s.length; ++i) { 624 | var x = intAt(s,i); 625 | if(x < 0) { 626 | if(s.charAt(i) == "-" && this.signum() == 0) mi = true; 627 | continue; 628 | } 629 | w = b*w+x; 630 | if(++j >= cs) { 631 | this.dMultiply(d); 632 | this.dAddOffset(w,0); 633 | j = 0; 634 | w = 0; 635 | } 636 | } 637 | if(j > 0) { 638 | this.dMultiply(Math.pow(b,j)); 639 | this.dAddOffset(w,0); 640 | } 641 | if(mi) BigInteger.ZERO.subTo(this,this); 642 | } 643 | 644 | // (protected) alternate constructor 645 | function bnpFromNumber(a,b,c) { 646 | if("number" == typeof b) { 647 | // new BigInteger(int,int,RNG) 648 | if(a < 2) this.fromInt(1); 649 | else { 650 | this.fromNumber(a,c); 651 | if(!this.testBit(a-1)) // force MSB set 652 | this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); 653 | if(this.isEven()) this.dAddOffset(1,0); // force odd 654 | while(!this.isProbablePrime(b)) { 655 | this.dAddOffset(2,0); 656 | if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); 657 | } 658 | } 659 | } 660 | else { 661 | // new BigInteger(int,RNG) 662 | var x = new Array(), t = a&7; 663 | x.length = (a>>3)+1; 664 | b.nextBytes(x); 665 | if(t > 0) x[0] &= ((1< 0) { 676 | if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) 677 | r[k++] = d|(this.s<<(this.DB-p)); 678 | while(i >= 0) { 679 | if(p < 8) { 680 | d = (this[i]&((1<>(p+=this.DB-8); 682 | } 683 | else { 684 | d = (this[i]>>(p-=8))&0xff; 685 | if(p <= 0) { p += this.DB; --i; } 686 | } 687 | if((d&0x80) != 0) d |= -256; 688 | if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; 689 | if(k > 0 || d != this.s) r[k++] = d; 690 | } 691 | } 692 | return r; 693 | } 694 | 695 | function bnEquals(a) { return(this.compareTo(a)==0); } 696 | function bnMin(a) { return(this.compareTo(a)<0)?this:a; } 697 | function bnMax(a) { return(this.compareTo(a)>0)?this:a; } 698 | 699 | // (protected) r = this op a (bitwise) 700 | function bnpBitwiseTo(a,op,r) { 701 | var i, f, m = Math.min(a.t,this.t); 702 | for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); 703 | if(a.t < this.t) { 704 | f = a.s&this.DM; 705 | for(i = m; i < this.t; ++i) r[i] = op(this[i],f); 706 | r.t = this.t; 707 | } 708 | else { 709 | f = this.s&this.DM; 710 | for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); 711 | r.t = a.t; 712 | } 713 | r.s = op(this.s,a.s); 714 | r.clamp(); 715 | } 716 | 717 | // (public) this & a 718 | function op_and(x,y) { return x&y; } 719 | function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } 720 | 721 | // (public) this | a 722 | function op_or(x,y) { return x|y; } 723 | function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } 724 | 725 | // (public) this ^ a 726 | function op_xor(x,y) { return x^y; } 727 | function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } 728 | 729 | // (public) this & ~a 730 | function op_andnot(x,y) { return x&~y; } 731 | function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } 732 | 733 | // (public) ~this 734 | function bnNot() { 735 | var r = nbi(); 736 | for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; 737 | r.t = this.t; 738 | r.s = ~this.s; 739 | return r; 740 | } 741 | 742 | // (public) this << n 743 | function bnShiftLeft(n) { 744 | var r = nbi(); 745 | if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); 746 | return r; 747 | } 748 | 749 | // (public) this >> n 750 | function bnShiftRight(n) { 751 | var r = nbi(); 752 | if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); 753 | return r; 754 | } 755 | 756 | // return index of lowest 1-bit in x, x < 2^31 757 | function lbit(x) { 758 | if(x == 0) return -1; 759 | var r = 0; 760 | if((x&0xffff) == 0) { x >>= 16; r += 16; } 761 | if((x&0xff) == 0) { x >>= 8; r += 8; } 762 | if((x&0xf) == 0) { x >>= 4; r += 4; } 763 | if((x&3) == 0) { x >>= 2; r += 2; } 764 | if((x&1) == 0) ++r; 765 | return r; 766 | } 767 | 768 | // (public) returns index of lowest 1-bit (or -1 if none) 769 | function bnGetLowestSetBit() { 770 | for(var i = 0; i < this.t; ++i) 771 | if(this[i] != 0) return i*this.DB+lbit(this[i]); 772 | if(this.s < 0) return this.t*this.DB; 773 | return -1; 774 | } 775 | 776 | // return number of 1 bits in x 777 | function cbit(x) { 778 | var r = 0; 779 | while(x != 0) { x &= x-1; ++r; } 780 | return r; 781 | } 782 | 783 | // (public) return number of set bits 784 | function bnBitCount() { 785 | var r = 0, x = this.s&this.DM; 786 | for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); 787 | return r; 788 | } 789 | 790 | // (public) true iff nth bit is set 791 | function bnTestBit(n) { 792 | var j = Math.floor(n/this.DB); 793 | if(j >= this.t) return(this.s!=0); 794 | return((this[j]&(1<<(n%this.DB)))!=0); 795 | } 796 | 797 | // (protected) this op (1<>= this.DB; 820 | } 821 | if(a.t < this.t) { 822 | c += a.s; 823 | while(i < this.t) { 824 | c += this[i]; 825 | r[i++] = c&this.DM; 826 | c >>= this.DB; 827 | } 828 | c += this.s; 829 | } 830 | else { 831 | c += this.s; 832 | while(i < a.t) { 833 | c += a[i]; 834 | r[i++] = c&this.DM; 835 | c >>= this.DB; 836 | } 837 | c += a.s; 838 | } 839 | r.s = (c<0)?-1:0; 840 | if(c > 0) r[i++] = c; 841 | else if(c < -1) r[i++] = this.DV+c; 842 | r.t = i; 843 | r.clamp(); 844 | } 845 | 846 | // (public) this + a 847 | function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } 848 | 849 | // (public) this - a 850 | function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } 851 | 852 | // (public) this * a 853 | function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } 854 | 855 | // (public) this^2 856 | function bnSquare() { var r = nbi(); this.squareTo(r); return r; } 857 | 858 | // (public) this / a 859 | function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } 860 | 861 | // (public) this % a 862 | function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } 863 | 864 | // (public) [this/a,this%a] 865 | function bnDivideAndRemainder(a) { 866 | var q = nbi(), r = nbi(); 867 | this.divRemTo(a,q,r); 868 | return new Array(q,r); 869 | } 870 | 871 | // (protected) this *= n, this >= 0, 1 < n < DV 872 | function bnpDMultiply(n) { 873 | this[this.t] = this.am(0,n-1,this,0,0,this.t); 874 | ++this.t; 875 | this.clamp(); 876 | } 877 | 878 | // (protected) this += n << w words, this >= 0 879 | function bnpDAddOffset(n,w) { 880 | if(n == 0) return; 881 | while(this.t <= w) this[this.t++] = 0; 882 | this[w] += n; 883 | while(this[w] >= this.DV) { 884 | this[w] -= this.DV; 885 | if(++w >= this.t) this[this.t++] = 0; 886 | ++this[w]; 887 | } 888 | } 889 | 890 | // A "null" reducer 891 | function NullExp() {} 892 | function nNop(x) { return x; } 893 | function nMulTo(x,y,r) { x.multiplyTo(y,r); } 894 | function nSqrTo(x,r) { x.squareTo(r); } 895 | 896 | NullExp.prototype.convert = nNop; 897 | NullExp.prototype.revert = nNop; 898 | NullExp.prototype.mulTo = nMulTo; 899 | NullExp.prototype.sqrTo = nSqrTo; 900 | 901 | // (public) this^e 902 | function bnPow(e) { return this.exp(e,new NullExp()); } 903 | 904 | // (protected) r = lower n words of "this * a", a.t <= n 905 | // "this" should be the larger one if appropriate. 906 | function bnpMultiplyLowerTo(a,n,r) { 907 | var i = Math.min(this.t+a.t,n); 908 | r.s = 0; // assumes a,this >= 0 909 | r.t = i; 910 | while(i > 0) r[--i] = 0; 911 | var j; 912 | for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); 913 | for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); 914 | r.clamp(); 915 | } 916 | 917 | // (protected) r = "this * a" without lower n words, n > 0 918 | // "this" should be the larger one if appropriate. 919 | function bnpMultiplyUpperTo(a,n,r) { 920 | --n; 921 | var i = r.t = this.t+a.t-n; 922 | r.s = 0; // assumes a,this >= 0 923 | while(--i >= 0) r[i] = 0; 924 | for(i = Math.max(n-this.t,0); i < a.t; ++i) 925 | r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); 926 | r.clamp(); 927 | r.drShiftTo(1,r); 928 | } 929 | 930 | // Barrett modular reduction 931 | function Barrett(m) { 932 | // setup Barrett 933 | this.r2 = nbi(); 934 | this.q3 = nbi(); 935 | BigInteger.ONE.dlShiftTo(2*m.t,this.r2); 936 | this.mu = this.r2.divide(m); 937 | this.m = m; 938 | } 939 | 940 | function barrettConvert(x) { 941 | if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); 942 | else if(x.compareTo(this.m) < 0) return x; 943 | else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } 944 | } 945 | 946 | function barrettRevert(x) { return x; } 947 | 948 | // x = x mod m (HAC 14.42) 949 | function barrettReduce(x) { 950 | x.drShiftTo(this.m.t-1,this.r2); 951 | if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } 952 | this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); 953 | this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); 954 | while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); 955 | x.subTo(this.r2,x); 956 | while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 957 | } 958 | 959 | // r = x^2 mod m; x != r 960 | function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 961 | 962 | // r = x*y mod m; x,y != r 963 | function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 964 | 965 | Barrett.prototype.convert = barrettConvert; 966 | Barrett.prototype.revert = barrettRevert; 967 | Barrett.prototype.reduce = barrettReduce; 968 | Barrett.prototype.mulTo = barrettMulTo; 969 | Barrett.prototype.sqrTo = barrettSqrTo; 970 | 971 | // (public) this^e % m (HAC 14.85) 972 | function bnModPow(e,m) { 973 | var i = e.bitLength(), k, r = nbv(1), z; 974 | if(i <= 0) return r; 975 | else if(i < 18) k = 1; 976 | else if(i < 48) k = 3; 977 | else if(i < 144) k = 4; 978 | else if(i < 768) k = 5; 979 | else k = 6; 980 | if(i < 8) 981 | z = new Classic(m); 982 | else if(m.isEven()) 983 | z = new Barrett(m); 984 | else 985 | z = new Montgomery(m); 986 | 987 | // precomputation 988 | var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { 991 | var g2 = nbi(); 992 | z.sqrTo(g[1],g2); 993 | while(n <= km) { 994 | g[n] = nbi(); 995 | z.mulTo(g2,g[n-2],g[n]); 996 | n += 2; 997 | } 998 | } 999 | 1000 | var j = e.t-1, w, is1 = true, r2 = nbi(), t; 1001 | i = nbits(e[j])-1; 1002 | while(j >= 0) { 1003 | if(i >= k1) w = (e[j]>>(i-k1))&km; 1004 | else { 1005 | w = (e[j]&((1<<(i+1))-1))<<(k1-i); 1006 | if(j > 0) w |= e[j-1]>>(this.DB+i-k1); 1007 | } 1008 | 1009 | n = k; 1010 | while((w&1) == 0) { w >>= 1; --n; } 1011 | if((i -= n) < 0) { i += this.DB; --j; } 1012 | if(is1) { // ret == 1, don't bother squaring or multiplying it 1013 | g[w].copyTo(r); 1014 | is1 = false; 1015 | } 1016 | else { 1017 | while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } 1018 | if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } 1019 | z.mulTo(r2,g[w],r); 1020 | } 1021 | 1022 | while(j >= 0 && (e[j]&(1< 0) { 1039 | x.rShiftTo(g,x); 1040 | y.rShiftTo(g,y); 1041 | } 1042 | while(x.signum() > 0) { 1043 | if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); 1044 | if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); 1045 | if(x.compareTo(y) >= 0) { 1046 | x.subTo(y,x); 1047 | x.rShiftTo(1,x); 1048 | } 1049 | else { 1050 | y.subTo(x,y); 1051 | y.rShiftTo(1,y); 1052 | } 1053 | } 1054 | if(g > 0) y.lShiftTo(g,y); 1055 | return y; 1056 | } 1057 | 1058 | // (protected) this % n, n < 2^26 1059 | function bnpModInt(n) { 1060 | if(n <= 0) return 0; 1061 | var d = this.DV%n, r = (this.s<0)?n-1:0; 1062 | if(this.t > 0) 1063 | if(d == 0) r = this[0]%n; 1064 | else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; 1065 | return r; 1066 | } 1067 | 1068 | // (public) 1/this % m (HAC 14.61) 1069 | function bnModInverse(m) { 1070 | var ac = m.isEven(); 1071 | if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; 1072 | var u = m.clone(), v = this.clone(); 1073 | var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); 1074 | while(u.signum() != 0) { 1075 | while(u.isEven()) { 1076 | u.rShiftTo(1,u); 1077 | if(ac) { 1078 | if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } 1079 | a.rShiftTo(1,a); 1080 | } 1081 | else if(!b.isEven()) b.subTo(m,b); 1082 | b.rShiftTo(1,b); 1083 | } 1084 | while(v.isEven()) { 1085 | v.rShiftTo(1,v); 1086 | if(ac) { 1087 | if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } 1088 | c.rShiftTo(1,c); 1089 | } 1090 | else if(!d.isEven()) d.subTo(m,d); 1091 | d.rShiftTo(1,d); 1092 | } 1093 | if(u.compareTo(v) >= 0) { 1094 | u.subTo(v,u); 1095 | if(ac) a.subTo(c,a); 1096 | b.subTo(d,b); 1097 | } 1098 | else { 1099 | v.subTo(u,v); 1100 | if(ac) c.subTo(a,c); 1101 | d.subTo(b,d); 1102 | } 1103 | } 1104 | if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; 1105 | if(d.compareTo(m) >= 0) return d.subtract(m); 1106 | if(d.signum() < 0) d.addTo(m,d); else return d; 1107 | if(d.signum() < 0) return d.add(m); else return d; 1108 | } 1109 | 1110 | 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]; 1111 | var lplim = (1<<26)/lowprimes[lowprimes.length-1]; 1112 | 1113 | // (public) test primality with certainty >= 1-.5^t 1114 | function bnIsProbablePrime(t) { 1115 | var i, x = this.abs(); 1116 | if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { 1117 | for(i = 0; i < lowprimes.length; ++i) 1118 | if(x[0] == lowprimes[i]) return true; 1119 | return false; 1120 | } 1121 | if(x.isEven()) return false; 1122 | i = 1; 1123 | while(i < lowprimes.length) { 1124 | var m = lowprimes[i], j = i+1; 1125 | while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; 1126 | m = x.modInt(m); 1127 | while(i < j) if(m%lowprimes[i++] == 0) return false; 1128 | } 1129 | return x.millerRabin(t); 1130 | } 1131 | 1132 | // (protected) true if probably prime (HAC 4.24, Miller-Rabin) 1133 | function bnpMillerRabin(t) { 1134 | var n1 = this.subtract(BigInteger.ONE); 1135 | var k = n1.getLowestSetBit(); 1136 | if(k <= 0) return false; 1137 | var r = n1.shiftRight(k); 1138 | t = (t+1)>>1; 1139 | if(t > lowprimes.length) t = lowprimes.length; 1140 | var a = nbi(); 1141 | for(var i = 0; i < t; ++i) { 1142 | //Pick bases at random, instead of starting at 2 1143 | a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); 1144 | var y = a.modPow(r,this); 1145 | if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { 1146 | var j = 1; 1147 | while(j++ < k && y.compareTo(n1) != 0) { 1148 | y = y.modPowInt(2,this); 1149 | if(y.compareTo(BigInteger.ONE) == 0) return false; 1150 | } 1151 | if(y.compareTo(n1) != 0) return false; 1152 | } 1153 | } 1154 | return true; 1155 | } 1156 | 1157 | // protected 1158 | BigInteger.prototype.chunkSize = bnpChunkSize; 1159 | BigInteger.prototype.toRadix = bnpToRadix; 1160 | BigInteger.prototype.fromRadix = bnpFromRadix; 1161 | BigInteger.prototype.fromNumber = bnpFromNumber; 1162 | BigInteger.prototype.bitwiseTo = bnpBitwiseTo; 1163 | BigInteger.prototype.changeBit = bnpChangeBit; 1164 | BigInteger.prototype.addTo = bnpAddTo; 1165 | BigInteger.prototype.dMultiply = bnpDMultiply; 1166 | BigInteger.prototype.dAddOffset = bnpDAddOffset; 1167 | BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; 1168 | BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; 1169 | BigInteger.prototype.modInt = bnpModInt; 1170 | BigInteger.prototype.millerRabin = bnpMillerRabin; 1171 | 1172 | // public 1173 | BigInteger.prototype.clone = bnClone; 1174 | BigInteger.prototype.intValue = bnIntValue; 1175 | BigInteger.prototype.byteValue = bnByteValue; 1176 | BigInteger.prototype.shortValue = bnShortValue; 1177 | BigInteger.prototype.signum = bnSigNum; 1178 | BigInteger.prototype.toByteArray = bnToByteArray; 1179 | BigInteger.prototype.equals = bnEquals; 1180 | BigInteger.prototype.min = bnMin; 1181 | BigInteger.prototype.max = bnMax; 1182 | BigInteger.prototype.and = bnAnd; 1183 | BigInteger.prototype.or = bnOr; 1184 | BigInteger.prototype.xor = bnXor; 1185 | BigInteger.prototype.andNot = bnAndNot; 1186 | BigInteger.prototype.not = bnNot; 1187 | BigInteger.prototype.shiftLeft = bnShiftLeft; 1188 | BigInteger.prototype.shiftRight = bnShiftRight; 1189 | BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; 1190 | BigInteger.prototype.bitCount = bnBitCount; 1191 | BigInteger.prototype.testBit = bnTestBit; 1192 | BigInteger.prototype.setBit = bnSetBit; 1193 | BigInteger.prototype.clearBit = bnClearBit; 1194 | BigInteger.prototype.flipBit = bnFlipBit; 1195 | BigInteger.prototype.add = bnAdd; 1196 | BigInteger.prototype.subtract = bnSubtract; 1197 | BigInteger.prototype.multiply = bnMultiply; 1198 | BigInteger.prototype.divide = bnDivide; 1199 | BigInteger.prototype.remainder = bnRemainder; 1200 | BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; 1201 | BigInteger.prototype.modPow = bnModPow; 1202 | BigInteger.prototype.modInverse = bnModInverse; 1203 | BigInteger.prototype.pow = bnPow; 1204 | BigInteger.prototype.gcd = bnGCD; 1205 | BigInteger.prototype.isProbablePrime = bnIsProbablePrime; 1206 | 1207 | // JSBN-specific extension 1208 | BigInteger.prototype.square = bnSquare; 1209 | 1210 | // BigInteger interfaces not implemented in jsbn: 1211 | 1212 | // BigInteger(int signum, byte[] magnitude) 1213 | // double doubleValue() 1214 | // float floatValue() 1215 | // int hashCode() 1216 | // long longValue() 1217 | // static BigInteger valueOf(long val) 1218 | // prng4.js - uses Arcfour as a PRNG 1219 | 1220 | function Arcfour() { 1221 | this.i = 0; 1222 | this.j = 0; 1223 | this.S = new Array(); 1224 | } 1225 | 1226 | // Initialize arcfour context from key, an array of ints, each from [0..255] 1227 | function ARC4init(key) { 1228 | var i, j, t; 1229 | for(i = 0; i < 256; ++i) 1230 | this.S[i] = i; 1231 | j = 0; 1232 | for(i = 0; i < 256; ++i) { 1233 | j = (j + this.S[i] + key[i % key.length]) & 255; 1234 | t = this.S[i]; 1235 | this.S[i] = this.S[j]; 1236 | this.S[j] = t; 1237 | } 1238 | this.i = 0; 1239 | this.j = 0; 1240 | } 1241 | 1242 | function ARC4next() { 1243 | var t; 1244 | this.i = (this.i + 1) & 255; 1245 | this.j = (this.j + this.S[this.i]) & 255; 1246 | t = this.S[this.i]; 1247 | this.S[this.i] = this.S[this.j]; 1248 | this.S[this.j] = t; 1249 | return this.S[(t + this.S[this.i]) & 255]; 1250 | } 1251 | 1252 | Arcfour.prototype.init = ARC4init; 1253 | Arcfour.prototype.next = ARC4next; 1254 | 1255 | // Plug in your RNG constructor here 1256 | function prng_newstate() { 1257 | return new Arcfour(); 1258 | } 1259 | 1260 | // Pool size must be a multiple of 4 and greater than 32. 1261 | // An array of bytes the size of the pool will be passed to init() 1262 | var rng_psize = 256; 1263 | // Random number generator - requires a PRNG backend, e.g. prng4.js 1264 | var rng_state; 1265 | var rng_pool; 1266 | var rng_pptr; 1267 | 1268 | // Initialize the pool with junk if needed. 1269 | if(rng_pool == null) { 1270 | rng_pool = new Array(); 1271 | rng_pptr = 0; 1272 | var t; 1273 | if(window.crypto && window.crypto.getRandomValues) { 1274 | // Extract entropy (2048 bits) from RNG if available 1275 | var z = new Uint32Array(256); 1276 | window.crypto.getRandomValues(z); 1277 | for (t = 0; t < z.length; ++t) 1278 | rng_pool[rng_pptr++] = z[t] & 255; 1279 | } 1280 | 1281 | // Use mouse events for entropy, if we do not have enough entropy by the time 1282 | // we need it, entropy will be generated by Math.random. 1283 | var onMouseMoveListener = function(ev) { 1284 | this.count = this.count || 0; 1285 | if (this.count >= 256 || rng_pptr >= rng_psize) { 1286 | if (window.removeEventListener) 1287 | window.removeEventListener("mousemove", onMouseMoveListener); 1288 | else if (window.detachEvent) 1289 | window.detachEvent("onmousemove", onMouseMoveListener); 1290 | return; 1291 | } 1292 | this.count += 1; 1293 | var mouseCoordinates = ev.x + ev.y; 1294 | rng_pool[rng_pptr++] = mouseCoordinates & 255; 1295 | }; 1296 | if (window.addEventListener) 1297 | window.addEventListener("mousemove", onMouseMoveListener); 1298 | else if (window.attachEvent) 1299 | window.attachEvent("onmousemove", onMouseMoveListener); 1300 | 1301 | } 1302 | 1303 | function rng_get_byte() { 1304 | if(rng_state == null) { 1305 | rng_state = prng_newstate(); 1306 | // At this point, we may not have collected enough entropy. If not, fall back to Math.random 1307 | while (rng_pptr < rng_psize) { 1308 | var random = Math.floor(65536 * Math.random()); 1309 | rng_pool[rng_pptr++] = random & 255; 1310 | } 1311 | rng_state.init(rng_pool); 1312 | for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) 1313 | rng_pool[rng_pptr] = 0; 1314 | rng_pptr = 0; 1315 | } 1316 | // TODO: allow reseeding after first request 1317 | return rng_state.next(); 1318 | } 1319 | 1320 | function rng_get_bytes(ba) { 1321 | var i; 1322 | for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); 1323 | } 1324 | 1325 | function SecureRandom() {} 1326 | 1327 | SecureRandom.prototype.nextBytes = rng_get_bytes; 1328 | // Depends on jsbn.js and rng.js 1329 | 1330 | // Version 1.1: support utf-8 encoding in pkcs1pad2 1331 | 1332 | // convert a (hex) string to a bignum object 1333 | function parseBigInt(str,r) { 1334 | return new BigInteger(str,r); 1335 | } 1336 | 1337 | function linebrk(s,n) { 1338 | var ret = ""; 1339 | var i = 0; 1340 | while(i + n < s.length) { 1341 | ret += s.substring(i,i+n) + "\n"; 1342 | i += n; 1343 | } 1344 | return ret + s.substring(i,s.length); 1345 | } 1346 | 1347 | function byte2Hex(b) { 1348 | if(b < 0x10) 1349 | return "0" + b.toString(16); 1350 | else 1351 | return b.toString(16); 1352 | } 1353 | 1354 | // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint 1355 | function pkcs1pad2(s,n) { 1356 | if(n < s.length + 11) { // TODO: fix for utf-8 1357 | console.error("Message too long for RSA"); 1358 | return null; 1359 | } 1360 | var ba = new Array(); 1361 | var i = s.length - 1; 1362 | while(i >= 0 && n > 0) { 1363 | var c = s.charCodeAt(i--); 1364 | if(c < 128) { // encode using utf-8 1365 | ba[--n] = c; 1366 | } 1367 | else if((c > 127) && (c < 2048)) { 1368 | ba[--n] = (c & 63) | 128; 1369 | ba[--n] = (c >> 6) | 192; 1370 | } 1371 | else { 1372 | ba[--n] = (c & 63) | 128; 1373 | ba[--n] = ((c >> 6) & 63) | 128; 1374 | ba[--n] = (c >> 12) | 224; 1375 | } 1376 | } 1377 | ba[--n] = 0; 1378 | var rng = new SecureRandom(); 1379 | var x = new Array(); 1380 | while(n > 2) { // random non-zero pad 1381 | x[0] = 0; 1382 | while(x[0] == 0) rng.nextBytes(x); 1383 | ba[--n] = x[0]; 1384 | } 1385 | ba[--n] = 2; 1386 | ba[--n] = 0; 1387 | return new BigInteger(ba); 1388 | } 1389 | 1390 | // "empty" RSA key constructor 1391 | function RSAKey() { 1392 | this.n = null; 1393 | this.e = 0; 1394 | this.d = null; 1395 | this.p = null; 1396 | this.q = null; 1397 | this.dmp1 = null; 1398 | this.dmq1 = null; 1399 | this.coeff = null; 1400 | } 1401 | 1402 | // Set the public key fields N and e from hex strings 1403 | function RSASetPublic(N,E) { 1404 | if(N != null && E != null && N.length > 0 && E.length > 0) { 1405 | this.n = parseBigInt(N,16); 1406 | this.e = parseInt(E,16); 1407 | } 1408 | else 1409 | console.error("Invalid RSA public key"); 1410 | } 1411 | 1412 | // Perform raw public operation on "x": return x^e (mod n) 1413 | function RSADoPublic(x) { 1414 | return x.modPowInt(this.e, this.n); 1415 | } 1416 | 1417 | // Return the PKCS#1 RSA encryption of "text" as an even-length hex string 1418 | function RSAEncrypt(text) { 1419 | var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3); 1420 | if(m == null) return null; 1421 | var c = this.doPublic(m); 1422 | if(c == null) return null; 1423 | var h = c.toString(16); 1424 | if((h.length & 1) == 0) return h; else return "0" + h; 1425 | } 1426 | 1427 | // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string 1428 | //function RSAEncryptB64(text) { 1429 | // var h = this.encrypt(text); 1430 | // if(h) return hex2b64(h); else return null; 1431 | //} 1432 | 1433 | // protected 1434 | RSAKey.prototype.doPublic = RSADoPublic; 1435 | 1436 | // public 1437 | RSAKey.prototype.setPublic = RSASetPublic; 1438 | RSAKey.prototype.encrypt = RSAEncrypt; 1439 | //RSAKey.prototype.encrypt_b64 = RSAEncryptB64; 1440 | // Depends on rsa.js and jsbn2.js 1441 | 1442 | // Version 1.1: support utf-8 decoding in pkcs1unpad2 1443 | 1444 | // Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext 1445 | function pkcs1unpad2(d,n) { 1446 | var b = d.toByteArray(); 1447 | var i = 0; 1448 | while(i < b.length && b[i] == 0) ++i; 1449 | if(b.length-i != n-1 || b[i] != 2) 1450 | return null; 1451 | ++i; 1452 | while(b[i] != 0) 1453 | if(++i >= b.length) return null; 1454 | var ret = ""; 1455 | while(++i < b.length) { 1456 | var c = b[i] & 255; 1457 | if(c < 128) { // utf-8 decode 1458 | ret += String.fromCharCode(c); 1459 | } 1460 | else if((c > 191) && (c < 224)) { 1461 | ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63)); 1462 | ++i; 1463 | } 1464 | else { 1465 | ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63)); 1466 | i += 2; 1467 | } 1468 | } 1469 | return ret; 1470 | } 1471 | 1472 | // Set the private key fields N, e, and d from hex strings 1473 | function RSASetPrivate(N,E,D) { 1474 | if(N != null && E != null && N.length > 0 && E.length > 0) { 1475 | this.n = parseBigInt(N,16); 1476 | this.e = parseInt(E,16); 1477 | this.d = parseBigInt(D,16); 1478 | } 1479 | else 1480 | console.error("Invalid RSA private key"); 1481 | } 1482 | 1483 | // Set the private key fields N, e, d and CRT params from hex strings 1484 | function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) { 1485 | if(N != null && E != null && N.length > 0 && E.length > 0) { 1486 | this.n = parseBigInt(N,16); 1487 | this.e = parseInt(E,16); 1488 | this.d = parseBigInt(D,16); 1489 | this.p = parseBigInt(P,16); 1490 | this.q = parseBigInt(Q,16); 1491 | this.dmp1 = parseBigInt(DP,16); 1492 | this.dmq1 = parseBigInt(DQ,16); 1493 | this.coeff = parseBigInt(C,16); 1494 | } 1495 | else 1496 | console.error("Invalid RSA private key"); 1497 | } 1498 | 1499 | // Generate a new random private key B bits long, using public expt E 1500 | function RSAGenerate(B,E) { 1501 | var rng = new SecureRandom(); 1502 | var qs = B>>1; 1503 | this.e = parseInt(E,16); 1504 | var ee = new BigInteger(E,16); 1505 | for(;;) { 1506 | for(;;) { 1507 | this.p = new BigInteger(B-qs,1,rng); 1508 | if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break; 1509 | } 1510 | for(;;) { 1511 | this.q = new BigInteger(qs,1,rng); 1512 | if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break; 1513 | } 1514 | if(this.p.compareTo(this.q) <= 0) { 1515 | var t = this.p; 1516 | this.p = this.q; 1517 | this.q = t; 1518 | } 1519 | var p1 = this.p.subtract(BigInteger.ONE); 1520 | var q1 = this.q.subtract(BigInteger.ONE); 1521 | var phi = p1.multiply(q1); 1522 | if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { 1523 | this.n = this.p.multiply(this.q); 1524 | this.d = ee.modInverse(phi); 1525 | this.dmp1 = this.d.mod(p1); 1526 | this.dmq1 = this.d.mod(q1); 1527 | this.coeff = this.q.modInverse(this.p); 1528 | break; 1529 | } 1530 | } 1531 | } 1532 | 1533 | // Perform raw private operation on "x": return x^d (mod n) 1534 | function RSADoPrivate(x) { 1535 | if(this.p == null || this.q == null) 1536 | return x.modPow(this.d, this.n); 1537 | 1538 | // TODO: re-calculate any missing CRT params 1539 | var xp = x.mod(this.p).modPow(this.dmp1, this.p); 1540 | var xq = x.mod(this.q).modPow(this.dmq1, this.q); 1541 | 1542 | while(xp.compareTo(xq) < 0) 1543 | xp = xp.add(this.p); 1544 | return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq); 1545 | } 1546 | 1547 | // Return the PKCS#1 RSA decryption of "ctext". 1548 | // "ctext" is an even-length hex string and the output is a plain string. 1549 | function RSADecrypt(ctext) { 1550 | var c = parseBigInt(ctext, 16); 1551 | var m = this.doPrivate(c); 1552 | if(m == null) return null; 1553 | return pkcs1unpad2(m, (this.n.bitLength()+7)>>3); 1554 | } 1555 | 1556 | // Return the PKCS#1 RSA decryption of "ctext". 1557 | // "ctext" is a Base64-encoded string and the output is a plain string. 1558 | //function RSAB64Decrypt(ctext) { 1559 | // var h = b64tohex(ctext); 1560 | // if(h) return this.decrypt(h); else return null; 1561 | //} 1562 | 1563 | // protected 1564 | RSAKey.prototype.doPrivate = RSADoPrivate; 1565 | 1566 | // public 1567 | RSAKey.prototype.setPrivate = RSASetPrivate; 1568 | RSAKey.prototype.setPrivateEx = RSASetPrivateEx; 1569 | RSAKey.prototype.generate = RSAGenerate; 1570 | RSAKey.prototype.decrypt = RSADecrypt; 1571 | //RSAKey.prototype.b64_decrypt = RSAB64Decrypt; 1572 | // Copyright (c) 2011 Kevin M Burns Jr. 1573 | // All Rights Reserved. 1574 | // See "LICENSE" for details. 1575 | // 1576 | // Extension to jsbn which adds facilities for asynchronous RSA key generation 1577 | // Primarily created to avoid execution timeout on mobile devices 1578 | // 1579 | // http://www-cs-students.stanford.edu/~tjw/jsbn/ 1580 | // 1581 | // --- 1582 | 1583 | (function(){ 1584 | 1585 | // Generate a new random private key B bits long, using public expt E 1586 | var RSAGenerateAsync = function (B, E, callback) { 1587 | //var rng = new SeededRandom(); 1588 | var rng = new SecureRandom(); 1589 | var qs = B >> 1; 1590 | this.e = parseInt(E, 16); 1591 | var ee = new BigInteger(E, 16); 1592 | var rsa = this; 1593 | // These functions have non-descript names because they were originally for(;;) loops. 1594 | // I don't know about cryptography to give them better names than loop1-4. 1595 | var loop1 = function() { 1596 | var loop4 = function() { 1597 | if (rsa.p.compareTo(rsa.q) <= 0) { 1598 | var t = rsa.p; 1599 | rsa.p = rsa.q; 1600 | rsa.q = t; 1601 | } 1602 | var p1 = rsa.p.subtract(BigInteger.ONE); 1603 | var q1 = rsa.q.subtract(BigInteger.ONE); 1604 | var phi = p1.multiply(q1); 1605 | if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { 1606 | rsa.n = rsa.p.multiply(rsa.q); 1607 | rsa.d = ee.modInverse(phi); 1608 | rsa.dmp1 = rsa.d.mod(p1); 1609 | rsa.dmq1 = rsa.d.mod(q1); 1610 | rsa.coeff = rsa.q.modInverse(rsa.p); 1611 | setTimeout(function(){callback()},0); // escape 1612 | } else { 1613 | setTimeout(loop1,0); 1614 | } 1615 | }; 1616 | var loop3 = function() { 1617 | rsa.q = nbi(); 1618 | rsa.q.fromNumberAsync(qs, 1, rng, function(){ 1619 | rsa.q.subtract(BigInteger.ONE).gcda(ee, function(r){ 1620 | if (r.compareTo(BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) { 1621 | setTimeout(loop4,0); 1622 | } else { 1623 | setTimeout(loop3,0); 1624 | } 1625 | }); 1626 | }); 1627 | }; 1628 | var loop2 = function() { 1629 | rsa.p = nbi(); 1630 | rsa.p.fromNumberAsync(B - qs, 1, rng, function(){ 1631 | rsa.p.subtract(BigInteger.ONE).gcda(ee, function(r){ 1632 | if (r.compareTo(BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) { 1633 | setTimeout(loop3,0); 1634 | } else { 1635 | setTimeout(loop2,0); 1636 | } 1637 | }); 1638 | }); 1639 | }; 1640 | setTimeout(loop2,0); 1641 | }; 1642 | setTimeout(loop1,0); 1643 | }; 1644 | RSAKey.prototype.generateAsync = RSAGenerateAsync; 1645 | 1646 | // Public API method 1647 | var bnGCDAsync = function (a, callback) { 1648 | var x = (this.s < 0) ? this.negate() : this.clone(); 1649 | var y = (a.s < 0) ? a.negate() : a.clone(); 1650 | if (x.compareTo(y) < 0) { 1651 | var t = x; 1652 | x = y; 1653 | y = t; 1654 | } 1655 | var i = x.getLowestSetBit(), 1656 | g = y.getLowestSetBit(); 1657 | if (g < 0) { 1658 | callback(x); 1659 | return; 1660 | } 1661 | if (i < g) g = i; 1662 | if (g > 0) { 1663 | x.rShiftTo(g, x); 1664 | y.rShiftTo(g, y); 1665 | } 1666 | // Workhorse of the algorithm, gets called 200 - 800 times per 512 bit keygen. 1667 | var gcda1 = function() { 1668 | if ((i = x.getLowestSetBit()) > 0){ x.rShiftTo(i, x); } 1669 | if ((i = y.getLowestSetBit()) > 0){ y.rShiftTo(i, y); } 1670 | if (x.compareTo(y) >= 0) { 1671 | x.subTo(y, x); 1672 | x.rShiftTo(1, x); 1673 | } else { 1674 | y.subTo(x, y); 1675 | y.rShiftTo(1, y); 1676 | } 1677 | if(!(x.signum() > 0)) { 1678 | if (g > 0) y.lShiftTo(g, y); 1679 | setTimeout(function(){callback(y)},0); // escape 1680 | } else { 1681 | setTimeout(gcda1,0); 1682 | } 1683 | }; 1684 | setTimeout(gcda1,10); 1685 | }; 1686 | BigInteger.prototype.gcda = bnGCDAsync; 1687 | 1688 | // (protected) alternate constructor 1689 | var bnpFromNumberAsync = function (a,b,c,callback) { 1690 | if("number" == typeof b) { 1691 | if(a < 2) { 1692 | this.fromInt(1); 1693 | } else { 1694 | this.fromNumber(a,c); 1695 | if(!this.testBit(a-1)){ 1696 | this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); 1697 | } 1698 | if(this.isEven()) { 1699 | this.dAddOffset(1,0); 1700 | } 1701 | var bnp = this; 1702 | var bnpfn1 = function(){ 1703 | bnp.dAddOffset(2,0); 1704 | if(bnp.bitLength() > a) bnp.subTo(BigInteger.ONE.shiftLeft(a-1),bnp); 1705 | if(bnp.isProbablePrime(b)) { 1706 | setTimeout(function(){callback()},0); // escape 1707 | } else { 1708 | setTimeout(bnpfn1,0); 1709 | } 1710 | }; 1711 | setTimeout(bnpfn1,0); 1712 | } 1713 | } else { 1714 | var x = new Array(), t = a&7; 1715 | x.length = (a>>3)+1; 1716 | b.nextBytes(x); 1717 | if(t > 0) x[0] &= ((1<> 6) + b64map.charAt(c & 63); 1733 | } 1734 | if(i+1 == h.length) { 1735 | c = parseInt(h.substring(i,i+1),16); 1736 | ret += b64map.charAt(c << 2); 1737 | } 1738 | else if(i+2 == h.length) { 1739 | c = parseInt(h.substring(i,i+2),16); 1740 | ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); 1741 | } 1742 | while((ret.length & 3) > 0) ret += b64pad; 1743 | return ret; 1744 | } 1745 | 1746 | // convert a base64 string to hex 1747 | function b64tohex(s) { 1748 | var ret = "" 1749 | var i; 1750 | var k = 0; // b64 state, 0-3 1751 | var slop; 1752 | for(i = 0; i < s.length; ++i) { 1753 | if(s.charAt(i) == b64pad) break; 1754 | v = b64map.indexOf(s.charAt(i)); 1755 | if(v < 0) continue; 1756 | if(k == 0) { 1757 | ret += int2char(v >> 2); 1758 | slop = v & 3; 1759 | k = 1; 1760 | } 1761 | else if(k == 1) { 1762 | ret += int2char((slop << 2) | (v >> 4)); 1763 | slop = v & 0xf; 1764 | k = 2; 1765 | } 1766 | else if(k == 2) { 1767 | ret += int2char(slop); 1768 | ret += int2char(v >> 2); 1769 | slop = v & 3; 1770 | k = 3; 1771 | } 1772 | else { 1773 | ret += int2char((slop << 2) | (v >> 4)); 1774 | ret += int2char(v & 0xf); 1775 | k = 0; 1776 | } 1777 | } 1778 | if(k == 1) 1779 | ret += int2char(slop << 2); 1780 | return ret; 1781 | } 1782 | 1783 | // convert a base64 string to a byte/number array 1784 | function b64toBA(s) { 1785 | //piggyback on b64tohex for now, optimize later 1786 | var h = b64tohex(s); 1787 | var i; 1788 | var a = new Array(); 1789 | for(i = 0; 2*i < h.length; ++i) { 1790 | a[i] = parseInt(h.substring(2*i,2*i+2),16); 1791 | } 1792 | return a; 1793 | } 1794 | /*! asn1-1.0.2.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license 1795 | */ 1796 | 1797 | var JSX = JSX || {}; 1798 | JSX.env = JSX.env || {}; 1799 | 1800 | var L = JSX, OP = Object.prototype, FUNCTION_TOSTRING = '[object Function]',ADD = ["toString", "valueOf"]; 1801 | 1802 | JSX.env.parseUA = function(agent) { 1803 | 1804 | var numberify = function(s) { 1805 | var c = 0; 1806 | return parseFloat(s.replace(/\./g, function() { 1807 | return (c++ == 1) ? '' : '.'; 1808 | })); 1809 | }, 1810 | 1811 | nav = navigator, 1812 | o = { 1813 | ie: 0, 1814 | opera: 0, 1815 | gecko: 0, 1816 | webkit: 0, 1817 | chrome: 0, 1818 | mobile: null, 1819 | air: 0, 1820 | ipad: 0, 1821 | iphone: 0, 1822 | ipod: 0, 1823 | ios: null, 1824 | android: 0, 1825 | webos: 0, 1826 | caja: nav && nav.cajaVersion, 1827 | secure: false, 1828 | os: null 1829 | 1830 | }, 1831 | 1832 | ua = agent || (navigator && navigator.userAgent), 1833 | loc = window && window.location, 1834 | href = loc && loc.href, 1835 | m; 1836 | 1837 | o.secure = href && (href.toLowerCase().indexOf("https") === 0); 1838 | 1839 | if (ua) { 1840 | 1841 | if ((/windows|win32/i).test(ua)) { 1842 | o.os = 'windows'; 1843 | } else if ((/macintosh/i).test(ua)) { 1844 | o.os = 'macintosh'; 1845 | } else if ((/rhino/i).test(ua)) { 1846 | o.os = 'rhino'; 1847 | } 1848 | if ((/KHTML/).test(ua)) { 1849 | o.webkit = 1; 1850 | } 1851 | m = ua.match(/AppleWebKit\/([^\s]*)/); 1852 | if (m && m[1]) { 1853 | o.webkit = numberify(m[1]); 1854 | if (/ Mobile\//.test(ua)) { 1855 | o.mobile = 'Apple'; // iPhone or iPod Touch 1856 | m = ua.match(/OS ([^\s]*)/); 1857 | if (m && m[1]) { 1858 | m = numberify(m[1].replace('_', '.')); 1859 | } 1860 | o.ios = m; 1861 | o.ipad = o.ipod = o.iphone = 0; 1862 | m = ua.match(/iPad|iPod|iPhone/); 1863 | if (m && m[0]) { 1864 | o[m[0].toLowerCase()] = o.ios; 1865 | } 1866 | } else { 1867 | m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/); 1868 | if (m) { 1869 | o.mobile = m[0]; 1870 | } 1871 | if (/webOS/.test(ua)) { 1872 | o.mobile = 'WebOS'; 1873 | m = ua.match(/webOS\/([^\s]*);/); 1874 | if (m && m[1]) { 1875 | o.webos = numberify(m[1]); 1876 | } 1877 | } 1878 | if (/ Android/.test(ua)) { 1879 | o.mobile = 'Android'; 1880 | m = ua.match(/Android ([^\s]*);/); 1881 | if (m && m[1]) { 1882 | o.android = numberify(m[1]); 1883 | } 1884 | } 1885 | } 1886 | m = ua.match(/Chrome\/([^\s]*)/); 1887 | if (m && m[1]) { 1888 | o.chrome = numberify(m[1]); // Chrome 1889 | } else { 1890 | m = ua.match(/AdobeAIR\/([^\s]*)/); 1891 | if (m) { 1892 | o.air = m[0]; // Adobe AIR 1.0 or better 1893 | } 1894 | } 1895 | } 1896 | if (!o.webkit) { 1897 | m = ua.match(/Opera[\s\/]([^\s]*)/); 1898 | if (m && m[1]) { 1899 | o.opera = numberify(m[1]); 1900 | m = ua.match(/Version\/([^\s]*)/); 1901 | if (m && m[1]) { 1902 | o.opera = numberify(m[1]); // opera 10+ 1903 | } 1904 | m = ua.match(/Opera Mini[^;]*/); 1905 | if (m) { 1906 | o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 1907 | } 1908 | } else { // not opera or webkit 1909 | m = ua.match(/MSIE\s([^;]*)/); 1910 | if (m && m[1]) { 1911 | o.ie = numberify(m[1]); 1912 | } else { // not opera, webkit, or ie 1913 | m = ua.match(/Gecko\/([^\s]*)/); 1914 | if (m) { 1915 | o.gecko = 1; // Gecko detected, look for revision 1916 | m = ua.match(/rv:([^\s\)]*)/); 1917 | if (m && m[1]) { 1918 | o.gecko = numberify(m[1]); 1919 | } 1920 | } 1921 | } 1922 | } 1923 | } 1924 | } 1925 | return o; 1926 | }; 1927 | 1928 | JSX.env.ua = JSX.env.parseUA(); 1929 | 1930 | JSX.isFunction = function(o) { 1931 | return (typeof o === 'function') || OP.toString.apply(o) === FUNCTION_TOSTRING; 1932 | }; 1933 | 1934 | JSX._IEEnumFix = (JSX.env.ua.ie) ? function(r, s) { 1935 | var i, fname, f; 1936 | for (i=0;iMIT License 1991 | */ 1992 | 1993 | /** 1994 | * kjur's class library name space 1995 | *

1996 | * This name space provides following name spaces: 1997 | *

    1998 | *
  • {@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder
  • 1999 | *
  • {@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL
  • 2000 | *
  • {@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature 2001 | * class and utilities
  • 2002 | *
2003 | *

2004 | * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2. 2005 | * @name KJUR 2006 | * @namespace kjur's class library name space 2007 | */ 2008 | if (typeof KJUR == "undefined" || !KJUR) KJUR = {}; 2009 | 2010 | /** 2011 | * kjur's ASN.1 class library name space 2012 | *

2013 | * This is ITU-T X.690 ASN.1 DER encoder class library and 2014 | * class structure and methods is very similar to 2015 | * org.bouncycastle.asn1 package of 2016 | * well known BouncyCaslte Cryptography Library. 2017 | * 2018 | *

PROVIDING ASN.1 PRIMITIVES

2019 | * Here are ASN.1 DER primitive classes. 2020 | *
    2021 | *
  • {@link KJUR.asn1.DERBoolean}
  • 2022 | *
  • {@link KJUR.asn1.DERInteger}
  • 2023 | *
  • {@link KJUR.asn1.DERBitString}
  • 2024 | *
  • {@link KJUR.asn1.DEROctetString}
  • 2025 | *
  • {@link KJUR.asn1.DERNull}
  • 2026 | *
  • {@link KJUR.asn1.DERObjectIdentifier}
  • 2027 | *
  • {@link KJUR.asn1.DERUTF8String}
  • 2028 | *
  • {@link KJUR.asn1.DERNumericString}
  • 2029 | *
  • {@link KJUR.asn1.DERPrintableString}
  • 2030 | *
  • {@link KJUR.asn1.DERTeletexString}
  • 2031 | *
  • {@link KJUR.asn1.DERIA5String}
  • 2032 | *
  • {@link KJUR.asn1.DERUTCTime}
  • 2033 | *
  • {@link KJUR.asn1.DERGeneralizedTime}
  • 2034 | *
  • {@link KJUR.asn1.DERSequence}
  • 2035 | *
  • {@link KJUR.asn1.DERSet}
  • 2036 | *
2037 | * 2038 | *

OTHER ASN.1 CLASSES

2039 | *
    2040 | *
  • {@link KJUR.asn1.ASN1Object}
  • 2041 | *
  • {@link KJUR.asn1.DERAbstractString}
  • 2042 | *
  • {@link KJUR.asn1.DERAbstractTime}
  • 2043 | *
  • {@link KJUR.asn1.DERAbstractStructured}
  • 2044 | *
  • {@link KJUR.asn1.DERTaggedObject}
  • 2045 | *
2046 | *

2047 | * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2. 2048 | * @name KJUR.asn1 2049 | * @namespace 2050 | */ 2051 | if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {}; 2052 | 2053 | /** 2054 | * ASN1 utilities class 2055 | * @name KJUR.asn1.ASN1Util 2056 | * @classs ASN1 utilities class 2057 | * @since asn1 1.0.2 2058 | */ 2059 | KJUR.asn1.ASN1Util = new function() { 2060 | this.integerToByteHex = function(i) { 2061 | var h = i.toString(16); 2062 | if ((h.length % 2) == 1) h = '0' + h; 2063 | return h; 2064 | }; 2065 | this.bigIntToMinTwosComplementsHex = function(bigIntegerValue) { 2066 | var h = bigIntegerValue.toString(16); 2067 | if (h.substr(0, 1) != '-') { 2068 | if (h.length % 2 == 1) { 2069 | h = '0' + h; 2070 | } else { 2071 | if (! h.match(/^[0-7]/)) { 2072 | h = '00' + h; 2073 | } 2074 | } 2075 | } else { 2076 | var hPos = h.substr(1); 2077 | var xorLen = hPos.length; 2078 | if (xorLen % 2 == 1) { 2079 | xorLen += 1; 2080 | } else { 2081 | if (! h.match(/^[0-7]/)) { 2082 | xorLen += 2; 2083 | } 2084 | } 2085 | var hMask = ''; 2086 | for (var i = 0; i < xorLen; i++) { 2087 | hMask += 'f'; 2088 | } 2089 | var biMask = new BigInteger(hMask, 16); 2090 | var biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE); 2091 | h = biNeg.toString(16).replace(/^-/, ''); 2092 | } 2093 | return h; 2094 | }; 2095 | /** 2096 | * get PEM string from hexadecimal data and header string 2097 | * @name getPEMStringFromHex 2098 | * @memberOf KJUR.asn1.ASN1Util 2099 | * @function 2100 | * @param {String} dataHex hexadecimal string of PEM body 2101 | * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY') 2102 | * @return {String} PEM formatted string of input data 2103 | * @description 2104 | * @example 2105 | * var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex('616161', 'RSA PRIVATE KEY'); 2106 | * // value of pem will be: 2107 | * -----BEGIN PRIVATE KEY----- 2108 | * YWFh 2109 | * -----END PRIVATE KEY----- 2110 | */ 2111 | this.getPEMStringFromHex = function(dataHex, pemHeader) { 2112 | var dataWA = CryptoJS.enc.Hex.parse(dataHex); 2113 | var dataB64 = CryptoJS.enc.Base64.stringify(dataWA); 2114 | var pemBody = dataB64.replace(/(.{64})/g, "$1\r\n"); 2115 | pemBody = pemBody.replace(/\r\n$/, ''); 2116 | return "-----BEGIN " + pemHeader + "-----\r\n" + 2117 | pemBody + 2118 | "\r\n-----END " + pemHeader + "-----\r\n"; 2119 | }; 2120 | }; 2121 | 2122 | // ******************************************************************** 2123 | // Abstract ASN.1 Classes 2124 | // ******************************************************************** 2125 | 2126 | // ******************************************************************** 2127 | 2128 | /** 2129 | * base class for ASN.1 DER encoder object 2130 | * @name KJUR.asn1.ASN1Object 2131 | * @class base class for ASN.1 DER encoder object 2132 | * @property {Boolean} isModified flag whether internal data was changed 2133 | * @property {String} hTLV hexadecimal string of ASN.1 TLV 2134 | * @property {String} hT hexadecimal string of ASN.1 TLV tag(T) 2135 | * @property {String} hL hexadecimal string of ASN.1 TLV length(L) 2136 | * @property {String} hV hexadecimal string of ASN.1 TLV value(V) 2137 | * @description 2138 | */ 2139 | KJUR.asn1.ASN1Object = function() { 2140 | var isModified = true; 2141 | var hTLV = null; 2142 | var hT = '00' 2143 | var hL = '00'; 2144 | var hV = ''; 2145 | 2146 | /** 2147 | * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V) 2148 | * @name getLengthHexFromValue 2149 | * @memberOf KJUR.asn1.ASN1Object 2150 | * @function 2151 | * @return {String} hexadecimal string of ASN.1 TLV length(L) 2152 | */ 2153 | this.getLengthHexFromValue = function() { 2154 | if (typeof this.hV == "undefined" || this.hV == null) { 2155 | throw "this.hV is null or undefined."; 2156 | } 2157 | if (this.hV.length % 2 == 1) { 2158 | throw "value hex must be even length: n=" + hV.length + ",v=" + this.hV; 2159 | } 2160 | var n = this.hV.length / 2; 2161 | var hN = n.toString(16); 2162 | if (hN.length % 2 == 1) { 2163 | hN = "0" + hN; 2164 | } 2165 | if (n < 128) { 2166 | return hN; 2167 | } else { 2168 | var hNlen = hN.length / 2; 2169 | if (hNlen > 15) { 2170 | throw "ASN.1 length too long to represent by 8x: n = " + n.toString(16); 2171 | } 2172 | var head = 128 + hNlen; 2173 | return head.toString(16) + hN; 2174 | } 2175 | }; 2176 | 2177 | /** 2178 | * get hexadecimal string of ASN.1 TLV bytes 2179 | * @name getEncodedHex 2180 | * @memberOf KJUR.asn1.ASN1Object 2181 | * @function 2182 | * @return {String} hexadecimal string of ASN.1 TLV 2183 | */ 2184 | this.getEncodedHex = function() { 2185 | if (this.hTLV == null || this.isModified) { 2186 | this.hV = this.getFreshValueHex(); 2187 | this.hL = this.getLengthHexFromValue(); 2188 | this.hTLV = this.hT + this.hL + this.hV; 2189 | this.isModified = false; 2190 | //console.error("first time: " + this.hTLV); 2191 | } 2192 | return this.hTLV; 2193 | }; 2194 | 2195 | /** 2196 | * get hexadecimal string of ASN.1 TLV value(V) bytes 2197 | * @name getValueHex 2198 | * @memberOf KJUR.asn1.ASN1Object 2199 | * @function 2200 | * @return {String} hexadecimal string of ASN.1 TLV value(V) bytes 2201 | */ 2202 | this.getValueHex = function() { 2203 | this.getEncodedHex(); 2204 | return this.hV; 2205 | } 2206 | 2207 | this.getFreshValueHex = function() { 2208 | return ''; 2209 | }; 2210 | }; 2211 | 2212 | // == BEGIN DERAbstractString ================================================ 2213 | /** 2214 | * base class for ASN.1 DER string classes 2215 | * @name KJUR.asn1.DERAbstractString 2216 | * @class base class for ASN.1 DER string classes 2217 | * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) 2218 | * @property {String} s internal string of value 2219 | * @extends KJUR.asn1.ASN1Object 2220 | * @description 2221 | *
2222 | * As for argument 'params' for constructor, you can specify one of 2223 | * following properties: 2224 | *
    2225 | *
  • str - specify initial ASN.1 value(V) by a string
  • 2226 | *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • 2227 | *
2228 | * NOTE: 'params' can be omitted. 2229 | */ 2230 | KJUR.asn1.DERAbstractString = function(params) { 2231 | KJUR.asn1.DERAbstractString.superclass.constructor.call(this); 2232 | var s = null; 2233 | var hV = null; 2234 | 2235 | /** 2236 | * get string value of this string object 2237 | * @name getString 2238 | * @memberOf KJUR.asn1.DERAbstractString 2239 | * @function 2240 | * @return {String} string value of this string object 2241 | */ 2242 | this.getString = function() { 2243 | return this.s; 2244 | }; 2245 | 2246 | /** 2247 | * set value by a string 2248 | * @name setString 2249 | * @memberOf KJUR.asn1.DERAbstractString 2250 | * @function 2251 | * @param {String} newS value by a string to set 2252 | */ 2253 | this.setString = function(newS) { 2254 | this.hTLV = null; 2255 | this.isModified = true; 2256 | this.s = newS; 2257 | this.hV = stohex(this.s); 2258 | }; 2259 | 2260 | /** 2261 | * set value by a hexadecimal string 2262 | * @name setStringHex 2263 | * @memberOf KJUR.asn1.DERAbstractString 2264 | * @function 2265 | * @param {String} newHexString value by a hexadecimal string to set 2266 | */ 2267 | this.setStringHex = function(newHexString) { 2268 | this.hTLV = null; 2269 | this.isModified = true; 2270 | this.s = null; 2271 | this.hV = newHexString; 2272 | }; 2273 | 2274 | this.getFreshValueHex = function() { 2275 | return this.hV; 2276 | }; 2277 | 2278 | if (typeof params != "undefined") { 2279 | if (typeof params['str'] != "undefined") { 2280 | this.setString(params['str']); 2281 | } else if (typeof params['hex'] != "undefined") { 2282 | this.setStringHex(params['hex']); 2283 | } 2284 | } 2285 | }; 2286 | JSX.extend(KJUR.asn1.DERAbstractString, KJUR.asn1.ASN1Object); 2287 | // == END DERAbstractString ================================================ 2288 | 2289 | // == BEGIN DERAbstractTime ================================================== 2290 | /** 2291 | * base class for ASN.1 DER Generalized/UTCTime class 2292 | * @name KJUR.asn1.DERAbstractTime 2293 | * @class base class for ASN.1 DER Generalized/UTCTime class 2294 | * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) 2295 | * @extends KJUR.asn1.ASN1Object 2296 | * @description 2297 | * @see KJUR.asn1.ASN1Object - superclass 2298 | */ 2299 | KJUR.asn1.DERAbstractTime = function(params) { 2300 | KJUR.asn1.DERAbstractTime.superclass.constructor.call(this); 2301 | var s = null; 2302 | var date = null; 2303 | 2304 | // --- PRIVATE METHODS -------------------- 2305 | this.localDateToUTC = function(d) { 2306 | utc = d.getTime() + (d.getTimezoneOffset() * 60000); 2307 | var utcDate = new Date(utc); 2308 | return utcDate; 2309 | }; 2310 | 2311 | this.formatDate = function(dateObject, type) { 2312 | var pad = this.zeroPadding; 2313 | var d = this.localDateToUTC(dateObject); 2314 | var year = String(d.getFullYear()); 2315 | if (type == 'utc') year = year.substr(2, 2); 2316 | var month = pad(String(d.getMonth() + 1), 2); 2317 | var day = pad(String(d.getDate()), 2); 2318 | var hour = pad(String(d.getHours()), 2); 2319 | var min = pad(String(d.getMinutes()), 2); 2320 | var sec = pad(String(d.getSeconds()), 2); 2321 | return year + month + day + hour + min + sec + 'Z'; 2322 | }; 2323 | 2324 | this.zeroPadding = function(s, len) { 2325 | if (s.length >= len) return s; 2326 | return new Array(len - s.length + 1).join('0') + s; 2327 | }; 2328 | 2329 | // --- PUBLIC METHODS -------------------- 2330 | /** 2331 | * get string value of this string object 2332 | * @name getString 2333 | * @memberOf KJUR.asn1.DERAbstractTime 2334 | * @function 2335 | * @return {String} string value of this time object 2336 | */ 2337 | this.getString = function() { 2338 | return this.s; 2339 | }; 2340 | 2341 | /** 2342 | * set value by a string 2343 | * @name setString 2344 | * @memberOf KJUR.asn1.DERAbstractTime 2345 | * @function 2346 | * @param {String} newS value by a string to set such like "130430235959Z" 2347 | */ 2348 | this.setString = function(newS) { 2349 | this.hTLV = null; 2350 | this.isModified = true; 2351 | this.s = newS; 2352 | this.hV = stohex(this.s); 2353 | }; 2354 | 2355 | /** 2356 | * set value by a Date object 2357 | * @name setByDateValue 2358 | * @memberOf KJUR.asn1.DERAbstractTime 2359 | * @function 2360 | * @param {Integer} year year of date (ex. 2013) 2361 | * @param {Integer} month month of date between 1 and 12 (ex. 12) 2362 | * @param {Integer} day day of month 2363 | * @param {Integer} hour hours of date 2364 | * @param {Integer} min minutes of date 2365 | * @param {Integer} sec seconds of date 2366 | */ 2367 | this.setByDateValue = function(year, month, day, hour, min, sec) { 2368 | var dateObject = new Date(Date.UTC(year, month - 1, day, hour, min, sec, 0)); 2369 | this.setByDate(dateObject); 2370 | }; 2371 | 2372 | this.getFreshValueHex = function() { 2373 | return this.hV; 2374 | }; 2375 | }; 2376 | JSX.extend(KJUR.asn1.DERAbstractTime, KJUR.asn1.ASN1Object); 2377 | // == END DERAbstractTime ================================================== 2378 | 2379 | // == BEGIN DERAbstractStructured ============================================ 2380 | /** 2381 | * base class for ASN.1 DER structured class 2382 | * @name KJUR.asn1.DERAbstractStructured 2383 | * @class base class for ASN.1 DER structured class 2384 | * @property {Array} asn1Array internal array of ASN1Object 2385 | * @extends KJUR.asn1.ASN1Object 2386 | * @description 2387 | * @see KJUR.asn1.ASN1Object - superclass 2388 | */ 2389 | KJUR.asn1.DERAbstractStructured = function(params) { 2390 | KJUR.asn1.DERAbstractString.superclass.constructor.call(this); 2391 | var asn1Array = null; 2392 | 2393 | /** 2394 | * set value by array of ASN1Object 2395 | * @name setByASN1ObjectArray 2396 | * @memberOf KJUR.asn1.DERAbstractStructured 2397 | * @function 2398 | * @param {array} asn1ObjectArray array of ASN1Object to set 2399 | */ 2400 | this.setByASN1ObjectArray = function(asn1ObjectArray) { 2401 | this.hTLV = null; 2402 | this.isModified = true; 2403 | this.asn1Array = asn1ObjectArray; 2404 | }; 2405 | 2406 | /** 2407 | * append an ASN1Object to internal array 2408 | * @name appendASN1Object 2409 | * @memberOf KJUR.asn1.DERAbstractStructured 2410 | * @function 2411 | * @param {ASN1Object} asn1Object to add 2412 | */ 2413 | this.appendASN1Object = function(asn1Object) { 2414 | this.hTLV = null; 2415 | this.isModified = true; 2416 | this.asn1Array.push(asn1Object); 2417 | }; 2418 | 2419 | this.asn1Array = new Array(); 2420 | if (typeof params != "undefined") { 2421 | if (typeof params['array'] != "undefined") { 2422 | this.asn1Array = params['array']; 2423 | } 2424 | } 2425 | }; 2426 | JSX.extend(KJUR.asn1.DERAbstractStructured, KJUR.asn1.ASN1Object); 2427 | 2428 | 2429 | // ******************************************************************** 2430 | // ASN.1 Object Classes 2431 | // ******************************************************************** 2432 | 2433 | // ******************************************************************** 2434 | /** 2435 | * class for ASN.1 DER Boolean 2436 | * @name KJUR.asn1.DERBoolean 2437 | * @class class for ASN.1 DER Boolean 2438 | * @extends KJUR.asn1.ASN1Object 2439 | * @description 2440 | * @see KJUR.asn1.ASN1Object - superclass 2441 | */ 2442 | KJUR.asn1.DERBoolean = function() { 2443 | KJUR.asn1.DERBoolean.superclass.constructor.call(this); 2444 | this.hT = "01"; 2445 | this.hTLV = "0101ff"; 2446 | }; 2447 | JSX.extend(KJUR.asn1.DERBoolean, KJUR.asn1.ASN1Object); 2448 | 2449 | // ******************************************************************** 2450 | /** 2451 | * class for ASN.1 DER Integer 2452 | * @name KJUR.asn1.DERInteger 2453 | * @class class for ASN.1 DER Integer 2454 | * @extends KJUR.asn1.ASN1Object 2455 | * @description 2456 | *
2457 | * As for argument 'params' for constructor, you can specify one of 2458 | * following properties: 2459 | *
    2460 | *
  • int - specify initial ASN.1 value(V) by integer value
  • 2461 | *
  • bigint - specify initial ASN.1 value(V) by BigInteger object
  • 2462 | *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • 2463 | *
2464 | * NOTE: 'params' can be omitted. 2465 | */ 2466 | KJUR.asn1.DERInteger = function(params) { 2467 | KJUR.asn1.DERInteger.superclass.constructor.call(this); 2468 | this.hT = "02"; 2469 | 2470 | /** 2471 | * set value by Tom Wu's BigInteger object 2472 | * @name setByBigInteger 2473 | * @memberOf KJUR.asn1.DERInteger 2474 | * @function 2475 | * @param {BigInteger} bigIntegerValue to set 2476 | */ 2477 | this.setByBigInteger = function(bigIntegerValue) { 2478 | this.hTLV = null; 2479 | this.isModified = true; 2480 | this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue); 2481 | }; 2482 | 2483 | /** 2484 | * set value by integer value 2485 | * @name setByInteger 2486 | * @memberOf KJUR.asn1.DERInteger 2487 | * @function 2488 | * @param {Integer} integer value to set 2489 | */ 2490 | this.setByInteger = function(intValue) { 2491 | var bi = new BigInteger(String(intValue), 10); 2492 | this.setByBigInteger(bi); 2493 | }; 2494 | 2495 | /** 2496 | * set value by integer value 2497 | * @name setValueHex 2498 | * @memberOf KJUR.asn1.DERInteger 2499 | * @function 2500 | * @param {String} hexadecimal string of integer value 2501 | * @description 2502 | *
2503 | * NOTE: Value shall be represented by minimum octet length of 2504 | * two's complement representation. 2505 | */ 2506 | this.setValueHex = function(newHexString) { 2507 | this.hV = newHexString; 2508 | }; 2509 | 2510 | this.getFreshValueHex = function() { 2511 | return this.hV; 2512 | }; 2513 | 2514 | if (typeof params != "undefined") { 2515 | if (typeof params['bigint'] != "undefined") { 2516 | this.setByBigInteger(params['bigint']); 2517 | } else if (typeof params['int'] != "undefined") { 2518 | this.setByInteger(params['int']); 2519 | } else if (typeof params['hex'] != "undefined") { 2520 | this.setValueHex(params['hex']); 2521 | } 2522 | } 2523 | }; 2524 | JSX.extend(KJUR.asn1.DERInteger, KJUR.asn1.ASN1Object); 2525 | 2526 | // ******************************************************************** 2527 | /** 2528 | * class for ASN.1 DER encoded BitString primitive 2529 | * @name KJUR.asn1.DERBitString 2530 | * @class class for ASN.1 DER encoded BitString primitive 2531 | * @extends KJUR.asn1.ASN1Object 2532 | * @description 2533 | *
2534 | * As for argument 'params' for constructor, you can specify one of 2535 | * following properties: 2536 | *
    2537 | *
  • bin - specify binary string (ex. '10111')
  • 2538 | *
  • array - specify array of boolean (ex. [true,false,true,true])
  • 2539 | *
  • hex - specify hexadecimal string of ASN.1 value(V) including unused bits
  • 2540 | *
2541 | * NOTE: 'params' can be omitted. 2542 | */ 2543 | KJUR.asn1.DERBitString = function(params) { 2544 | KJUR.asn1.DERBitString.superclass.constructor.call(this); 2545 | this.hT = "03"; 2546 | 2547 | /** 2548 | * set ASN.1 value(V) by a hexadecimal string including unused bits 2549 | * @name setHexValueIncludingUnusedBits 2550 | * @memberOf KJUR.asn1.DERBitString 2551 | * @function 2552 | * @param {String} newHexStringIncludingUnusedBits 2553 | */ 2554 | this.setHexValueIncludingUnusedBits = function(newHexStringIncludingUnusedBits) { 2555 | this.hTLV = null; 2556 | this.isModified = true; 2557 | this.hV = newHexStringIncludingUnusedBits; 2558 | }; 2559 | 2560 | /** 2561 | * set ASN.1 value(V) by unused bit and hexadecimal string of value 2562 | * @name setUnusedBitsAndHexValue 2563 | * @memberOf KJUR.asn1.DERBitString 2564 | * @function 2565 | * @param {Integer} unusedBits 2566 | * @param {String} hValue 2567 | */ 2568 | this.setUnusedBitsAndHexValue = function(unusedBits, hValue) { 2569 | if (unusedBits < 0 || 7 < unusedBits) { 2570 | throw "unused bits shall be from 0 to 7: u = " + unusedBits; 2571 | } 2572 | var hUnusedBits = "0" + unusedBits; 2573 | this.hTLV = null; 2574 | this.isModified = true; 2575 | this.hV = hUnusedBits + hValue; 2576 | }; 2577 | 2578 | /** 2579 | * set ASN.1 DER BitString by binary string 2580 | * @name setByBinaryString 2581 | * @memberOf KJUR.asn1.DERBitString 2582 | * @function 2583 | * @param {String} binaryString binary value string (i.e. '10111') 2584 | * @description 2585 | * Its unused bits will be calculated automatically by length of 2586 | * 'binaryValue'.
2587 | * NOTE: Trailing zeros '0' will be ignored. 2588 | */ 2589 | this.setByBinaryString = function(binaryString) { 2590 | binaryString = binaryString.replace(/0+$/, ''); 2591 | var unusedBits = 8 - binaryString.length % 8; 2592 | if (unusedBits == 8) unusedBits = 0; 2593 | for (var i = 0; i <= unusedBits; i++) { 2594 | binaryString += '0'; 2595 | } 2596 | var h = ''; 2597 | for (var i = 0; i < binaryString.length - 1; i += 8) { 2598 | var b = binaryString.substr(i, 8); 2599 | var x = parseInt(b, 2).toString(16); 2600 | if (x.length == 1) x = '0' + x; 2601 | h += x; 2602 | } 2603 | this.hTLV = null; 2604 | this.isModified = true; 2605 | this.hV = '0' + unusedBits + h; 2606 | }; 2607 | 2608 | /** 2609 | * set ASN.1 TLV value(V) by an array of boolean 2610 | * @name setByBooleanArray 2611 | * @memberOf KJUR.asn1.DERBitString 2612 | * @function 2613 | * @param {array} booleanArray array of boolean (ex. [true, false, true]) 2614 | * @description 2615 | * NOTE: Trailing falses will be ignored. 2616 | */ 2617 | this.setByBooleanArray = function(booleanArray) { 2618 | var s = ''; 2619 | for (var i = 0; i < booleanArray.length; i++) { 2620 | if (booleanArray[i] == true) { 2621 | s += '1'; 2622 | } else { 2623 | s += '0'; 2624 | } 2625 | } 2626 | this.setByBinaryString(s); 2627 | }; 2628 | 2629 | /** 2630 | * generate an array of false with specified length 2631 | * @name newFalseArray 2632 | * @memberOf KJUR.asn1.DERBitString 2633 | * @function 2634 | * @param {Integer} nLength length of array to generate 2635 | * @return {array} array of boolean faluse 2636 | * @description 2637 | * This static method may be useful to initialize boolean array. 2638 | */ 2639 | this.newFalseArray = function(nLength) { 2640 | var a = new Array(nLength); 2641 | for (var i = 0; i < nLength; i++) { 2642 | a[i] = false; 2643 | } 2644 | return a; 2645 | }; 2646 | 2647 | this.getFreshValueHex = function() { 2648 | return this.hV; 2649 | }; 2650 | 2651 | if (typeof params != "undefined") { 2652 | if (typeof params['hex'] != "undefined") { 2653 | this.setHexValueIncludingUnusedBits(params['hex']); 2654 | } else if (typeof params['bin'] != "undefined") { 2655 | this.setByBinaryString(params['bin']); 2656 | } else if (typeof params['array'] != "undefined") { 2657 | this.setByBooleanArray(params['array']); 2658 | } 2659 | } 2660 | }; 2661 | JSX.extend(KJUR.asn1.DERBitString, KJUR.asn1.ASN1Object); 2662 | 2663 | // ******************************************************************** 2664 | /** 2665 | * class for ASN.1 DER OctetString 2666 | * @name KJUR.asn1.DEROctetString 2667 | * @class class for ASN.1 DER OctetString 2668 | * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) 2669 | * @extends KJUR.asn1.DERAbstractString 2670 | * @description 2671 | * @see KJUR.asn1.DERAbstractString - superclass 2672 | */ 2673 | KJUR.asn1.DEROctetString = function(params) { 2674 | KJUR.asn1.DEROctetString.superclass.constructor.call(this, params); 2675 | this.hT = "04"; 2676 | }; 2677 | JSX.extend(KJUR.asn1.DEROctetString, KJUR.asn1.DERAbstractString); 2678 | 2679 | // ******************************************************************** 2680 | /** 2681 | * class for ASN.1 DER Null 2682 | * @name KJUR.asn1.DERNull 2683 | * @class class for ASN.1 DER Null 2684 | * @extends KJUR.asn1.ASN1Object 2685 | * @description 2686 | * @see KJUR.asn1.ASN1Object - superclass 2687 | */ 2688 | KJUR.asn1.DERNull = function() { 2689 | KJUR.asn1.DERNull.superclass.constructor.call(this); 2690 | this.hT = "05"; 2691 | this.hTLV = "0500"; 2692 | }; 2693 | JSX.extend(KJUR.asn1.DERNull, KJUR.asn1.ASN1Object); 2694 | 2695 | // ******************************************************************** 2696 | /** 2697 | * class for ASN.1 DER ObjectIdentifier 2698 | * @name KJUR.asn1.DERObjectIdentifier 2699 | * @class class for ASN.1 DER ObjectIdentifier 2700 | * @param {Array} params associative array of parameters (ex. {'oid': '2.5.4.5'}) 2701 | * @extends KJUR.asn1.ASN1Object 2702 | * @description 2703 | *
2704 | * As for argument 'params' for constructor, you can specify one of 2705 | * following properties: 2706 | *
    2707 | *
  • oid - specify initial ASN.1 value(V) by a oid string (ex. 2.5.4.13)
  • 2708 | *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • 2709 | *
2710 | * NOTE: 'params' can be omitted. 2711 | */ 2712 | KJUR.asn1.DERObjectIdentifier = function(params) { 2713 | var itox = function(i) { 2714 | var h = i.toString(16); 2715 | if (h.length == 1) h = '0' + h; 2716 | return h; 2717 | }; 2718 | var roidtox = function(roid) { 2719 | var h = ''; 2720 | var bi = new BigInteger(roid, 10); 2721 | var b = bi.toString(2); 2722 | var padLen = 7 - b.length % 7; 2723 | if (padLen == 7) padLen = 0; 2724 | var bPad = ''; 2725 | for (var i = 0; i < padLen; i++) bPad += '0'; 2726 | b = bPad + b; 2727 | for (var i = 0; i < b.length - 1; i += 7) { 2728 | var b8 = b.substr(i, 7); 2729 | if (i != b.length - 7) b8 = '1' + b8; 2730 | h += itox(parseInt(b8, 2)); 2731 | } 2732 | return h; 2733 | } 2734 | 2735 | KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this); 2736 | this.hT = "06"; 2737 | 2738 | /** 2739 | * set value by a hexadecimal string 2740 | * @name setValueHex 2741 | * @memberOf KJUR.asn1.DERObjectIdentifier 2742 | * @function 2743 | * @param {String} newHexString hexadecimal value of OID bytes 2744 | */ 2745 | this.setValueHex = function(newHexString) { 2746 | this.hTLV = null; 2747 | this.isModified = true; 2748 | this.s = null; 2749 | this.hV = newHexString; 2750 | }; 2751 | 2752 | /** 2753 | * set value by a OID string 2754 | * @name setValueOidString 2755 | * @memberOf KJUR.asn1.DERObjectIdentifier 2756 | * @function 2757 | * @param {String} oidString OID string (ex. 2.5.4.13) 2758 | */ 2759 | this.setValueOidString = function(oidString) { 2760 | if (! oidString.match(/^[0-9.]+$/)) { 2761 | throw "malformed oid string: " + oidString; 2762 | } 2763 | var h = ''; 2764 | var a = oidString.split('.'); 2765 | var i0 = parseInt(a[0]) * 40 + parseInt(a[1]); 2766 | h += itox(i0); 2767 | a.splice(0, 2); 2768 | for (var i = 0; i < a.length; i++) { 2769 | h += roidtox(a[i]); 2770 | } 2771 | this.hTLV = null; 2772 | this.isModified = true; 2773 | this.s = null; 2774 | this.hV = h; 2775 | }; 2776 | 2777 | /** 2778 | * set value by a OID name 2779 | * @name setValueName 2780 | * @memberOf KJUR.asn1.DERObjectIdentifier 2781 | * @function 2782 | * @param {String} oidName OID name (ex. 'serverAuth') 2783 | * @since 1.0.1 2784 | * @description 2785 | * OID name shall be defined in 'KJUR.asn1.x509.OID.name2oidList'. 2786 | * Otherwise raise error. 2787 | */ 2788 | this.setValueName = function(oidName) { 2789 | if (typeof KJUR.asn1.x509.OID.name2oidList[oidName] != "undefined") { 2790 | var oid = KJUR.asn1.x509.OID.name2oidList[oidName]; 2791 | this.setValueOidString(oid); 2792 | } else { 2793 | throw "DERObjectIdentifier oidName undefined: " + oidName; 2794 | } 2795 | }; 2796 | 2797 | this.getFreshValueHex = function() { 2798 | return this.hV; 2799 | }; 2800 | 2801 | if (typeof params != "undefined") { 2802 | if (typeof params['oid'] != "undefined") { 2803 | this.setValueOidString(params['oid']); 2804 | } else if (typeof params['hex'] != "undefined") { 2805 | this.setValueHex(params['hex']); 2806 | } else if (typeof params['name'] != "undefined") { 2807 | this.setValueName(params['name']); 2808 | } 2809 | } 2810 | }; 2811 | JSX.extend(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object); 2812 | 2813 | // ******************************************************************** 2814 | /** 2815 | * class for ASN.1 DER UTF8String 2816 | * @name KJUR.asn1.DERUTF8String 2817 | * @class class for ASN.1 DER UTF8String 2818 | * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) 2819 | * @extends KJUR.asn1.DERAbstractString 2820 | * @description 2821 | * @see KJUR.asn1.DERAbstractString - superclass 2822 | */ 2823 | KJUR.asn1.DERUTF8String = function(params) { 2824 | KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params); 2825 | this.hT = "0c"; 2826 | }; 2827 | JSX.extend(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString); 2828 | 2829 | // ******************************************************************** 2830 | /** 2831 | * class for ASN.1 DER NumericString 2832 | * @name KJUR.asn1.DERNumericString 2833 | * @class class for ASN.1 DER NumericString 2834 | * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) 2835 | * @extends KJUR.asn1.DERAbstractString 2836 | * @description 2837 | * @see KJUR.asn1.DERAbstractString - superclass 2838 | */ 2839 | KJUR.asn1.DERNumericString = function(params) { 2840 | KJUR.asn1.DERNumericString.superclass.constructor.call(this, params); 2841 | this.hT = "12"; 2842 | }; 2843 | JSX.extend(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString); 2844 | 2845 | // ******************************************************************** 2846 | /** 2847 | * class for ASN.1 DER PrintableString 2848 | * @name KJUR.asn1.DERPrintableString 2849 | * @class class for ASN.1 DER PrintableString 2850 | * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) 2851 | * @extends KJUR.asn1.DERAbstractString 2852 | * @description 2853 | * @see KJUR.asn1.DERAbstractString - superclass 2854 | */ 2855 | KJUR.asn1.DERPrintableString = function(params) { 2856 | KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params); 2857 | this.hT = "13"; 2858 | }; 2859 | JSX.extend(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString); 2860 | 2861 | // ******************************************************************** 2862 | /** 2863 | * class for ASN.1 DER TeletexString 2864 | * @name KJUR.asn1.DERTeletexString 2865 | * @class class for ASN.1 DER TeletexString 2866 | * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) 2867 | * @extends KJUR.asn1.DERAbstractString 2868 | * @description 2869 | * @see KJUR.asn1.DERAbstractString - superclass 2870 | */ 2871 | KJUR.asn1.DERTeletexString = function(params) { 2872 | KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params); 2873 | this.hT = "14"; 2874 | }; 2875 | JSX.extend(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString); 2876 | 2877 | // ******************************************************************** 2878 | /** 2879 | * class for ASN.1 DER IA5String 2880 | * @name KJUR.asn1.DERIA5String 2881 | * @class class for ASN.1 DER IA5String 2882 | * @param {Array} params associative array of parameters (ex. {'str': 'aaa'}) 2883 | * @extends KJUR.asn1.DERAbstractString 2884 | * @description 2885 | * @see KJUR.asn1.DERAbstractString - superclass 2886 | */ 2887 | KJUR.asn1.DERIA5String = function(params) { 2888 | KJUR.asn1.DERIA5String.superclass.constructor.call(this, params); 2889 | this.hT = "16"; 2890 | }; 2891 | JSX.extend(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString); 2892 | 2893 | // ******************************************************************** 2894 | /** 2895 | * class for ASN.1 DER UTCTime 2896 | * @name KJUR.asn1.DERUTCTime 2897 | * @class class for ASN.1 DER UTCTime 2898 | * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'}) 2899 | * @extends KJUR.asn1.DERAbstractTime 2900 | * @description 2901 | *
2902 | * As for argument 'params' for constructor, you can specify one of 2903 | * following properties: 2904 | *
    2905 | *
  • str - specify initial ASN.1 value(V) by a string (ex.'130430235959Z')
  • 2906 | *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • 2907 | *
  • date - specify Date object.
  • 2908 | *
2909 | * NOTE: 'params' can be omitted. 2910 | *

EXAMPLES

2911 | * @example 2912 | * var d1 = new KJUR.asn1.DERUTCTime(); 2913 | * d1.setString('130430125959Z'); 2914 | * 2915 | * var d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'}); 2916 | * 2917 | * var d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))}); 2918 | */ 2919 | KJUR.asn1.DERUTCTime = function(params) { 2920 | KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params); 2921 | this.hT = "17"; 2922 | 2923 | /** 2924 | * set value by a Date object 2925 | * @name setByDate 2926 | * @memberOf KJUR.asn1.DERUTCTime 2927 | * @function 2928 | * @param {Date} dateObject Date object to set ASN.1 value(V) 2929 | */ 2930 | this.setByDate = function(dateObject) { 2931 | this.hTLV = null; 2932 | this.isModified = true; 2933 | this.date = dateObject; 2934 | this.s = this.formatDate(this.date, 'utc'); 2935 | this.hV = stohex(this.s); 2936 | }; 2937 | 2938 | if (typeof params != "undefined") { 2939 | if (typeof params['str'] != "undefined") { 2940 | this.setString(params['str']); 2941 | } else if (typeof params['hex'] != "undefined") { 2942 | this.setStringHex(params['hex']); 2943 | } else if (typeof params['date'] != "undefined") { 2944 | this.setByDate(params['date']); 2945 | } 2946 | } 2947 | }; 2948 | JSX.extend(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime); 2949 | 2950 | // ******************************************************************** 2951 | /** 2952 | * class for ASN.1 DER GeneralizedTime 2953 | * @name KJUR.asn1.DERGeneralizedTime 2954 | * @class class for ASN.1 DER GeneralizedTime 2955 | * @param {Array} params associative array of parameters (ex. {'str': '20130430235959Z'}) 2956 | * @extends KJUR.asn1.DERAbstractTime 2957 | * @description 2958 | *
2959 | * As for argument 'params' for constructor, you can specify one of 2960 | * following properties: 2961 | *
    2962 | *
  • str - specify initial ASN.1 value(V) by a string (ex.'20130430235959Z')
  • 2963 | *
  • hex - specify initial ASN.1 value(V) by a hexadecimal string
  • 2964 | *
  • date - specify Date object.
  • 2965 | *
2966 | * NOTE: 'params' can be omitted. 2967 | */ 2968 | KJUR.asn1.DERGeneralizedTime = function(params) { 2969 | KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params); 2970 | this.hT = "18"; 2971 | 2972 | /** 2973 | * set value by a Date object 2974 | * @name setByDate 2975 | * @memberOf KJUR.asn1.DERGeneralizedTime 2976 | * @function 2977 | * @param {Date} dateObject Date object to set ASN.1 value(V) 2978 | * @example 2979 | * When you specify UTC time, use 'Date.UTC' method like this:
2980 | * var o = new DERUTCTime(); 2981 | * var date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59 2982 | * o.setByDate(date); 2983 | */ 2984 | this.setByDate = function(dateObject) { 2985 | this.hTLV = null; 2986 | this.isModified = true; 2987 | this.date = dateObject; 2988 | this.s = this.formatDate(this.date, 'gen'); 2989 | this.hV = stohex(this.s); 2990 | }; 2991 | 2992 | if (typeof params != "undefined") { 2993 | if (typeof params['str'] != "undefined") { 2994 | this.setString(params['str']); 2995 | } else if (typeof params['hex'] != "undefined") { 2996 | this.setStringHex(params['hex']); 2997 | } else if (typeof params['date'] != "undefined") { 2998 | this.setByDate(params['date']); 2999 | } 3000 | } 3001 | }; 3002 | JSX.extend(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime); 3003 | 3004 | // ******************************************************************** 3005 | /** 3006 | * class for ASN.1 DER Sequence 3007 | * @name KJUR.asn1.DERSequence 3008 | * @class class for ASN.1 DER Sequence 3009 | * @extends KJUR.asn1.DERAbstractStructured 3010 | * @description 3011 | *
3012 | * As for argument 'params' for constructor, you can specify one of 3013 | * following properties: 3014 | *
    3015 | *
  • array - specify array of ASN1Object to set elements of content
  • 3016 | *
3017 | * NOTE: 'params' can be omitted. 3018 | */ 3019 | KJUR.asn1.DERSequence = function(params) { 3020 | KJUR.asn1.DERSequence.superclass.constructor.call(this, params); 3021 | this.hT = "30"; 3022 | this.getFreshValueHex = function() { 3023 | var h = ''; 3024 | for (var i = 0; i < this.asn1Array.length; i++) { 3025 | var asn1Obj = this.asn1Array[i]; 3026 | h += asn1Obj.getEncodedHex(); 3027 | } 3028 | this.hV = h; 3029 | return this.hV; 3030 | }; 3031 | }; 3032 | JSX.extend(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured); 3033 | 3034 | // ******************************************************************** 3035 | /** 3036 | * class for ASN.1 DER Set 3037 | * @name KJUR.asn1.DERSet 3038 | * @class class for ASN.1 DER Set 3039 | * @extends KJUR.asn1.DERAbstractStructured 3040 | * @description 3041 | *
3042 | * As for argument 'params' for constructor, you can specify one of 3043 | * following properties: 3044 | *
    3045 | *
  • array - specify array of ASN1Object to set elements of content
  • 3046 | *
3047 | * NOTE: 'params' can be omitted. 3048 | */ 3049 | KJUR.asn1.DERSet = function(params) { 3050 | KJUR.asn1.DERSet.superclass.constructor.call(this, params); 3051 | this.hT = "31"; 3052 | this.getFreshValueHex = function() { 3053 | var a = new Array(); 3054 | for (var i = 0; i < this.asn1Array.length; i++) { 3055 | var asn1Obj = this.asn1Array[i]; 3056 | a.push(asn1Obj.getEncodedHex()); 3057 | } 3058 | a.sort(); 3059 | this.hV = a.join(''); 3060 | return this.hV; 3061 | }; 3062 | }; 3063 | JSX.extend(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured); 3064 | 3065 | // ******************************************************************** 3066 | /** 3067 | * class for ASN.1 DER TaggedObject 3068 | * @name KJUR.asn1.DERTaggedObject 3069 | * @class class for ASN.1 DER TaggedObject 3070 | * @extends KJUR.asn1.ASN1Object 3071 | * @description 3072 | *
3073 | * Parameter 'tagNoNex' is ASN.1 tag(T) value for this object. 3074 | * For example, if you find '[1]' tag in a ASN.1 dump, 3075 | * 'tagNoHex' will be 'a1'. 3076 | *
3077 | * As for optional argument 'params' for constructor, you can specify *ANY* of 3078 | * following properties: 3079 | *
    3080 | *
  • explicit - specify true if this is explicit tag otherwise false 3081 | * (default is 'true').
  • 3082 | *
  • tag - specify tag (default is 'a0' which means [0])
  • 3083 | *
  • obj - specify ASN1Object which is tagged
  • 3084 | *
3085 | * @example 3086 | * d1 = new KJUR.asn1.DERUTF8String({'str':'a'}); 3087 | * d2 = new KJUR.asn1.DERTaggedObject({'obj': d1}); 3088 | * hex = d2.getEncodedHex(); 3089 | */ 3090 | KJUR.asn1.DERTaggedObject = function(params) { 3091 | KJUR.asn1.DERTaggedObject.superclass.constructor.call(this); 3092 | this.hT = "a0"; 3093 | this.hV = ''; 3094 | this.isExplicit = true; 3095 | this.asn1Object = null; 3096 | 3097 | /** 3098 | * set value by an ASN1Object 3099 | * @name setString 3100 | * @memberOf KJUR.asn1.DERTaggedObject 3101 | * @function 3102 | * @param {Boolean} isExplicitFlag flag for explicit/implicit tag 3103 | * @param {Integer} tagNoHex hexadecimal string of ASN.1 tag 3104 | * @param {ASN1Object} asn1Object ASN.1 to encapsulate 3105 | */ 3106 | this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) { 3107 | this.hT = tagNoHex; 3108 | this.isExplicit = isExplicitFlag; 3109 | this.asn1Object = asn1Object; 3110 | if (this.isExplicit) { 3111 | this.hV = this.asn1Object.getEncodedHex(); 3112 | this.hTLV = null; 3113 | this.isModified = true; 3114 | } else { 3115 | this.hV = null; 3116 | this.hTLV = asn1Object.getEncodedHex(); 3117 | this.hTLV = this.hTLV.replace(/^../, tagNoHex); 3118 | this.isModified = false; 3119 | } 3120 | }; 3121 | 3122 | this.getFreshValueHex = function() { 3123 | return this.hV; 3124 | }; 3125 | 3126 | if (typeof params != "undefined") { 3127 | if (typeof params['tag'] != "undefined") { 3128 | this.hT = params['tag']; 3129 | } 3130 | if (typeof params['explicit'] != "undefined") { 3131 | this.isExplicit = params['explicit']; 3132 | } 3133 | if (typeof params['obj'] != "undefined") { 3134 | this.asn1Object = params['obj']; 3135 | this.setASN1Object(this.isExplicit, this.hT, this.asn1Object); 3136 | } 3137 | } 3138 | }; 3139 | JSX.extend(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object);// Hex JavaScript decoder 3140 | // Copyright (c) 2008-2013 Lapo Luchini 3141 | 3142 | // Permission to use, copy, modify, and/or distribute this software for any 3143 | // purpose with or without fee is hereby granted, provided that the above 3144 | // copyright notice and this permission notice appear in all copies. 3145 | // 3146 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 3147 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 3148 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 3149 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 3150 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 3151 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 3152 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 3153 | 3154 | /*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ 3155 | (function (undefined) { 3156 | "use strict"; 3157 | 3158 | var Hex = {}, 3159 | decoder; 3160 | 3161 | Hex.decode = function(a) { 3162 | var i; 3163 | if (decoder === undefined) { 3164 | var hex = "0123456789ABCDEF", 3165 | ignore = " \f\n\r\t\u00A0\u2028\u2029"; 3166 | decoder = []; 3167 | for (i = 0; i < 16; ++i) 3168 | decoder[hex.charAt(i)] = i; 3169 | hex = hex.toLowerCase(); 3170 | for (i = 10; i < 16; ++i) 3171 | decoder[hex.charAt(i)] = i; 3172 | for (i = 0; i < ignore.length; ++i) 3173 | decoder[ignore.charAt(i)] = -1; 3174 | } 3175 | var out = [], 3176 | bits = 0, 3177 | char_count = 0; 3178 | for (i = 0; i < a.length; ++i) { 3179 | var c = a.charAt(i); 3180 | if (c == '=') 3181 | break; 3182 | c = decoder[c]; 3183 | if (c == -1) 3184 | continue; 3185 | if (c === undefined) 3186 | throw 'Illegal character at offset ' + i; 3187 | bits |= c; 3188 | if (++char_count >= 2) { 3189 | out[out.length] = bits; 3190 | bits = 0; 3191 | char_count = 0; 3192 | } else { 3193 | bits <<= 4; 3194 | } 3195 | } 3196 | if (char_count) 3197 | throw "Hex encoding incomplete: 4 bits missing"; 3198 | return out; 3199 | }; 3200 | 3201 | // export globals 3202 | window.Hex = Hex; 3203 | })();// Base64 JavaScript decoder 3204 | // Copyright (c) 2008-2013 Lapo Luchini 3205 | 3206 | // Permission to use, copy, modify, and/or distribute this software for any 3207 | // purpose with or without fee is hereby granted, provided that the above 3208 | // copyright notice and this permission notice appear in all copies. 3209 | // 3210 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 3211 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 3212 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 3213 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 3214 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 3215 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 3216 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 3217 | 3218 | /*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ 3219 | (function (undefined) { 3220 | "use strict"; 3221 | 3222 | var Base64 = {}, 3223 | decoder; 3224 | 3225 | Base64.decode = function (a) { 3226 | var i; 3227 | if (decoder === undefined) { 3228 | var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 3229 | ignore = "= \f\n\r\t\u00A0\u2028\u2029"; 3230 | decoder = []; 3231 | for (i = 0; i < 64; ++i) 3232 | decoder[b64.charAt(i)] = i; 3233 | for (i = 0; i < ignore.length; ++i) 3234 | decoder[ignore.charAt(i)] = -1; 3235 | } 3236 | var out = []; 3237 | var bits = 0, char_count = 0; 3238 | for (i = 0; i < a.length; ++i) { 3239 | var c = a.charAt(i); 3240 | if (c == '=') 3241 | break; 3242 | c = decoder[c]; 3243 | if (c == -1) 3244 | continue; 3245 | if (c === undefined) 3246 | throw 'Illegal character at offset ' + i; 3247 | bits |= c; 3248 | if (++char_count >= 4) { 3249 | out[out.length] = (bits >> 16); 3250 | out[out.length] = (bits >> 8) & 0xFF; 3251 | out[out.length] = bits & 0xFF; 3252 | bits = 0; 3253 | char_count = 0; 3254 | } else { 3255 | bits <<= 6; 3256 | } 3257 | } 3258 | switch (char_count) { 3259 | case 1: 3260 | throw "Base64 encoding incomplete: at least 2 bits missing"; 3261 | case 2: 3262 | out[out.length] = (bits >> 10); 3263 | break; 3264 | case 3: 3265 | out[out.length] = (bits >> 16); 3266 | out[out.length] = (bits >> 8) & 0xFF; 3267 | break; 3268 | } 3269 | return out; 3270 | }; 3271 | 3272 | Base64.re = /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/; 3273 | Base64.unarmor = function (a) { 3274 | var m = Base64.re.exec(a); 3275 | if (m) { 3276 | if (m[1]) 3277 | a = m[1]; 3278 | else if (m[2]) 3279 | a = m[2]; 3280 | else 3281 | throw "RegExp out of sync"; 3282 | } 3283 | return Base64.decode(a); 3284 | }; 3285 | 3286 | // export globals 3287 | window.Base64 = Base64; 3288 | })();// ASN.1 JavaScript decoder 3289 | // Copyright (c) 2008-2013 Lapo Luchini 3290 | 3291 | // Permission to use, copy, modify, and/or distribute this software for any 3292 | // purpose with or without fee is hereby granted, provided that the above 3293 | // copyright notice and this permission notice appear in all copies. 3294 | // 3295 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 3296 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 3297 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 3298 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 3299 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 3300 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 3301 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 3302 | 3303 | /*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ 3304 | /*global oids */ 3305 | (function (undefined) { 3306 | "use strict"; 3307 | 3308 | var hardLimit = 100, 3309 | ellipsis = "\u2026", 3310 | DOM = { 3311 | tag: function (tagName, className) { 3312 | var t = document.createElement(tagName); 3313 | t.className = className; 3314 | return t; 3315 | }, 3316 | text: function (str) { 3317 | return document.createTextNode(str); 3318 | } 3319 | }; 3320 | 3321 | function Stream(enc, pos) { 3322 | if (enc instanceof Stream) { 3323 | this.enc = enc.enc; 3324 | this.pos = enc.pos; 3325 | } else { 3326 | this.enc = enc; 3327 | this.pos = pos; 3328 | } 3329 | } 3330 | Stream.prototype.get = function (pos) { 3331 | if (pos === undefined) 3332 | pos = this.pos++; 3333 | if (pos >= this.enc.length) 3334 | throw 'Requesting byte offset ' + pos + ' on a stream of length ' + this.enc.length; 3335 | return this.enc[pos]; 3336 | }; 3337 | Stream.prototype.hexDigits = "0123456789ABCDEF"; 3338 | Stream.prototype.hexByte = function (b) { 3339 | return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF); 3340 | }; 3341 | Stream.prototype.hexDump = function (start, end, raw) { 3342 | var s = ""; 3343 | for (var i = start; i < end; ++i) { 3344 | s += this.hexByte(this.get(i)); 3345 | if (raw !== true) 3346 | switch (i & 0xF) { 3347 | case 0x7: s += " "; break; 3348 | case 0xF: s += "\n"; break; 3349 | default: s += " "; 3350 | } 3351 | } 3352 | return s; 3353 | }; 3354 | Stream.prototype.parseStringISO = function (start, end) { 3355 | var s = ""; 3356 | for (var i = start; i < end; ++i) 3357 | s += String.fromCharCode(this.get(i)); 3358 | return s; 3359 | }; 3360 | Stream.prototype.parseStringUTF = function (start, end) { 3361 | var s = ""; 3362 | for (var i = start; i < end; ) { 3363 | var c = this.get(i++); 3364 | if (c < 128) 3365 | s += String.fromCharCode(c); 3366 | else if ((c > 191) && (c < 224)) 3367 | s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F)); 3368 | else 3369 | s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F)); 3370 | } 3371 | return s; 3372 | }; 3373 | Stream.prototype.parseStringBMP = function (start, end) { 3374 | var str = "" 3375 | for (var i = start; i < end; i += 2) { 3376 | var high_byte = this.get(i); 3377 | var low_byte = this.get(i + 1); 3378 | str += String.fromCharCode( (high_byte << 8) + low_byte ); 3379 | } 3380 | 3381 | return str; 3382 | }; 3383 | 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)?)?$/; 3384 | Stream.prototype.parseTime = function (start, end) { 3385 | var s = this.parseStringISO(start, end), 3386 | m = this.reTime.exec(s); 3387 | if (!m) 3388 | return "Unrecognized time: " + s; 3389 | s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4]; 3390 | if (m[5]) { 3391 | s += ":" + m[5]; 3392 | if (m[6]) { 3393 | s += ":" + m[6]; 3394 | if (m[7]) 3395 | s += "." + m[7]; 3396 | } 3397 | } 3398 | if (m[8]) { 3399 | s += " UTC"; 3400 | if (m[8] != 'Z') { 3401 | s += m[8]; 3402 | if (m[9]) 3403 | s += ":" + m[9]; 3404 | } 3405 | } 3406 | return s; 3407 | }; 3408 | Stream.prototype.parseInteger = function (start, end) { 3409 | //TODO support negative numbers 3410 | var len = end - start; 3411 | if (len > 4) { 3412 | len <<= 3; 3413 | var s = this.get(start); 3414 | if (s === 0) 3415 | len -= 8; 3416 | else 3417 | while (s < 128) { 3418 | s <<= 1; 3419 | --len; 3420 | } 3421 | return "(" + len + " bit)"; 3422 | } 3423 | var n = 0; 3424 | for (var i = start; i < end; ++i) 3425 | n = (n << 8) | this.get(i); 3426 | return n; 3427 | }; 3428 | Stream.prototype.parseBitString = function (start, end) { 3429 | var unusedBit = this.get(start), 3430 | lenBit = ((end - start - 1) << 3) - unusedBit, 3431 | s = "(" + lenBit + " bit)"; 3432 | if (lenBit <= 20) { 3433 | var skip = unusedBit; 3434 | s += " "; 3435 | for (var i = end - 1; i > start; --i) { 3436 | var b = this.get(i); 3437 | for (var j = skip; j < 8; ++j) 3438 | s += (b >> j) & 1 ? "1" : "0"; 3439 | skip = 0; 3440 | } 3441 | } 3442 | return s; 3443 | }; 3444 | Stream.prototype.parseOctetString = function (start, end) { 3445 | var len = end - start, 3446 | s = "(" + len + " byte) "; 3447 | if (len > hardLimit) 3448 | end = start + hardLimit; 3449 | for (var i = start; i < end; ++i) 3450 | s += this.hexByte(this.get(i)); //TODO: also try Latin1? 3451 | if (len > hardLimit) 3452 | s += ellipsis; 3453 | return s; 3454 | }; 3455 | Stream.prototype.parseOID = function (start, end) { 3456 | var s = '', 3457 | n = 0, 3458 | bits = 0; 3459 | for (var i = start; i < end; ++i) { 3460 | var v = this.get(i); 3461 | n = (n << 7) | (v & 0x7F); 3462 | bits += 7; 3463 | if (!(v & 0x80)) { // finished 3464 | if (s === '') { 3465 | var m = n < 80 ? n < 40 ? 0 : 1 : 2; 3466 | s = m + "." + (n - m * 40); 3467 | } else 3468 | s += "." + ((bits >= 31) ? "bigint" : n); 3469 | n = bits = 0; 3470 | } 3471 | } 3472 | return s; 3473 | }; 3474 | 3475 | function ASN1(stream, header, length, tag, sub) { 3476 | this.stream = stream; 3477 | this.header = header; 3478 | this.length = length; 3479 | this.tag = tag; 3480 | this.sub = sub; 3481 | } 3482 | ASN1.prototype.typeName = function () { 3483 | if (this.tag === undefined) 3484 | return "unknown"; 3485 | var tagClass = this.tag >> 6, 3486 | tagConstructed = (this.tag >> 5) & 1, 3487 | tagNumber = this.tag & 0x1F; 3488 | switch (tagClass) { 3489 | case 0: // universal 3490 | switch (tagNumber) { 3491 | case 0x00: return "EOC"; 3492 | case 0x01: return "BOOLEAN"; 3493 | case 0x02: return "INTEGER"; 3494 | case 0x03: return "BIT_STRING"; 3495 | case 0x04: return "OCTET_STRING"; 3496 | case 0x05: return "NULL"; 3497 | case 0x06: return "OBJECT_IDENTIFIER"; 3498 | case 0x07: return "ObjectDescriptor"; 3499 | case 0x08: return "EXTERNAL"; 3500 | case 0x09: return "REAL"; 3501 | case 0x0A: return "ENUMERATED"; 3502 | case 0x0B: return "EMBEDDED_PDV"; 3503 | case 0x0C: return "UTF8String"; 3504 | case 0x10: return "SEQUENCE"; 3505 | case 0x11: return "SET"; 3506 | case 0x12: return "NumericString"; 3507 | case 0x13: return "PrintableString"; // ASCII subset 3508 | case 0x14: return "TeletexString"; // aka T61String 3509 | case 0x15: return "VideotexString"; 3510 | case 0x16: return "IA5String"; // ASCII 3511 | case 0x17: return "UTCTime"; 3512 | case 0x18: return "GeneralizedTime"; 3513 | case 0x19: return "GraphicString"; 3514 | case 0x1A: return "VisibleString"; // ASCII subset 3515 | case 0x1B: return "GeneralString"; 3516 | case 0x1C: return "UniversalString"; 3517 | case 0x1E: return "BMPString"; 3518 | default: return "Universal_" + tagNumber.toString(16); 3519 | } 3520 | case 1: return "Application_" + tagNumber.toString(16); 3521 | case 2: return "[" + tagNumber + "]"; // Context 3522 | case 3: return "Private_" + tagNumber.toString(16); 3523 | } 3524 | }; 3525 | ASN1.prototype.reSeemsASCII = /^[ -~]+$/; 3526 | ASN1.prototype.content = function () { 3527 | if (this.tag === undefined) 3528 | return null; 3529 | var tagClass = this.tag >> 6, 3530 | tagNumber = this.tag & 0x1F, 3531 | content = this.posContent(), 3532 | len = Math.abs(this.length); 3533 | if (tagClass !== 0) { // universal 3534 | if (this.sub !== null) 3535 | return "(" + this.sub.length + " elem)"; 3536 | //TODO: TRY TO PARSE ASCII STRING 3537 | var s = this.stream.parseStringISO(content, content + Math.min(len, hardLimit)); 3538 | if (this.reSeemsASCII.test(s)) 3539 | return s.substring(0, 2 * hardLimit) + ((s.length > 2 * hardLimit) ? ellipsis : ""); 3540 | else 3541 | return this.stream.parseOctetString(content, content + len); 3542 | } 3543 | switch (tagNumber) { 3544 | case 0x01: // BOOLEAN 3545 | return (this.stream.get(content) === 0) ? "false" : "true"; 3546 | case 0x02: // INTEGER 3547 | return this.stream.parseInteger(content, content + len); 3548 | case 0x03: // BIT_STRING 3549 | return this.sub ? "(" + this.sub.length + " elem)" : 3550 | this.stream.parseBitString(content, content + len); 3551 | case 0x04: // OCTET_STRING 3552 | return this.sub ? "(" + this.sub.length + " elem)" : 3553 | this.stream.parseOctetString(content, content + len); 3554 | //case 0x05: // NULL 3555 | case 0x06: // OBJECT_IDENTIFIER 3556 | return this.stream.parseOID(content, content + len); 3557 | //case 0x07: // ObjectDescriptor 3558 | //case 0x08: // EXTERNAL 3559 | //case 0x09: // REAL 3560 | //case 0x0A: // ENUMERATED 3561 | //case 0x0B: // EMBEDDED_PDV 3562 | case 0x10: // SEQUENCE 3563 | case 0x11: // SET 3564 | return "(" + this.sub.length + " elem)"; 3565 | case 0x0C: // UTF8String 3566 | return this.stream.parseStringUTF(content, content + len); 3567 | case 0x12: // NumericString 3568 | case 0x13: // PrintableString 3569 | case 0x14: // TeletexString 3570 | case 0x15: // VideotexString 3571 | case 0x16: // IA5String 3572 | //case 0x19: // GraphicString 3573 | case 0x1A: // VisibleString 3574 | //case 0x1B: // GeneralString 3575 | //case 0x1C: // UniversalString 3576 | return this.stream.parseStringISO(content, content + len); 3577 | case 0x1E: // BMPString 3578 | return this.stream.parseStringBMP(content, content + len); 3579 | case 0x17: // UTCTime 3580 | case 0x18: // GeneralizedTime 3581 | return this.stream.parseTime(content, content + len); 3582 | } 3583 | return null; 3584 | }; 3585 | ASN1.prototype.toString = function () { 3586 | return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? 'null' : this.sub.length) + "]"; 3587 | }; 3588 | ASN1.prototype.print = function (indent) { 3589 | if (indent === undefined) indent = ''; 3590 | document.writeln(indent + this); 3591 | if (this.sub !== null) { 3592 | indent += ' '; 3593 | for (var i = 0, max = this.sub.length; i < max; ++i) 3594 | this.sub[i].print(indent); 3595 | } 3596 | }; 3597 | ASN1.prototype.toPrettyString = function (indent) { 3598 | if (indent === undefined) indent = ''; 3599 | var s = indent + this.typeName() + " @" + this.stream.pos; 3600 | if (this.length >= 0) 3601 | s += "+"; 3602 | s += this.length; 3603 | if (this.tag & 0x20) 3604 | s += " (constructed)"; 3605 | else if (((this.tag == 0x03) || (this.tag == 0x04)) && (this.sub !== null)) 3606 | s += " (encapsulates)"; 3607 | s += "\n"; 3608 | if (this.sub !== null) { 3609 | indent += ' '; 3610 | for (var i = 0, max = this.sub.length; i < max; ++i) 3611 | s += this.sub[i].toPrettyString(indent); 3612 | } 3613 | return s; 3614 | }; 3615 | ASN1.prototype.toDOM = function () { 3616 | var node = DOM.tag("div", "node"); 3617 | node.asn1 = this; 3618 | var head = DOM.tag("div", "head"); 3619 | var s = this.typeName().replace(/_/g, " "); 3620 | head.innerHTML = s; 3621 | var content = this.content(); 3622 | if (content !== null) { 3623 | content = String(content).replace(/"; 3633 | s += "Length: " + this.header + "+"; 3634 | if (this.length >= 0) 3635 | s += this.length; 3636 | else 3637 | s += (-this.length) + " (undefined)"; 3638 | if (this.tag & 0x20) 3639 | s += "
(constructed)"; 3640 | else if (((this.tag == 0x03) || (this.tag == 0x04)) && (this.sub !== null)) 3641 | s += "
(encapsulates)"; 3642 | //TODO if (this.tag == 0x03) s += "Unused bits: " 3643 | if (content !== null) { 3644 | s += "
Value:
" + content + ""; 3645 | if ((typeof oids === 'object') && (this.tag == 0x06)) { 3646 | var oid = oids[content]; 3647 | if (oid) { 3648 | if (oid.d) s += "
" + oid.d; 3649 | if (oid.c) s += "
" + oid.c; 3650 | if (oid.w) s += "
(warning!)"; 3651 | } 3652 | } 3653 | } 3654 | value.innerHTML = s; 3655 | node.appendChild(value); 3656 | var sub = DOM.tag("div", "sub"); 3657 | if (this.sub !== null) { 3658 | for (var i = 0, max = this.sub.length; i < max; ++i) 3659 | sub.appendChild(this.sub[i].toDOM()); 3660 | } 3661 | node.appendChild(sub); 3662 | head.onclick = function () { 3663 | node.className = (node.className == "node collapsed") ? "node" : "node collapsed"; 3664 | }; 3665 | return node; 3666 | }; 3667 | ASN1.prototype.posStart = function () { 3668 | return this.stream.pos; 3669 | }; 3670 | ASN1.prototype.posContent = function () { 3671 | return this.stream.pos + this.header; 3672 | }; 3673 | ASN1.prototype.posEnd = function () { 3674 | return this.stream.pos + this.header + Math.abs(this.length); 3675 | }; 3676 | ASN1.prototype.fakeHover = function (current) { 3677 | this.node.className += " hover"; 3678 | if (current) 3679 | this.head.className += " hover"; 3680 | }; 3681 | ASN1.prototype.fakeOut = function (current) { 3682 | var re = / ?hover/; 3683 | this.node.className = this.node.className.replace(re, ""); 3684 | if (current) 3685 | this.head.className = this.head.className.replace(re, ""); 3686 | }; 3687 | ASN1.prototype.toHexDOM_sub = function (node, className, stream, start, end) { 3688 | if (start >= end) 3689 | return; 3690 | var sub = DOM.tag("span", className); 3691 | sub.appendChild(DOM.text( 3692 | stream.hexDump(start, end))); 3693 | node.appendChild(sub); 3694 | }; 3695 | ASN1.prototype.toHexDOM = function (root) { 3696 | var node = DOM.tag("span", "hex"); 3697 | if (root === undefined) root = node; 3698 | this.head.hexNode = node; 3699 | this.head.onmouseover = function () { this.hexNode.className = "hexCurrent"; }; 3700 | this.head.onmouseout = function () { this.hexNode.className = "hex"; }; 3701 | node.asn1 = this; 3702 | node.onmouseover = function () { 3703 | var current = !root.selected; 3704 | if (current) { 3705 | root.selected = this.asn1; 3706 | this.className = "hexCurrent"; 3707 | } 3708 | this.asn1.fakeHover(current); 3709 | }; 3710 | node.onmouseout = function () { 3711 | var current = (root.selected == this.asn1); 3712 | this.asn1.fakeOut(current); 3713 | if (current) { 3714 | root.selected = null; 3715 | this.className = "hex"; 3716 | } 3717 | }; 3718 | this.toHexDOM_sub(node, "tag", this.stream, this.posStart(), this.posStart() + 1); 3719 | this.toHexDOM_sub(node, (this.length >= 0) ? "dlen" : "ulen", this.stream, this.posStart() + 1, this.posContent()); 3720 | if (this.sub === null) 3721 | node.appendChild(DOM.text( 3722 | this.stream.hexDump(this.posContent(), this.posEnd()))); 3723 | else if (this.sub.length > 0) { 3724 | var first = this.sub[0]; 3725 | var last = this.sub[this.sub.length - 1]; 3726 | this.toHexDOM_sub(node, "intro", this.stream, this.posContent(), first.posStart()); 3727 | for (var i = 0, max = this.sub.length; i < max; ++i) 3728 | node.appendChild(this.sub[i].toHexDOM(root)); 3729 | this.toHexDOM_sub(node, "outro", this.stream, last.posEnd(), this.posEnd()); 3730 | } 3731 | return node; 3732 | }; 3733 | ASN1.prototype.toHexString = function (root) { 3734 | return this.stream.hexDump(this.posStart(), this.posEnd(), true); 3735 | }; 3736 | ASN1.decodeLength = function (stream) { 3737 | var buf = stream.get(), 3738 | len = buf & 0x7F; 3739 | if (len == buf) 3740 | return len; 3741 | if (len > 3) 3742 | throw "Length over 24 bits not supported at position " + (stream.pos - 1); 3743 | if (len === 0) 3744 | return -1; // undefined 3745 | buf = 0; 3746 | for (var i = 0; i < len; ++i) 3747 | buf = (buf << 8) | stream.get(); 3748 | return buf; 3749 | }; 3750 | ASN1.hasContent = function (tag, len, stream) { 3751 | if (tag & 0x20) // constructed 3752 | return true; 3753 | if ((tag < 0x03) || (tag > 0x04)) 3754 | return false; 3755 | var p = new Stream(stream); 3756 | if (tag == 0x03) p.get(); // BitString unused bits, must be in [0, 7] 3757 | var subTag = p.get(); 3758 | if ((subTag >> 6) & 0x01) // not (universal or context) 3759 | return false; 3760 | try { 3761 | var subLength = ASN1.decodeLength(p); 3762 | return ((p.pos - stream.pos) + subLength == len); 3763 | } catch (exception) { 3764 | return false; 3765 | } 3766 | }; 3767 | ASN1.decode = function (stream) { 3768 | if (!(stream instanceof Stream)) 3769 | stream = new Stream(stream, 0); 3770 | var streamStart = new Stream(stream), 3771 | tag = stream.get(), 3772 | len = ASN1.decodeLength(stream), 3773 | header = stream.pos - streamStart.pos, 3774 | sub = null; 3775 | if (ASN1.hasContent(tag, len, stream)) { 3776 | // it has content, so we decode it 3777 | var start = stream.pos; 3778 | if (tag == 0x03) stream.get(); // skip BitString unused bits, must be in [0, 7] 3779 | sub = []; 3780 | if (len >= 0) { 3781 | // definite length 3782 | var end = start + len; 3783 | while (stream.pos < end) 3784 | sub[sub.length] = ASN1.decode(stream); 3785 | if (stream.pos != end) 3786 | throw "Content size is not correct for container starting at offset " + start; 3787 | } else { 3788 | // undefined length 3789 | try { 3790 | for (;;) { 3791 | var s = ASN1.decode(stream); 3792 | if (s.tag === 0) 3793 | break; 3794 | sub[sub.length] = s; 3795 | } 3796 | len = start - stream.pos; 3797 | } catch (e) { 3798 | throw "Exception while decoding undefined length content: " + e; 3799 | } 3800 | } 3801 | } else 3802 | stream.pos += len; // skip content 3803 | return new ASN1(streamStart, header, len, tag, sub); 3804 | }; 3805 | ASN1.test = function () { 3806 | var test = [ 3807 | { value: [0x27], expected: 0x27 }, 3808 | { value: [0x81, 0xC9], expected: 0xC9 }, 3809 | { value: [0x83, 0xFE, 0xDC, 0xBA], expected: 0xFEDCBA } 3810 | ]; 3811 | for (var i = 0, max = test.length; i < max; ++i) { 3812 | var pos = 0, 3813 | stream = new Stream(test[i].value, 0), 3814 | res = ASN1.decodeLength(stream); 3815 | if (res != test[i].expected) 3816 | document.write("In test[" + i + "] expected " + test[i].expected + " got " + res + "\n"); 3817 | } 3818 | }; 3819 | 3820 | // export globals 3821 | window.ASN1 = ASN1; 3822 | })();/** 3823 | * Retrieve the hexadecimal value (as a string) of the current ASN.1 element 3824 | * @returns {string} 3825 | * @public 3826 | */ 3827 | ASN1.prototype.getHexStringValue = function () { 3828 | var hexString = this.toHexString(); 3829 | var offset = this.header * 2; 3830 | var length = this.length * 2; 3831 | return hexString.substr(offset, length); 3832 | }; 3833 | 3834 | /** 3835 | * Method to parse a pem encoded string containing both a public or private key. 3836 | * The method will translate the pem encoded string in a der encoded string and 3837 | * will parse private key and public key parameters. This method accepts public key 3838 | * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1). 3839 | * 3840 | * @todo Check how many rsa formats use the same format of pkcs #1. 3841 | * 3842 | * The format is defined as: 3843 | * PublicKeyInfo ::= SEQUENCE { 3844 | * algorithm AlgorithmIdentifier, 3845 | * PublicKey BIT STRING 3846 | * } 3847 | * Where AlgorithmIdentifier is: 3848 | * AlgorithmIdentifier ::= SEQUENCE { 3849 | * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm 3850 | * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) 3851 | * } 3852 | * and PublicKey is a SEQUENCE encapsulated in a BIT STRING 3853 | * RSAPublicKey ::= SEQUENCE { 3854 | * modulus INTEGER, -- n 3855 | * publicExponent INTEGER -- e 3856 | * } 3857 | * it's possible to examine the structure of the keys obtained from openssl using 3858 | * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/ 3859 | * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer 3860 | * @private 3861 | */ 3862 | RSAKey.prototype.parseKey = function (pem) { 3863 | try { 3864 | var modulus = 0; 3865 | var public_exponent = 0; 3866 | var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/; 3867 | var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem); 3868 | var asn1 = ASN1.decode(der); 3869 | 3870 | //Fixes a bug with OpenSSL 1.0+ private keys 3871 | if(asn1.sub.length === 3){ 3872 | asn1 = asn1.sub[2].sub[0]; 3873 | } 3874 | if (asn1.sub.length === 9) { 3875 | 3876 | // Parse the private key. 3877 | modulus = asn1.sub[1].getHexStringValue(); //bigint 3878 | this.n = parseBigInt(modulus, 16); 3879 | 3880 | public_exponent = asn1.sub[2].getHexStringValue(); //int 3881 | this.e = parseInt(public_exponent, 16); 3882 | 3883 | var private_exponent = asn1.sub[3].getHexStringValue(); //bigint 3884 | this.d = parseBigInt(private_exponent, 16); 3885 | 3886 | var prime1 = asn1.sub[4].getHexStringValue(); //bigint 3887 | this.p = parseBigInt(prime1, 16); 3888 | 3889 | var prime2 = asn1.sub[5].getHexStringValue(); //bigint 3890 | this.q = parseBigInt(prime2, 16); 3891 | 3892 | var exponent1 = asn1.sub[6].getHexStringValue(); //bigint 3893 | this.dmp1 = parseBigInt(exponent1, 16); 3894 | 3895 | var exponent2 = asn1.sub[7].getHexStringValue(); //bigint 3896 | this.dmq1 = parseBigInt(exponent2, 16); 3897 | 3898 | var coefficient = asn1.sub[8].getHexStringValue(); //bigint 3899 | this.coeff = parseBigInt(coefficient, 16); 3900 | 3901 | } 3902 | else if (asn1.sub.length === 2) { 3903 | 3904 | // Parse the public key. 3905 | var bit_string = asn1.sub[1]; 3906 | var sequence = bit_string.sub[0]; 3907 | 3908 | modulus = sequence.sub[0].getHexStringValue(); 3909 | this.n = parseBigInt(modulus, 16); 3910 | public_exponent = sequence.sub[1].getHexStringValue(); 3911 | this.e = parseInt(public_exponent, 16); 3912 | 3913 | } 3914 | else { 3915 | return false; 3916 | } 3917 | return true; 3918 | } 3919 | catch (ex) { 3920 | return false; 3921 | } 3922 | }; 3923 | 3924 | /** 3925 | * Translate rsa parameters in a hex encoded string representing the rsa key. 3926 | * 3927 | * The translation follow the ASN.1 notation : 3928 | * RSAPrivateKey ::= SEQUENCE { 3929 | * version Version, 3930 | * modulus INTEGER, -- n 3931 | * publicExponent INTEGER, -- e 3932 | * privateExponent INTEGER, -- d 3933 | * prime1 INTEGER, -- p 3934 | * prime2 INTEGER, -- q 3935 | * exponent1 INTEGER, -- d mod (p1) 3936 | * exponent2 INTEGER, -- d mod (q-1) 3937 | * coefficient INTEGER, -- (inverse of q) mod p 3938 | * } 3939 | * @returns {string} DER Encoded String representing the rsa private key 3940 | * @private 3941 | */ 3942 | RSAKey.prototype.getPrivateBaseKey = function () { 3943 | var options = { 3944 | 'array': [ 3945 | new KJUR.asn1.DERInteger({'int': 0}), 3946 | new KJUR.asn1.DERInteger({'bigint': this.n}), 3947 | new KJUR.asn1.DERInteger({'int': this.e}), 3948 | new KJUR.asn1.DERInteger({'bigint': this.d}), 3949 | new KJUR.asn1.DERInteger({'bigint': this.p}), 3950 | new KJUR.asn1.DERInteger({'bigint': this.q}), 3951 | new KJUR.asn1.DERInteger({'bigint': this.dmp1}), 3952 | new KJUR.asn1.DERInteger({'bigint': this.dmq1}), 3953 | new KJUR.asn1.DERInteger({'bigint': this.coeff}) 3954 | ] 3955 | }; 3956 | var seq = new KJUR.asn1.DERSequence(options); 3957 | return seq.getEncodedHex(); 3958 | }; 3959 | 3960 | /** 3961 | * base64 (pem) encoded version of the DER encoded representation 3962 | * @returns {string} pem encoded representation without header and footer 3963 | * @public 3964 | */ 3965 | RSAKey.prototype.getPrivateBaseKeyB64 = function () { 3966 | return hex2b64(this.getPrivateBaseKey()); 3967 | }; 3968 | 3969 | /** 3970 | * Translate rsa parameters in a hex encoded string representing the rsa public key. 3971 | * The representation follow the ASN.1 notation : 3972 | * PublicKeyInfo ::= SEQUENCE { 3973 | * algorithm AlgorithmIdentifier, 3974 | * PublicKey BIT STRING 3975 | * } 3976 | * Where AlgorithmIdentifier is: 3977 | * AlgorithmIdentifier ::= SEQUENCE { 3978 | * algorithm OBJECT IDENTIFIER, the OID of the enc algorithm 3979 | * parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1) 3980 | * } 3981 | * and PublicKey is a SEQUENCE encapsulated in a BIT STRING 3982 | * RSAPublicKey ::= SEQUENCE { 3983 | * modulus INTEGER, -- n 3984 | * publicExponent INTEGER -- e 3985 | * } 3986 | * @returns {string} DER Encoded String representing the rsa public key 3987 | * @private 3988 | */ 3989 | RSAKey.prototype.getPublicBaseKey = function () { 3990 | var options = { 3991 | 'array': [ 3992 | new KJUR.asn1.DERObjectIdentifier({'oid': '1.2.840.113549.1.1.1'}), //RSA Encryption pkcs #1 oid 3993 | new KJUR.asn1.DERNull() 3994 | ] 3995 | }; 3996 | var first_sequence = new KJUR.asn1.DERSequence(options); 3997 | 3998 | options = { 3999 | 'array': [ 4000 | new KJUR.asn1.DERInteger({'bigint': this.n}), 4001 | new KJUR.asn1.DERInteger({'int': this.e}) 4002 | ] 4003 | }; 4004 | var second_sequence = new KJUR.asn1.DERSequence(options); 4005 | 4006 | options = { 4007 | 'hex': '00' + second_sequence.getEncodedHex() 4008 | }; 4009 | var bit_string = new KJUR.asn1.DERBitString(options); 4010 | 4011 | options = { 4012 | 'array': [ 4013 | first_sequence, 4014 | bit_string 4015 | ] 4016 | }; 4017 | var seq = new KJUR.asn1.DERSequence(options); 4018 | return seq.getEncodedHex(); 4019 | }; 4020 | 4021 | /** 4022 | * base64 (pem) encoded version of the DER encoded representation 4023 | * @returns {string} pem encoded representation without header and footer 4024 | * @public 4025 | */ 4026 | RSAKey.prototype.getPublicBaseKeyB64 = function () { 4027 | return hex2b64(this.getPublicBaseKey()); 4028 | }; 4029 | 4030 | /** 4031 | * wrap the string in block of width chars. The default value for rsa keys is 64 4032 | * characters. 4033 | * @param {string} str the pem encoded string without header and footer 4034 | * @param {Number} [width=64] - the length the string has to be wrapped at 4035 | * @returns {string} 4036 | * @private 4037 | */ 4038 | RSAKey.prototype.wordwrap = function (str, width) { 4039 | width = width || 64; 4040 | if (!str) { 4041 | return str; 4042 | } 4043 | var regex = '(.{1,' + width + '})( +|$\n?)|(.{1,' + width + '})'; 4044 | return str.match(RegExp(regex, 'g')).join('\n'); 4045 | }; 4046 | 4047 | /** 4048 | * Retrieve the pem encoded private key 4049 | * @returns {string} the pem encoded private key with header/footer 4050 | * @public 4051 | */ 4052 | RSAKey.prototype.getPrivateKey = function () { 4053 | var key = "-----BEGIN RSA PRIVATE KEY-----\n"; 4054 | key += this.wordwrap(this.getPrivateBaseKeyB64()) + "\n"; 4055 | key += "-----END RSA PRIVATE KEY-----"; 4056 | return key; 4057 | }; 4058 | 4059 | /** 4060 | * Retrieve the pem encoded public key 4061 | * @returns {string} the pem encoded public key with header/footer 4062 | * @public 4063 | */ 4064 | RSAKey.prototype.getPublicKey = function () { 4065 | var key = "-----BEGIN PUBLIC KEY-----\n"; 4066 | key += this.wordwrap(this.getPublicBaseKeyB64()) + "\n"; 4067 | key += "-----END PUBLIC KEY-----"; 4068 | return key; 4069 | }; 4070 | 4071 | /** 4072 | * Check if the object contains the necessary parameters to populate the rsa modulus 4073 | * and public exponent parameters. 4074 | * @param {Object} [obj={}] - An object that may contain the two public key 4075 | * parameters 4076 | * @returns {boolean} true if the object contains both the modulus and the public exponent 4077 | * properties (n and e) 4078 | * @todo check for types of n and e. N should be a parseable bigInt object, E should 4079 | * be a parseable integer number 4080 | * @private 4081 | */ 4082 | RSAKey.prototype.hasPublicKeyProperty = function (obj) { 4083 | obj = obj || {}; 4084 | return ( 4085 | obj.hasOwnProperty('n') && 4086 | obj.hasOwnProperty('e') 4087 | ); 4088 | }; 4089 | 4090 | /** 4091 | * Check if the object contains ALL the parameters of an RSA key. 4092 | * @param {Object} [obj={}] - An object that may contain nine rsa key 4093 | * parameters 4094 | * @returns {boolean} true if the object contains all the parameters needed 4095 | * @todo check for types of the parameters all the parameters but the public exponent 4096 | * should be parseable bigint objects, the public exponent should be a parseable integer number 4097 | * @private 4098 | */ 4099 | RSAKey.prototype.hasPrivateKeyProperty = function (obj) { 4100 | obj = obj || {}; 4101 | return ( 4102 | obj.hasOwnProperty('n') && 4103 | obj.hasOwnProperty('e') && 4104 | obj.hasOwnProperty('d') && 4105 | obj.hasOwnProperty('p') && 4106 | obj.hasOwnProperty('q') && 4107 | obj.hasOwnProperty('dmp1') && 4108 | obj.hasOwnProperty('dmq1') && 4109 | obj.hasOwnProperty('coeff') 4110 | ); 4111 | }; 4112 | 4113 | /** 4114 | * Parse the properties of obj in the current rsa object. Obj should AT LEAST 4115 | * include the modulus and public exponent (n, e) parameters. 4116 | * @param {Object} obj - the object containing rsa parameters 4117 | * @private 4118 | */ 4119 | RSAKey.prototype.parsePropertiesFrom = function (obj) { 4120 | this.n = obj.n; 4121 | this.e = obj.e; 4122 | 4123 | if (obj.hasOwnProperty('d')) { 4124 | this.d = obj.d; 4125 | this.p = obj.p; 4126 | this.q = obj.q; 4127 | this.dmp1 = obj.dmp1; 4128 | this.dmq1 = obj.dmq1; 4129 | this.coeff = obj.coeff; 4130 | } 4131 | }; 4132 | 4133 | /** 4134 | * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object. 4135 | * This object is just a decorator for parsing the key parameter 4136 | * @param {string|Object} key - The key in string format, or an object containing 4137 | * the parameters needed to build a RSAKey object. 4138 | * @constructor 4139 | */ 4140 | var JSEncryptRSAKey = function (key) { 4141 | // Call the super constructor. 4142 | RSAKey.call(this); 4143 | // If a key key was provided. 4144 | if (key) { 4145 | // If this is a string... 4146 | if (typeof key === 'string') { 4147 | this.parseKey(key); 4148 | } 4149 | else if ( 4150 | this.hasPrivateKeyProperty(key) || 4151 | this.hasPublicKeyProperty(key) 4152 | ) { 4153 | // Set the values for the key. 4154 | this.parsePropertiesFrom(key); 4155 | } 4156 | } 4157 | }; 4158 | 4159 | // Derive from RSAKey. 4160 | JSEncryptRSAKey.prototype = new RSAKey(); 4161 | 4162 | // Reset the contructor. 4163 | JSEncryptRSAKey.prototype.constructor = JSEncryptRSAKey; 4164 | 4165 | 4166 | /** 4167 | * 4168 | * @param {Object} [options = {}] - An object to customize JSEncrypt behaviour 4169 | * possible parameters are: 4170 | * - default_key_size {number} default: 1024 the key size in bit 4171 | * - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent 4172 | * - log {boolean} default: false whether log warn/error or not 4173 | * @constructor 4174 | */ 4175 | var JSEncrypt = function (options) { 4176 | options = options || {}; 4177 | this.default_key_size = parseInt(options.default_key_size) || 1024; 4178 | this.default_public_exponent = options.default_public_exponent || '010001'; //65537 default openssl public exponent for rsa key type 4179 | this.log = options.log || false; 4180 | // The private and public key. 4181 | this.key = null; 4182 | }; 4183 | 4184 | /** 4185 | * Method to set the rsa key parameter (one method is enough to set both the public 4186 | * and the private key, since the private key contains the public key paramenters) 4187 | * Log a warning if logs are enabled 4188 | * @param {Object|string} key the pem encoded string or an object (with or without header/footer) 4189 | * @public 4190 | */ 4191 | JSEncrypt.prototype.setKey = function (key) { 4192 | if (this.log && this.key) { 4193 | console.warn('A key was already set, overriding existing.'); 4194 | } 4195 | this.key = new JSEncryptRSAKey(key); 4196 | }; 4197 | 4198 | /** 4199 | * Proxy method for setKey, for api compatibility 4200 | * @see setKey 4201 | * @public 4202 | */ 4203 | JSEncrypt.prototype.setPrivateKey = function (privkey) { 4204 | // Create the key. 4205 | this.setKey(privkey); 4206 | }; 4207 | 4208 | /** 4209 | * Proxy method for setKey, for api compatibility 4210 | * @see setKey 4211 | * @public 4212 | */ 4213 | JSEncrypt.prototype.setPublicKey = function (pubkey) { 4214 | // Sets the public key. 4215 | this.setKey(pubkey); 4216 | }; 4217 | 4218 | /** 4219 | * Proxy method for RSAKey object's decrypt, decrypt the string using the private 4220 | * components of the rsa key object. Note that if the object was not set will be created 4221 | * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor 4222 | * @param {string} string base64 encoded crypted string to decrypt 4223 | * @return {string} the decrypted string 4224 | * @public 4225 | */ 4226 | JSEncrypt.prototype.decrypt = function (string) { 4227 | // Return the decrypted string. 4228 | try { 4229 | return this.getKey().decrypt(b64tohex(string)); 4230 | } 4231 | catch (ex) { 4232 | return false; 4233 | } 4234 | }; 4235 | 4236 | /** 4237 | * Proxy method for RSAKey object's encrypt, encrypt the string using the public 4238 | * components of the rsa key object. Note that if the object was not set will be created 4239 | * on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor 4240 | * @param {string} string the string to encrypt 4241 | * @return {string} the encrypted string encoded in base64 4242 | * @public 4243 | */ 4244 | JSEncrypt.prototype.encrypt = function (string) { 4245 | // Return the encrypted string. 4246 | try { 4247 | return hex2b64(this.getKey().encrypt(string)); 4248 | } 4249 | catch (ex) { 4250 | return false; 4251 | } 4252 | }; 4253 | 4254 | /** 4255 | * Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object 4256 | * will be created and returned 4257 | * @param {callback} [cb] the callback to be called if we want the key to be generated 4258 | * in an async fashion 4259 | * @returns {JSEncryptRSAKey} the JSEncryptRSAKey object 4260 | * @public 4261 | */ 4262 | JSEncrypt.prototype.getKey = function (cb) { 4263 | // Only create new if it does not exist. 4264 | if (!this.key) { 4265 | // Get a new private key. 4266 | this.key = new JSEncryptRSAKey(); 4267 | if (cb && {}.toString.call(cb) === '[object Function]') { 4268 | this.key.generateAsync(this.default_key_size, this.default_public_exponent, cb); 4269 | return; 4270 | } 4271 | // Generate the key. 4272 | this.key.generate(this.default_key_size, this.default_public_exponent); 4273 | } 4274 | return this.key; 4275 | }; 4276 | 4277 | /** 4278 | * Returns the pem encoded representation of the private key 4279 | * If the key doesn't exists a new key will be created 4280 | * @returns {string} pem encoded representation of the private key WITH header and footer 4281 | * @public 4282 | */ 4283 | JSEncrypt.prototype.getPrivateKey = function () { 4284 | // Return the private representation of this key. 4285 | return this.getKey().getPrivateKey(); 4286 | }; 4287 | 4288 | /** 4289 | * Returns the pem encoded representation of the private key 4290 | * If the key doesn't exists a new key will be created 4291 | * @returns {string} pem encoded representation of the private key WITHOUT header and footer 4292 | * @public 4293 | */ 4294 | JSEncrypt.prototype.getPrivateKeyB64 = function () { 4295 | // Return the private representation of this key. 4296 | return this.getKey().getPrivateBaseKeyB64(); 4297 | }; 4298 | 4299 | 4300 | /** 4301 | * Returns the pem encoded representation of the public key 4302 | * If the key doesn't exists a new key will be created 4303 | * @returns {string} pem encoded representation of the public key WITH header and footer 4304 | * @public 4305 | */ 4306 | JSEncrypt.prototype.getPublicKey = function () { 4307 | // Return the private representation of this key. 4308 | return this.getKey().getPublicKey(); 4309 | }; 4310 | 4311 | /** 4312 | * Returns the pem encoded representation of the public key 4313 | * If the key doesn't exists a new key will be created 4314 | * @returns {string} pem encoded representation of the public key WITHOUT header and footer 4315 | * @public 4316 | */ 4317 | JSEncrypt.prototype.getPublicKeyB64 = function () { 4318 | // Return the private representation of this key. 4319 | return this.getKey().getPublicBaseKeyB64(); 4320 | }; 4321 | 4322 | exports.JSEncrypt = JSEncrypt; 4323 | })(JSEncryptExports); 4324 | var JSEncrypt = JSEncryptExports.JSEncrypt; 4325 | --------------------------------------------------------------------------------