1/** 2 * Utility functions for web applications. 3 * 4 * @author Dave Longley 5 * 6 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 7 */ 8(function() { 9/* ########## Begin module implementation ########## */ 10function initModule(forge) { 11 12/* Utilities API */ 13var util = forge.util = forge.util || {}; 14 15// define setImmediate and nextTick 16(function() { 17 // use native nextTick 18 if(typeof process !== 'undefined' && process.nextTick) { 19 util.nextTick = process.nextTick; 20 if(typeof setImmediate === 'function') { 21 util.setImmediate = setImmediate; 22 } else { 23 // polyfill setImmediate with nextTick, older versions of node 24 // (those w/o setImmediate) won't totally starve IO 25 util.setImmediate = util.nextTick; 26 } 27 return; 28 } 29 30 // polyfill nextTick with native setImmediate 31 if(typeof setImmediate === 'function') { 32 util.setImmediate = function() { return setImmediate.apply(undefined, arguments); }; 33 util.nextTick = function(callback) { 34 return setImmediate(callback); 35 }; 36 return; 37 } 38 39 /* Note: A polyfill upgrade pattern is used here to allow combining 40 polyfills. For example, MutationObserver is fast, but blocks UI updates, 41 so it needs to allow UI updates periodically, so it falls back on 42 postMessage or setTimeout. */ 43 44 // polyfill with setTimeout 45 util.setImmediate = function(callback) { 46 setTimeout(callback, 0); 47 }; 48 49 // upgrade polyfill to use postMessage 50 if(typeof window !== 'undefined' && 51 typeof window.postMessage === 'function') { 52 var msg = 'forge.setImmediate'; 53 var callbacks = []; 54 util.setImmediate = function(callback) { 55 callbacks.push(callback); 56 // only send message when one hasn't been sent in 57 // the current turn of the event loop 58 if(callbacks.length === 1) { 59 window.postMessage(msg, '*'); 60 } 61 }; 62 function handler(event) { 63 if(event.source === window && event.data === msg) { 64 event.stopPropagation(); 65 var copy = callbacks.slice(); 66 callbacks.length = 0; 67 copy.forEach(function(callback) { 68 callback(); 69 }); 70 } 71 } 72 window.addEventListener('message', handler, true); 73 } 74 75 // upgrade polyfill to use MutationObserver 76 if(typeof MutationObserver !== 'undefined') { 77 // polyfill with MutationObserver 78 var now = Date.now(); 79 var attr = true; 80 var div = document.createElement('div'); 81 var callbacks = []; 82 new MutationObserver(function() { 83 var copy = callbacks.slice(); 84 callbacks.length = 0; 85 copy.forEach(function(callback) { 86 callback(); 87 }); 88 }).observe(div, {attributes: true}); 89 var oldSetImmediate = util.setImmediate; 90 util.setImmediate = function(callback) { 91 if(Date.now() - now > 15) { 92 now = Date.now(); 93 oldSetImmediate(callback); 94 } else { 95 callbacks.push(callback); 96 // only trigger observer when it hasn't been triggered in 97 // the current turn of the event loop 98 if(callbacks.length === 1) { 99 div.setAttribute('a', attr = !attr); 100 } 101 } 102 }; 103 } 104 105 util.nextTick = util.setImmediate; 106})(); 107 108// define isArray 109util.isArray = Array.isArray || function(x) { 110 return Object.prototype.toString.call(x) === '[object Array]'; 111}; 112 113// define isArrayBuffer 114util.isArrayBuffer = function(x) { 115 return typeof ArrayBuffer !== 'undefined' && x instanceof ArrayBuffer; 116}; 117 118// define isArrayBufferView 119util.isArrayBufferView = function(x) { 120 return x && util.isArrayBuffer(x.buffer) && x.byteLength !== undefined; 121}; 122 123// TODO: set ByteBuffer to best available backing 124util.ByteBuffer = ByteStringBuffer; 125 126/** Buffer w/BinaryString backing */ 127 128/** 129 * Constructor for a binary string backed byte buffer. 130 * 131 * @param [b] the bytes to wrap (either encoded as string, one byte per 132 * character, or as an ArrayBuffer or Typed Array). 133 */ 134function ByteStringBuffer(b) { 135 // TODO: update to match DataBuffer API 136 137 // the data in this buffer 138 this.data = ''; 139 // the pointer for reading from this buffer 140 this.read = 0; 141 142 if(typeof b === 'string') { 143 this.data = b; 144 } else if(util.isArrayBuffer(b) || util.isArrayBufferView(b)) { 145 // convert native buffer to forge buffer
146 // FIXME: support native buffers internally instead 147 var arr = new Uint8Array(b); 148 try { 149 this.data = String.fromCharCode.apply(null, arr); 150 } catch(e) { 151 for(var i = 0; i < arr.length; ++i) { 152 this.putByte(arr[i]); 153 } 154 } 155 } else if(b instanceof ByteStringBuffer || 156 (typeof b === 'object' && typeof b.data === 'string' && 157 typeof b.read === 'number')) { 158 // copy existing buffer 159 this.data = b.data; 160 this.read = b.read; 161 } 162 163 // used for v8 optimization 164 this._constructedStringLength = 0; 165} 166util.ByteStringBuffer = ByteStringBuffer; 167 168/* Note: This is an optimization for V8-based browsers. When V8 concatenates 169 a string, the strings are only joined logically using a "cons string" or 170 "constructed/concatenated string". These containers keep references to one 171 another and can result in very large memory usage. For example, if a 2MB 172 string is constructed by concatenating 4 bytes together at a time, the 173 memory usage will be ~44MB; so ~22x increase. The strings are only joined 174 together when an operation requiring their joining takes place, such as 175 substr(). This function is called when adding data to this buffer to ensure 176 these types of strings are periodically joined to reduce the memory 177 footprint. */ 178var _MAX_CONSTRUCTED_STRING_LENGTH = 4096; 179util.ByteStringBuffer.prototype._optimizeConstructedString = function(x) { 180 this._constructedStringLength += x; 181 if(this._constructedStringLength > _MAX_CONSTRUCTED_STRING_LENGTH) { 182 // this substr() should cause the constructed string to join 183 this.data.substr(0, 1); 184 this._constructedStringLength = 0; 185 } 186}; 187 188/** 189 * Gets the number of bytes in this buffer. 190 * 191 * @return the number of bytes in this buffer. 192 */ 193util.ByteStringBuffer.prototype.length = function() { 194 return this.data.length - this.read; 195}; 196 197/** 198 * Gets whether or not this buffer is empty. 199 * 200 * @return true if this buffer is empty, false if not. 201 */ 202util.ByteStringBuffer.prototype.isEmpty = function() { 203 return this.length() <= 0; 204}; 205 206/** 207 * Puts a byte in this buffer. 208 * 209 * @param b the byte to put. 210 * 211 * @return this buffer. 212 */ 213util.ByteStringBuffer.prototype.putByte = function(b) { 214 return this.putBytes(String.fromCharCode(b)); 215}; 216 217/** 218 * Puts a byte in this buffer N times. 219 * 220 * @param b the byte to put. 221 * @param n the number of bytes of value b to put. 222 * 223 * @return this buffer. 224 */ 225util.ByteStringBuffer.prototype.fillWithByte = function(b, n) { 226 b = String.fromCharCode(b); 227 var d = this.data; 228 while(n > 0) { 229 if(n & 1) { 230 d += b; 231 } 232 n >>>= 1; 233 if(n > 0) { 234 b += b; 235 } 236 } 237 this.data = d; 238 this._optimizeConstructedString(n); 239 return this; 240}; 241 242/** 243 * Puts bytes in this buffer. 244 * 245 * @param bytes the bytes (as a UTF-8 encoded string) to put. 246 * 247 * @return this buffer. 248 */ 249util.ByteStringBuffer.prototype.putBytes = function(bytes) { 250 this.data += bytes; 251 this._optimizeConstructedString(bytes.length); 252 return this; 253}; 254 255/** 256 * Puts a UTF-16 encoded string into this buffer. 257 * 258 * @param str the string to put. 259 * 260 * @return this buffer. 261 */ 262util.ByteStringBuffer.prototype.putString = function(str) { 263 return this.putBytes(util.encodeUtf8(str)); 264}; 265 266/** 267 * Puts a 16-bit integer in this buffer in big-endian order. 268 * 269 * @param i the 16-bit integer. 270 * 271 * @return this buffer. 272 */ 273util.ByteStringBuffer.prototype.putInt16 = function(i) { 274 return this.putBytes( 275 String.fromCharCode(i >> 8 & 0xFF) + 276 String.fromCharCode(i & 0xFF)); 277}; 278 279/** 280 * Puts a 24-bit integer in this buffer in big-endian order. 281 * 282 * @param i the 24-bit integer. 283 * 284 * @return this buffer. 285 */ 286util.ByteStringBuffer.prototype.putInt24 = function(i) { 287 return this.putBytes( 288 String.fromCharCode(i >> 16 & 0xFF) + 289 String.fromCharCode(i >> 8 & 0xFF) + 290 String.fromCharCode(i & 0xFF)); 291}; 292 293/** 294 * Puts a 32-bit integer in this buffer in big-endian order. 295 * 296 * @param i the 32-bit integer. 297 * 298 * @return this buffer. 299 */ 300util.ByteStringBuffer.prototype.putInt32 = function(i) { 301 return this.putBytes( 302 String.fromCharCode(i >> 24 & 0xFF) + 303 String.fromCharCode(i >> 16 & 0xFF) + 304 String.fromCharCode(i >> 8 & 0xFF) + 305 String.fromCharCode(i & 0xFF)); 306}; 307 308/** 309 * Puts a 16-bit integer in this buffer in little-endian order. 310 * 311 * @param i the 16-bit integer. 312 * 313 * @return this buffer. 314 */ 315util.ByteStringBuffer.prototype.putInt16Le = function(i) { 316 return this.putBytes( 317 String.fromCharCode(i & 0xFF) + 318 String.fromCharCode(i >> 8 & 0xFF)); 319}; 320 321/** 322 * Puts a 24-bit integer in this buffer in little-endian order. 323 * 324 * @param i the 24-bit integer. 325 * 326 * @return this buffer. 327 */ 328util.ByteStringBuffer.prototype.putInt24Le = function(i) { 329 return this.putBytes( 330 String.fromCharCode(i & 0xFF) + 331 String.fromCharCode(i >> 8 & 0xFF) + 332 String.fromCharCode(i >> 16 & 0xFF)); 333}; 334 335/** 336 * Puts a 32-bit integer in this buffer in little-endian order. 337 * 338 * @param i the 32-bit integer. 339 * 340 * @return this buffer. 341 */ 342util.ByteStringBuffer.prototype.putInt32Le = function(i) { 343 return this.putBytes( 344 String.fromCharCode(i & 0xFF) + 345 String.fromCharCode(i >> 8 & 0xFF) + 346 String.fromCharCode(i >> 16 & 0xFF) + 347 String.fromCharCode(i >> 24 & 0xFF)); 348}; 349 350/** 351 * Puts an n-bit integer in this buffer in big-endian order. 352 * 353 * @param i the n-bit integer. 354 * @param n the number of bits in the integer. 355 * 356 * @return this buffer. 357 */ 358util.ByteStringBuffer.prototype.putInt = function(i, n) { 359 var bytes = ''; 360 do { 361 n -= 8; 362 bytes += String.fromCharCode((i >> n) & 0xFF); 363 } while(n > 0); 364 return this.putBytes(bytes); 365}; 366 367/** 368 * Puts a signed n-bit integer in this buffer in big-endian order. Two's 369 * complement representation is used. 370 * 371 * @param i the n-bit integer. 372 * @param n the number of bits in the integer. 373 * 374 * @return this buffer. 375 */ 376util.ByteStringBuffer.prototype.putSignedInt = function(i, n) { 377 if(i < 0) { 378 i += 2 << (n - 1); 379 } 380 return this.putInt(i, n); 381}; 382 383/** 384 * Puts the given buffer into this buffer. 385 * 386 * @param buffer the buffer to put into this one. 387 * 388 * @return this buffer. 389 */ 390util.ByteStringBuffer.prototype.putBuffer = function(buffer) { 391 return this.putBytes(buffer.getBytes()); 392}; 393 394/** 395 * Gets a byte from this buffer and advances the read pointer by 1. 396 * 397 * @return the byte. 398 */ 399util.ByteStringBuffer.prototype.getByte = function() { 400 return this.data.charCodeAt(this.read++); 401}; 402 403/** 404 * Gets a uint16 from this buffer in big-endian order and advances the read 405 * pointer by 2. 406 * 407 * @return the uint16. 408 */ 409util.ByteStringBuffer.prototype.getInt16 = function() { 410 var rval = ( 411 this.data.charCodeAt(this.read) << 8 ^ 412 this.data.charCodeAt(this.read + 1)); 413 this.read += 2; 414 return rval; 415}; 416 417/** 418 * Gets a uint24 from this buffer in big-endian order and advances the read 419 * pointer by 3. 420 * 421 * @return the uint24. 422 */ 423util.ByteStringBuffer.prototype.getInt24 = function() { 424 var rval = ( 425 this.data.charCodeAt(this.read) << 16 ^ 426 this.data.charCodeAt(this.read + 1) << 8 ^ 427 this.data.charCodeAt(this.read + 2)); 428 this.read += 3; 429 return rval; 430}; 431 432/** 433 * Gets a uint32 from this buffer in big-endian order and advances the read 434 * pointer by 4. 435 * 436 * @return the word. 437 */ 438util.ByteStringBuffer.prototype.getInt32 = function() { 439 var rval = ( 440 this.data.charCodeAt(this.read) << 24 ^ 441 this.data.charCodeAt(this.read + 1) << 16 ^ 442 this.data.charCodeAt(this.read + 2) << 8 ^ 443 this.data.charCodeAt(this.read + 3)); 444 this.read += 4; 445 return rval; 446}; 447 448/** 449 * Gets a uint16 from this buffer in little-endian order and advances the read 450 * pointer by 2. 451 * 452 * @return the uint16. 453 */ 454util.ByteStringBuffer.prototype.getInt16Le = function() { 455 var rval = ( 456 this.data.charCodeAt(this.read) ^ 457 this.data.charCodeAt(this.read + 1) << 8); 458 this.read += 2; 459 return rval; 460}; 461 462/** 463 * Gets a uint24 from this buffer in little-endian order and advances the read 464 * pointer by 3. 465 * 466 * @return the uint24. 467 */ 468util.ByteStringBuffer.prototype.getInt24Le = function() { 469 var rval = ( 470 this.data.charCodeAt(this.read) ^ 471 this.data.charCodeAt(this.read + 1) << 8 ^ 472 this.data.charCodeAt(this.read + 2) << 16); 473 this.read += 3; 474 return rval; 475}; 476 477/** 478 * Gets a uint32 from this buffer in little-endian order and advances the read 479 * pointer by 4. 480 * 481 * @return the word. 482 */ 483util.ByteStringBuffer.prototype.getInt32Le = function() { 484 var rval = ( 485 this.data.charCodeAt(this.read) ^ 486 this.data.charCodeAt(this.read + 1) << 8 ^ 487 this.data.charCodeAt(this.read + 2) << 16 ^ 488 this.data.charCodeAt(this.read + 3) << 24); 489 this.read += 4; 490 return rval; 491}; 492 493/** 494 * Gets an n-bit integer from this buffer in big-endian order and advances the 495 * read pointer by n/8. 496 * 497 * @param n the number of bits in the integer. 498 * 499 * @return the integer. 500 */ 501util.ByteStringBuffer.prototype.getInt = function(n) { 502 var rval = 0; 503 do { 504 rval = (rval << 8) + this.data.charCodeAt(this.read++); 505 n -= 8; 506 } while(n > 0); 507 return rval; 508}; 509 510/** 511 * Gets a signed n-bit integer from this buffer in big-endian order, using 512 * two's complement, and advances the read pointer by n/8. 513 * 514 * @param n the number of bits in the integer. 515 * 516 * @return the integer. 517 */ 518util.ByteStringBuffer.prototype.getSignedInt = function(n) { 519 var x = this.getInt(n); 520 var max = 2 << (n - 2); 521 if(x >= max) { 522 x -= max << 1; 523 } 524 return x; 525}; 526 527/** 528 * Reads bytes out into a UTF-8 string and clears them from the buffer. 529 * 530 * @param count the number of bytes to read, undefined or null for all. 531 * 532 * @return a UTF-8 string of bytes. 533 */ 534util.ByteStringBuffer.prototype.getBytes = function(count) { 535 var rval; 536 if(count) { 537 // read count bytes 538 count = Math.min(this.length(), count); 539 rval = this.data.slice(this.read, this.read + count); 540 this.read += count; 541 } else if(count === 0) { 542 rval = ''; 543 } else { 544 // read all bytes, optimize to only copy when needed 545 rval = (this.read === 0) ? this.data : this.data.slice(this.read); 546 this.clear(); 547 } 548 return rval; 549}; 550 551/** 552 * Gets a UTF-8 encoded string of the bytes from this buffer without modifying 553 * the read pointer. 554 * 555 * @param count the number of bytes to get, omit to get all. 556 * 557 * @return a string full of UTF-8 encoded characters. 558 */ 559util.ByteStringBuffer.prototype.bytes = function(count) { 560 return (typeof(count) === 'undefined' ? 561 this.data.slice(this.read) : 562 this.data.slice(this.read, this.read + count)); 563}; 564 565/** 566 * Gets a byte at the given index without modifying the read pointer. 567 * 568 * @param i the byte index. 569 * 570 * @return the byte. 571 */ 572util.ByteStringBuffer.prototype.at = function(i) { 573 return this.data.charCodeAt(this.read + i); 574}; 575 576/** 577 * Puts a byte at the given index without modifying the read pointer. 578 * 579 * @param i the byte index. 580 * @param b the byte to put. 581 * 582 * @return this buffer. 583 */ 584util.ByteStringBuffer.prototype.setAt = function(i, b) { 585 this.data = this.data.substr(0, this.read + i) + 586 String.fromCharCode(b) + 587 this.data.substr(this.read + i + 1); 588 return this; 589}; 590 591/**
592 * Gets the last byte without modifying the read pointer. 593 * 594 * @return the last byte. 595 */ 596util.ByteStringBuffer.prototype.last = function() { 597 return this.data.charCodeAt(this.data.length - 1); 598}; 599 600/** 601 * Creates a copy of this buffer. 602 * 603 * @return the copy. 604 */ 605util.ByteStringBuffer.prototype.copy = function() { 606 var c = util.createBuffer(this.data); 607 c.read = this.read; 608 return c; 609}; 610 611/** 612 * Compacts this buffer. 613 * 614 * @return this buffer. 615 */ 616util.ByteStringBuffer.prototype.compact = function() { 617 if(this.read > 0) { 618 this.data = this.data.slice(this.read); 619 this.read = 0; 620 } 621 return this; 622}; 623 624/** 625 * Clears this buffer. 626 * 627 * @return this buffer. 628 */ 629util.ByteStringBuffer.prototype.clear = function() { 630 this.data = ''; 631 this.read = 0; 632 return this; 633}; 634 635/** 636 * Shortens this buffer by triming bytes off of the end of this buffer. 637 * 638 * @param count the number of bytes to trim off. 639 * 640 * @return this buffer. 641 */ 642util.ByteStringBuffer.prototype.truncate = function(count) { 643 var len = Math.max(0, this.length() - count); 644 this.data = this.data.substr(this.read, len); 645 this.read = 0; 646 return this; 647}; 648 649/** 650 * Converts this buffer to a hexadecimal string. 651 * 652 * @return a hexadecimal string. 653 */ 654util.ByteStringBuffer.prototype.toHex = function() { 655 var rval = ''; 656 for(var i = this.read; i < this.data.length; ++i) { 657 var b = this.data.charCodeAt(i); 658 if(b < 16) { 659 rval += '0'; 660 } 661 rval += b.toString(16); 662 } 663 return rval; 664}; 665 666/** 667 * Converts this buffer to a UTF-16 string (standard JavaScript string). 668 * 669 * @return a UTF-16 string. 670 */ 671util.ByteStringBuffer.prototype.toString = function() { 672 return util.decodeUtf8(this.bytes()); 673}; 674 675/** End Buffer w/BinaryString backing */ 676 677 678/** Buffer w/UInt8Array backing */ 679 680/** 681 * FIXME: Experimental. Do not use yet. 682 * 683 * Constructor for an ArrayBuffer-backed byte buffer. 684 * 685 * The buffer may be constructed from a string, an ArrayBuffer, DataView, or a 686 * TypedArray. 687 * 688 * If a string is given, its encoding should be provided as an option, 689 * otherwise it will default to 'binary'. A 'binary' string is encoded such 690 * that each character is one byte in length and size. 691 * 692 * If an ArrayBuffer, DataView, or TypedArray is given, it will be used 693 * *directly* without any copying. Note that, if a write to the buffer requires 694 * more space, the buffer will allocate a new backing ArrayBuffer to 695 * accommodate. The starting read and write offsets for the buffer may be 696 * given as options. 697 * 698 * @param [b] the initial bytes for this buffer. 699 * @param options the options to use: 700 * [readOffset] the starting read offset to use (default: 0). 701 * [writeOffset] the starting write offset to use (default: the 702 * length of the first parameter). 703 * [growSize] the minimum amount, in bytes, to grow the buffer by to 704 * accommodate writes (default: 1024). 705 * [encoding] the encoding ('binary', 'utf8', 'utf16', 'hex') for the 706 * first parameter, if it is a string (default: 'binary'). 707 */ 708function DataBuffer(b, options) { 709 // default options 710 options = options || {}; 711 712 // pointers for read from/write to buffer 713 this.read = options.readOffset || 0; 714 this.growSize = options.growSize || 1024; 715 716 var isArrayBuffer = util.isArrayBuffer(b); 717 var isArrayBufferView = util.isArrayBufferView(b); 718 if(isArrayBuffer || isArrayBufferView) { 719 // use ArrayBuffer directly 720 if(isArrayBuffer) { 721 this.data = new DataView(b); 722 } else { 723 // TODO: adjust read/write offset based on the type of view 724 // or specify that this must be done in the options ... that the 725 // offsets are byte-based 726 this.data = new DataView(b.buffer, b.byteOffset, b.byteLength); 727 } 728 this.write = ('writeOffset' in options ? 729 options.writeOffset : this.data.byteLength); 730 return; 731 } 732 733 // initialize to empty array buffer and add any given bytes using putBytes 734 this.data = new DataView(new ArrayBuffer(0)); 735 this.write = 0; 736 737 if(b !== null && b !== undefined) { 738 this.putBytes(b); 739 } 740 741 if('writeOffset' in options) { 742 this.write = options.writeOffset; 743 } 744} 745util.DataBuffer = DataBuffer; 746 747/** 748 * Gets the number of bytes in this buffer. 749 * 750 * @return the number of bytes in this buffer. 751 */ 752util.DataBuffer.prototype.length = function() { 753 return this.write - this.read; 754}; 755 756/** 757 * Gets whether or not this buffer is empty. 758 * 759 * @return true if this buffer is empty, false if not. 760 */ 761util.DataBuffer.prototype.isEmpty = function() { 762 return this.length() <= 0; 763}; 764 765/** 766 * Ensures this buffer has enough empty space to accommodate the given number 767 * of bytes. An optional parameter may be given that indicates a minimum 768 * amount to grow the buffer if necessary. If the parameter is not given, 769 * the buffer will be grown by some previously-specified default amount 770 * or heuristic. 771 * 772 * @param amount the number of bytes to accommodate. 773 * @param [growSize] the minimum amount, in bytes, to grow the buffer by if 774 * necessary. 775 */ 776util.DataBuffer.prototype.accommodate = function(amount, growSize) { 777 if(this.length() >= amount) { 778 return this; 779 } 780 growSize = Math.max(growSize || this.growSize, amount); 781 782 // grow buffer 783 var src = new Uint8Array( 784 this.data.buffer, this.data.byteOffset, this.data.byteLength); 785 var dst = new Uint8Array(this.length() + growSize); 786 dst.set(src); 787 this.data = new DataView(dst.buffer); 788 789 return this; 790}; 791 792/** 793 * Puts a byte in this buffer. 794 * 795 * @param b the byte to put. 796 * 797 * @return this buffer. 798 */ 799util.DataBuffer.prototype.putByte = function(b) { 800 this.accommodate(1); 801 this.data.setUint8(this.write++, b); 802 return this; 803}; 804 805/** 806 * Puts a byte in this buffer N times. 807 * 808 * @param b the byte to put. 809 * @param n the number of bytes of value b to put. 810 * 811 * @return this buffer. 812 */ 813util.DataBuffer.prototype.fillWithByte = function(b, n) { 814 this.accommodate(n); 815 for(var i = 0; i < n; ++i) { 816 this.data.setUint8(b); 817 } 818 return this; 819}; 820 821/** 822 * Puts bytes in this buffer. The bytes may be given as a string, an 823 * ArrayBuffer, a DataView, or a TypedArray. 824 * 825 * @param bytes the bytes to put. 826 * @param [encoding] the encoding for the first parameter ('binary', 'utf8', 827 * 'utf16', 'hex'), if it is a string (default: 'binary'). 828 * 829 * @return this buffer. 830 */ 831util.DataBuffer.prototype.putBytes = function(bytes, encoding) { 832 if(util.isArrayBufferView(bytes)) { 833 var src = new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength); 834 var len = src.byteLength - src.byteOffset; 835 this.accommodate(len); 836 var dst = new Uint8Array(this.data.buffer, this.write); 837 dst.set(src); 838 this.write += len; 839 return this; 840 } 841 842 if(util.isArrayBuffer(bytes)) { 843 var src = new Uint8Array(bytes); 844 this.accommodate(src.byteLength); 845 var dst = new Uint8Array(this.data.buffer); 846 dst.set(src, this.write); 847 this.write += src.byteLength; 848 return this; 849 } 850 851 // bytes is a util.DataBuffer or equivalent 852 if(bytes instanceof util.DataBuffer || 853 (typeof bytes === 'object' && 854 typeof bytes.read === 'number' && typeof bytes.write === 'number' && 855 util.isArrayBufferView(bytes.data))) { 856 var src = new Uint8Array(bytes.data.byteLength, bytes.read, bytes.length()); 857 this.accommodate(src.byteLength); 858 var dst = new Uint8Array(bytes.data.byteLength, this.write); 859 dst.set(src); 860 this.write += src.byteLength; 861 return this; 862 } 863 864 if(bytes instanceof util.ByteStringBuffer) { 865 // copy binary string and process as the same as a string parameter below 866 bytes = bytes.data; 867 encoding = 'binary'; 868 } 869 870 // string conversion 871 encoding = encoding || 'binary'; 872 if(typeof bytes === 'string') { 873 var view; 874 875 // decode from string 876 if(encoding === 'hex') { 877 this.accommodate(Math.ceil(bytes.length / 2)); 878 view = new Uint8Array(this.data.buffer, this.write); 879 this.write += util.binary.hex.decode(bytes, view, this.write); 880 return this; 881 } 882 if(encoding === 'base64') { 883 this.accommodate(Math.ceil(bytes.length / 4) * 3); 884 view = new Uint8Array(this.data.buffer, this.write); 885 this.write += util.binary.base64.decode(bytes, view, this.write); 886 return this; 887 } 888 889 // encode text as UTF-8 bytes 890 if(encoding === 'utf8') { 891 // encode as UTF-8 then decode string as raw binary 892 bytes = util.encodeUtf8(bytes); 893 encoding = 'binary'; 894 } 895 896 // decode string as raw binary 897 if(encoding === 'binary' || encoding === 'raw') { 898 // one byte per character 899 this.accommodate(bytes.length); 900 view = new Uint8Array(this.data.buffer, this.write); 901 this.write += util.binary.raw.decode(view); 902 return this; 903 } 904 905 // encode text as UTF-16 bytes 906 if(encoding === 'utf16') { 907 // two bytes per character 908 this.accommodate(bytes.length * 2); 909 view = new Uint16Array(this.data.buffer, this.write); 910 this.write += util.text.utf16.encode(view); 911 return this; 912 } 913 914 throw new Error('Invalid encoding: ' + encoding); 915 } 916 917 throw Error('Invalid parameter: ' + bytes); 918}; 919 920/** 921 * Puts the given buffer into this buffer. 922 * 923 * @param buffer the buffer to put into this one. 924 * 925 * @return this buffer. 926 */ 927util.DataBuffer.prototype.putBuffer = function(buffer) { 928 this.putBytes(buffer); 929 buffer.clear(); 930 return this; 931}; 932 933/** 934 * Puts a string into this buffer. 935 * 936 * @param str the string to put. 937 * @param [encoding] the encoding for the string (default: 'utf16'). 938 * 939 * @return this buffer. 940 */ 941util.DataBuffer.prototype.putString = function(str) { 942 return this.putBytes(str, 'utf16'); 943}; 944 945/** 946 * Puts a 16-bit integer in this buffer in big-endian order. 947 * 948 * @param i the 16-bit integer. 949 * 950 * @return this buffer. 951 */ 952util.DataBuffer.prototype.putInt16 = function(i) { 953 this.accommodate(2); 954 this.data.setInt16(this.write, i); 955 this.write += 2; 956 return this; 957}; 958 959/** 960 * Puts a 24-bit integer in this buffer in big-endian order. 961 * 962 * @param i the 24-bit integer. 963 * 964 * @return this buffer. 965 */ 966util.DataBuffer.prototype.putInt24 = function(i) { 967 this.accommodate(3); 968 this.data.setInt16(this.write, i >> 8 & 0xFFFF); 969 this.data.setInt8(this.write, i >> 16 & 0xFF); 970 this.write += 3; 971 return this; 972}; 973 974/** 975 * Puts a 32-bit integer in this buffer in big-endian order. 976 * 977 * @param i the 32-bit integer. 978 * 979 * @return this buffer. 980 */ 981util.DataBuffer.prototype.putInt32 = function(i) { 982 this.accommodate(4); 983 this.data.setInt32(this.write, i); 984 this.write += 4; 985 return this; 986}; 987 988/** 989 * Puts a 16-bit integer in this buffer in little-endian order. 990 * 991 * @param i the 16-bit integer. 992 * 993 * @return this buffer. 994 */ 995util.DataBuffer.prototype.putInt16Le = function(i) { 996 this.accommodate(2); 997 this.data.setInt16(this.write, i, true); 998 this.write += 2; 999 return this; 1000}; 1001 1002/** 1003 * Puts a 24-bit integer in this buffer in little-endian order. 1004 * 1005 * @param i the 24-bit integer. 1006 * 1007 * @return this buffer. 1008 */ 1009util.DataBuffer.prototype.putInt24Le = function(i) { 1010 this.accommodate(3); 1011 this.data.setInt8(this.write, i >> 16 & 0xFF); 1012 this.data.setInt16(this.write, i >> 8 & 0xFFFF, true); 1013 this.write += 3; 1014 return this; 1015}; 1016 1017/** 1018 * Puts a 32-bit integer in this buffer in little-endian order. 1019 * 1020 * @param i the 32-bit integer. 1021 * 1022 * @return this buffer. 1023 */ 1024util.DataBuffer.prototype.putInt32Le = function(i) { 1025 this.accommodate(4); 1026 this.data.setInt32(this.write, i, true); 1027 this.write += 4; 1028 return this; 1029}; 1030 1031/** 1032 * Puts an n-bit integer in this buffer in big-endian order. 1033 * 1034 * @param i the n-bit integer. 1035 * @param n the number of bits in the integer. 1036 * 1037 * @return this buffer. 1038 */ 1039util.DataBuffer.prototype.putInt = function(i, n) { 1040 this.accommodate(n / 8); 1041 do { 1042 n -= 8; 1043 this.data.setInt8(this.write++, (i >> n) & 0xFF); 1044 } while(n > 0); 1045 return this; 1046}; 1047 1048/** 1049 * Puts a signed n-bit integer in this buffer in big-endian order. Two's 1050 * complement representation is used. 1051 * 1052 * @param i the n-bit integer. 1053 * @param n the number of bits in the integer. 1054 * 1055 * @return this buffer. 1056 */ 1057util.DataBuffer.prototype.putSignedInt = function(i, n) { 1058 this.accommodate(n / 8); 1059 if(i < 0) { 1060 i += 2 << (n - 1); 1061 } 1062 return this.putInt(i, n); 1063}; 1064 1065/** 1066 * Gets a byte from this buffer and advances the read pointer by 1. 1067 * 1068 * @return the byte. 1069 */ 1070util.DataBuffer.prototype.getByte = function() { 1071 return this.data.getInt8(this.read++); 1072}; 1073 1074/** 1075 * Gets a uint16 from this buffer in big-endian order and advances the read 1076 * pointer by 2. 1077 * 1078 * @return the uint16. 1079 */ 1080util.DataBuffer.prototype.getInt16 = function() { 1081 var rval = this.data.getInt16(this.read); 1082 this.read += 2; 1083 return rval; 1084}; 1085 1086/** 1087 * Gets a uint24 from this buffer in big-endian order and advances the read 1088 * pointer by 3. 1089 * 1090 * @return the uint24. 1091 */ 1092util.DataBuffer.prototype.getInt24 = function() { 1093 var rval = ( 1094 this.data.getInt16(this.read) << 8 ^ 1095 this.data.getInt8(this.read + 2)); 1096 this.read += 3; 1097 return rval; 1098}; 1099 1100/** 1101 * Gets a uint32 from this buffer in big-endian order and advances the read 1102 * pointer by 4. 1103 * 1104 * @return the word. 1105 */ 1106util.DataBuffer.prototype.getInt32 = function() { 1107 var rval = this.data.getInt32(this.read); 1108 this.read += 4; 1109 return rval; 1110}; 1111 1112/** 1113 * Gets a uint16 from this buffer in little-endian order and advances the read 1114 * pointer by 2. 1115 * 1116 * @return the uint16. 1117 */ 1118util.DataBuffer.prototype.getInt16Le = function() { 1119 var rval = this.data.getInt16(this.read, true); 1120 this.read += 2; 1121 return rval; 1122}; 1123 1124/** 1125 * Gets a uint24 from this buffer in little-endian order and advances the read 1126 * pointer by 3. 1127 * 1128 * @return the uint24. 1129 */ 1130util.DataBuffer.prototype.getInt24Le = function() { 1131 var rval = ( 1132 this.data.getInt8(this.read) ^ 1133 this.data.getInt16(this.read + 1, true) << 8); 1134 this.read += 3; 1135 return rval; 1136}; 1137 1138/** 1139 * Gets a uint32 from this buffer in little-endian order and advances the read 1140 * pointer by 4. 1141 * 1142 * @return the word. 1143 */ 1144util.DataBuffer.prototype.getInt32Le = function() { 1145 var rval = this.data.getInt32(this.read, true); 1146 this.read += 4; 1147 return rval; 1148}; 1149 1150/** 1151 * Gets an n-bit integer from this buffer in big-endian order and advances the 1152 * read pointer by n/8. 1153 * 1154 * @param n the number of bits in the integer. 1155 * 1156 * @return the integer. 1157 */ 1158util.DataBuffer.prototype.getInt = function(n) { 1159 var rval = 0; 1160 do { 1161 rval = (rval << 8) + this.data.getInt8(this.read++); 1162 n -= 8; 1163 } while(n > 0); 1164 return rval; 1165}; 1166 1167/** 1168 * Gets a signed n-bit integer from this buffer in big-endian order, using 1169 * two's complement, and advances the read pointer by n/8. 1170 * 1171 * @param n the number of bits in the integer. 1172 * 1173 * @return the integer. 1174 */ 1175util.DataBuffer.prototype.getSignedInt = function(n) { 1176 var x = this.getInt(n); 1177 var max = 2 << (n - 2); 1178 if(x >= max) { 1179 x -= max << 1; 1180 } 1181 return x; 1182}; 1183 1184/** 1185 * Reads bytes out into a UTF-8 string and clears them from the buffer. 1186 * 1187 * @param count the number of bytes to read, undefined or null for all. 1188 * 1189 * @return a UTF-8 string of bytes. 1190 */ 1191util.DataBuffer.prototype.getBytes = function(count) { 1192 // TODO: deprecate this method, it is poorly named and 1193 // this.toString('binary') replaces it 1194 // add a toTypedArray()/toArrayBuffer() function 1195 var rval; 1196 if(count) { 1197 // read count bytes 1198 count = Math.min(this.length(), count); 1199 rval = this.data.slice(this.read, this.read + count); 1200 this.read += count; 1201 } else if(count === 0) { 1202 rval = ''; 1203 } else { 1204 // read all bytes, optimize to only copy when needed 1205 rval = (this.read === 0) ? this.data : this.data.slice(this.read); 1206 this.clear(); 1207 } 1208 return rval; 1209}; 1210 1211/** 1212 * Gets a UTF-8 encoded string of the bytes from this buffer without modifying 1213 * the read pointer. 1214 * 1215 * @param count the number of bytes to get, omit to get all. 1216 * 1217 * @return a string full of UTF-8 encoded characters. 1218 */ 1219util.DataBuffer.prototype.bytes = function(count) { 1220 // TODO: deprecate this method, it is poorly named, add "getString()" 1221 return (typeof(count) === 'undefined' ? 1222 this.data.slice(this.read) : 1223 this.data.slice(this.read, this.read + count)); 1224}; 1225 1226/** 1227 * Gets a byte at the given index without modifying the read pointer. 1228 * 1229 * @param i the byte index. 1230 * 1231 * @return the byte. 1232 */ 1233util.DataBuffer.prototype.at = function(i) { 1234 return this.data.getUint8(this.read + i); 1235}; 1236 1237/** 1238 * Puts a
1238byte at the given index without modifying the read pointer. 1239 * 1240 * @param i the byte index. 1241 * @param b the byte to put. 1242 * 1243 * @return this buffer. 1244 */ 1245util.DataBuffer.prototype.setAt = function(i, b) { 1246 this.data.setUint8(i, b); 1247 return this; 1248}; 1249 1250/** 1251 * Gets the last byte without modifying the read pointer. 1252 * 1253 * @return the last byte. 1254 */ 1255util.DataBuffer.prototype.last = function() { 1256 return this.data.getUint8(this.write - 1); 1257}; 1258 1259/** 1260 * Creates a copy of this buffer. 1261 * 1262 * @return the copy. 1263 */ 1264util.DataBuffer.prototype.copy = function() { 1265 return new util.DataBuffer(this); 1266}; 1267 1268/** 1269 * Compacts this buffer. 1270 * 1271 * @return this buffer. 1272 */ 1273util.DataBuffer.prototype.compact = function() { 1274 if(this.read > 0) { 1275 var src = new Uint8Array(this.data.buffer, this.read); 1276 var dst = new Uint8Array(src.byteLength); 1277 dst.set(src); 1278 this.data = new DataView(dst); 1279 this.write -= this.read; 1280 this.read = 0; 1281 } 1282 return this; 1283}; 1284 1285/** 1286 * Clears this buffer. 1287 * 1288 * @return this buffer. 1289 */ 1290util.DataBuffer.prototype.clear = function() { 1291 this.data = new DataView(new ArrayBuffer(0)); 1292 this.read = this.write = 0; 1293 return this; 1294}; 1295 1296/** 1297 * Shortens this buffer by triming bytes off of the end of this buffer. 1298 * 1299 * @param count the number of bytes to trim off. 1300 * 1301 * @return this buffer. 1302 */ 1303util.DataBuffer.prototype.truncate = function(count) { 1304 this.write = Math.max(0, this.length() - count); 1305 this.read = Math.min(this.read, this.write); 1306 return this; 1307}; 1308 1309/** 1310 * Converts this buffer to a hexadecimal string. 1311 * 1312 * @return a hexadecimal string. 1313 */ 1314util.DataBuffer.prototype.toHex = function() { 1315 var rval = ''; 1316 for(var i = this.read; i < this.data.byteLength; ++i) { 1317 var b = this.data.getUint8(i); 1318 if(b < 16) { 1319 rval += '0'; 1320 } 1321 rval += b.toString(16); 1322 } 1323 return rval; 1324}; 1325 1326/** 1327 * Converts this buffer to a string, using the given encoding. If no 1328 * encoding is given, 'utf8' (UTF-8) is used. 1329 * 1330 * @param [encoding] the encoding to use: 'binary', 'utf8', 'utf16', 'hex', 1331 * 'base64' (default: 'utf8'). 1332 * 1333 * @return a string representation of the bytes in this buffer. 1334 */ 1335util.DataBuffer.prototype.toString = function(encoding) { 1336 var view = new Uint8Array(this.data, this.read, this.length()); 1337 encoding = encoding || 'utf8'; 1338 1339 // encode to string 1340 if(encoding === 'binary' || encoding === 'raw') { 1341 return util.binary.raw.encode(view); 1342 } 1343 if(encoding === 'hex') { 1344 return util.binary.hex.encode(view); 1345 } 1346 if(encoding === 'base64') { 1347 return util.binary.base64.encode(view); 1348 } 1349 1350 // decode to text 1351 if(encoding === 'utf8') { 1352 return util.text.utf8.decode(view); 1353 } 1354 if(encoding === 'utf16') { 1355 return util.text.utf16.decode(view); 1356 } 1357 1358 throw new Error('Invalid encoding: ' + encoding); 1359}; 1360 1361/** End Buffer w/UInt8Array backing */ 1362 1363 1364/** 1365 * Creates a buffer that stores bytes. A value may be given to put into the 1366 * buffer that is either a string of bytes or a UTF-16 string that will 1367 * be encoded using UTF-8 (to do the latter, specify 'utf8' as the encoding). 1368 * 1369 * @param [input] the bytes to wrap (as a string) or a UTF-16 string to encode 1370 * as UTF-8. 1371 * @param [encoding] (default: 'raw', other: 'utf8'). 1372 */ 1373util.createBuffer = function(input, encoding) { 1374 // TODO: deprecate, use new ByteBuffer() instead 1375 encoding = encoding || 'raw'; 1376 if(input !== undefined && encoding === 'utf8') { 1377 input = util.encodeUtf8(input); 1378 } 1379 return new util.ByteBuffer(input); 1380}; 1381 1382/** 1383 * Fills a string with a particular value. If you want the string to be a byte 1384 * string, pass in String.fromCharCode(theByte). 1385 * 1386 * @param c the character to fill the string with, use String.fromCharCode 1387 * to fill the string with a byte value. 1388 * @param n the number of characters of value c to fill with. 1389 * 1390 * @return the filled string. 1391 */ 1392util.fillString = function(c, n) { 1393 var s = ''; 1394 while(n > 0) { 1395 if(n & 1) { 1396 s += c; 1397 } 1398 n >>>= 1; 1399 if(n > 0) { 1400 c += c; 1401 } 1402 } 1403 return s; 1404}; 1405 1406/** 1407 * Performs a per byte XOR between two byte strings and returns the result as a 1408 * string of bytes. 1409 * 1410 * @param s1 first string of bytes. 1411 * @param s2 second string of bytes. 1412 * @param n the number of bytes to XOR. 1413 * 1414 * @return the XOR'd result. 1415 */ 1416util.xorBytes = function(s1, s2, n) { 1417 var s3 = ''; 1418 var b = ''; 1419 var t = ''; 1420 var i = 0; 1421 var c = 0; 1422 for(; n > 0; --n, ++i) { 1423 b = s1.charCodeAt(i) ^ s2.charCodeAt(i); 1424 if(c >= 10) { 1425 s3 += t; 1426 t = ''; 1427 c = 0; 1428 } 1429 t += String.fromCharCode(b); 1430 ++c; 1431 } 1432 s3 += t; 1433 return s3; 1434}; 1435 1436/** 1437 * Converts a hex string into a 'binary' encoded string of bytes. 1438 * 1439 * @param hex the hexadecimal string to convert. 1440 * 1441 * @return the binary-encoded string of bytes. 1442 */ 1443util.hexToBytes = function(hex) { 1444 // TODO: deprecate: "Deprecated. Use util.binary.hex.decode instead." 1445 var rval = ''; 1446 var i = 0; 1447 if(hex.length & 1 == 1) { 1448 // odd number of characters, convert first character alone 1449 i = 1; 1450 rval += String.fromCharCode(parseInt(hex[0], 16)); 1451 } 1452 // convert 2 characters (1 byte) at a time 1453 for(; i < hex.length; i += 2) { 1454 rval += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); 1455 } 1456 return rval; 1457}; 1458 1459/** 1460 * Converts a 'binary' encoded string of bytes to hex. 1461 * 1462 * @param bytes the byte string to convert. 1463 * 1464 * @return the string of hexadecimal characters. 1465 */ 1466util.bytesToHex = function(bytes) { 1467 // TODO: deprecate: "Deprecated. Use util.binary.hex.encode instead." 1468 return util.createBuffer(bytes).toHex(); 1469}; 1470 1471/** 1472 * Converts an 32-bit integer to 4-big-endian byte string. 1473 * 1474 * @param i the integer. 1475 * 1476 * @return the byte string. 1477 */ 1478util.int32ToBytes = function(i) { 1479 return ( 1480 String.fromCharCode(i >> 24 & 0xFF) + 1481 String.fromCharCode(i >> 16 & 0xFF) + 1482 String.fromCharCode(i >> 8 & 0xFF) + 1483 String.fromCharCode(i & 0xFF)); 1484}; 1485 1486// base64 characters, reverse mapping 1487var _base64 = 1488 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
1488+/='; 1489var _base64Idx = [ 1490/*43 -43 = 0*/ 1491/*'+', 1, 2, 3,'/' */ 1492 62, -1, -1, -1, 63, 1493 1494/*'0','1','2','3','4','5','6','7','8','9' */ 1495 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 1496 1497/*15, 16, 17,'=', 19, 20, 21 */ 1498 -1, -1, -1, 64, -1, -1, -1, 1499 1500/*65 - 43 = 22*/ 1501/*'A','B','C','D','E','F','G','H','I','J','K','L','M', */ 1502 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1503 1504/*'N','O','P','Q','R','S','T','U','V','W','X','Y','Z' */ 1505 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 1506 1507/*91 - 43 = 48 */ 1508/*48, 49, 50, 51, 52, 53 */ 1509 -1, -1, -1, -1, -1, -1, 1510 1511/*97 - 43 = 54*/ 1512/*'a','b','c','d','e','f','g','h','i','j','k','l','m' */ 1513 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 1514 1515/*'n','o','p','q','r','s','t','u','v','w','x','y','z' */ 1516 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 1517]; 1518 1519/** 1520 * Base64 encodes a 'binary' encoded string of bytes. 1521 * 1522 * @param input the binary encoded string of bytes to base64-encode. 1523 * @param maxline the maximum number of encoded characters per line to use, 1524 * defaults to none. 1525 * 1526 * @return the base64-encoded output. 1527 */ 1528util.encode64 = function(input, maxline) { 1529 // TODO: deprecate: "Deprecated. Use util.binary.base64.encode instead." 1530 var line = ''; 1531 var output = ''; 1532 var chr1, chr2, chr3; 1533 var i = 0; 1534 while(i < input.length) { 1535 chr1 = input.charCodeAt(i++); 1536 chr2 = input.charCodeAt(i++); 1537 chr3 = input.charCodeAt(i++); 1538 1539 // encode 4 character group 1540 line += _base64.charAt(chr1 >> 2); 1541 line += _base64.charAt(((chr1 & 3) << 4) | (chr2 >> 4)); 1542 if(isNaN(chr2)) { 1543 line += '=='; 1544 } else { 1545 line += _base64.charAt(((chr2 & 15) << 2) | (chr3 >> 6)); 1546 line += isNaN(chr3) ? '=' : _base64.charAt(chr3 & 63); 1547 } 1548 1549 if(maxline && line.length > maxline) { 1550 output += line.substr(0, maxline) + '\r\n'; 1551 line = line.substr(maxline); 1552 } 1553 } 1554 output += line; 1555 return output; 1556}; 1557 1558/** 1559 * Base64 decodes a string into a 'binary' encoded string of bytes. 1560 * 1561 * @param input the base64-encoded input. 1562 * 1563 * @return the binary encoded string. 1564 */ 1565util.decode64 = function(input) { 1566 // TODO: deprecate: "Deprecated. Use util.binary.base64.decode instead." 1567 1568 // remove all non-base64 characters 1569 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); 1570 1571 var output = ''; 1572 var enc1, enc2, enc3, enc4; 1573 var i = 0; 1574 1575 while(i < input.length) { 1576 enc1 = _base64Idx[input.charCodeAt(i++) - 43]; 1577 enc2 = _base64Idx[input.charCodeAt(i++) - 43]; 1578 enc3 = _base64Idx[input.charCodeAt(i++) - 43]; 1579 enc4 = _base64Idx[input.charCodeAt(i++) - 43]; 1580 1581 output += String.fromCharCode((enc1 << 2) | (enc2 >> 4)); 1582 if(enc3 !== 64) { 1583 // decoded at least 2 bytes 1584 output += String.fromCharCode(((enc2 & 15) << 4) | (enc3 >> 2)); 1585 if(enc4 !== 64) { 1586 // decoded 3 bytes 1587 output += String.fromCharCode(((enc3 & 3) << 6) | enc4); 1588 } 1589 } 1590 } 1591 1592 return output; 1593}; 1594 1595/** 1596 * UTF-8 encodes the given UTF-16 encoded string (a standard JavaScript 1597 * string). Non-ASCII characters will be encoded as multiple bytes according 1598 * to UTF-8. 1599 * 1600 * @param str the string to encode. 1601 * 1602 * @return the UTF-8 encoded string. 1603 */ 1604util.encodeUtf8 = function(str) { 1605 return unescape(encodeURIComponent(str)); 1606}; 1607 1608/** 1609 * Decodes a UTF-8 encoded string into a UTF-16 string. 1610 * 1611 * @param str the string to decode. 1612 * 1613 * @return the UTF-16 encoded string (standard JavaScript string). 1614 */ 1615util.decodeUtf8 = function(str) { 1616 return decodeURIComponent(escape(str)); 1617}; 1618 1619// binary encoding/decoding tools 1620// FIXME: Experimental. Do not use yet. 1621util.binary = { 1622 raw: {}, 1623 hex: {}, 1624 base64: {} 1625}; 1626 1627/** 1628 * Encodes a Uint8Array as a binary-encoded string. This encoding uses 1629 * a value between 0 and 255 for each character. 1630 * 1631 * @param bytes the Uint8Array to encode. 1632 * 1633 * @return the binary-encoded string. 1634 */ 1635util.binary.raw.encode = function(bytes) { 1636 return String.fromCharCode.apply(null, bytes); 1637}; 1638 1639/** 1640 * Decodes a binary-encoded string to a Uint8Array. This encoding uses 1641 * a value between 0 and 255 for each character. 1642 * 1643 * @param str the binary-encoded string to decode. 1644 * @param [output] an optional Uint8Array to write the output to; if it 1645 * is too small, an exception will be thrown. 1646 * @param [offset] the start offset for writing to the output (default: 0). 1647 * 1648 * @return the Uint8Array or the number of bytes written if output was given. 1649 */ 1650util.binary.raw.decode = function(str, output, offset) { 1651 var out = output; 1652 if(!out) { 1653 out = new Uint8Array(str.length); 1654 } 1655 offset = offset || 0; 1656 var j = offset; 1657 for(var i = 0; i < str.length; ++i) { 1658 out[j++] = str.charCodeAt(i); 1659 } 1660 return output ? (j - offset) : out; 1661}; 1662 1663/** 1664 * Encodes a 'binary' string, ArrayBuffer, DataView, TypedArray, or 1665 * ByteBuffer as a string of hexadecimal characters. 1666 * 1667 * @param bytes the bytes to convert. 1668 * 1669 * @return the string of hexadecimal characters. 1670 */ 1671util.binary.hex.encode = util.bytesToHex; 1672 1673/** 1674 * Decodes a hex-encoded string to a Uint8Array. 1675 * 1676 * @param hex the hexadecimal string to convert. 1677 * @param [output] an optional Uint8Array to write the output to; if it 1678 * is too small, an exception will be thrown. 1679 * @param [offset] the start offset for writing to the output (default: 0). 1680 * 1681 * @return the Uint8Array or the number of bytes written if output was given. 1682 */ 1683util.binary.hex.decode = function(hex, output, offset) { 1684 var out = output; 1685 if(!out) { 1686 out = new Uint8Array(Math.ceil(hex.length / 2)); 1687 } 1688 offset = offset || 0; 1689 var i = 0, j = offset; 1690 if(hex.length & 1) { 1691 // odd number of characters, convert first character alone 1692 i = 1; 1693 out[j++] = parseInt(hex[0], 16); 1694 } 1695 // convert 2 characters (1 byte) at a time 1696 for(; i < hex.length; i += 2) { 1697 out[j++] = parseInt(hex.substr(i, 2), 16); 1698 } 1699 return output ? (j - offset) : out; 1700}; 1701 1702/** 1703 * Base64-encodes a Uint8Array. 1704 * 1705 * @param input the Uint8Array to encode. 1706 * @param maxline the maximum number of encoded characters per line to use, 1707 * defaults to none. 1708 * 1709 * @return the base64-encoded output string. 1710 */ 1711util.binary.base64.encode = function(input, maxline) { 1712 var line = ''; 1713 var output = ''; 1714 var chr1, chr2, chr3; 1715 var i = 0; 1716 while(i < input.byteLength) {
1717 chr1 = input[i++]; 1718 chr2 = input[i++]; 1719 chr3 = input[i++]; 1720 1721 // encode 4 character group 1722 line += _base64.charAt(chr1 >> 2); 1723 line += _base64.charAt(((chr1 & 3) << 4) | (chr2 >> 4)); 1724 if(isNaN(chr2)) { 1725 line += '=='; 1726 } else { 1727 line += _base64.charAt(((chr2 & 15) << 2) | (chr3 >> 6)); 1728 line += isNaN(chr3) ? '=' : _base64.charAt(chr3 & 63); 1729 } 1730 1731 if(maxline && line.length > maxline) { 1732 output += line.substr(0, maxline) + '\r\n'; 1733 line = line.substr(maxline); 1734 } 1735 } 1736 output += line; 1737 return output; 1738}; 1739 1740/** 1741 * Decodes a base64-encoded string to a Uint8Array. 1742 * 1743 * @param input the base64-encoded input string. 1744 * @param [output] an optional Uint8Array to write the output to; if it 1745 * is too small, an exception will be thrown. 1746 * @param [offset] the start offset for writing to the output (default: 0). 1747 * 1748 * @return the Uint8Array or the number of bytes written if output was given. 1749 */ 1750util.binary.base64.decode = function(input, output, offset) { 1751 var out = output; 1752 if(!out) { 1753 out = new Uint8Array(Math.ceil(input.length / 4) * 3); 1754 } 1755 1756 // remove all non-base64 characters 1757 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); 1758 1759 offset = offset || 0; 1760 var enc1, enc2, enc3, enc4; 1761 var i = 0, j = offset; 1762 1763 while(i < input.length) { 1764 enc1 = _base64Idx[input.charCodeAt(i++) - 43]; 1765 enc2 = _base64Idx[input.charCodeAt(i++) - 43]; 1766 enc3 = _base64Idx[input.charCodeAt(i++) - 43]; 1767 enc4 = _base64Idx[input.charCodeAt(i++) - 43]; 1768 1769 out[j++] = (enc1 << 2) | (enc2 >> 4); 1770 if(enc3 !== 64) { 1771 // decoded at least 2 bytes 1772 out[j++] = ((enc2 & 15) << 4) | (enc3 >> 2); 1773 if(enc4 !== 64) { 1774 // decoded 3 bytes 1775 out[j++] = ((enc3 & 3) << 6) | enc4; 1776 } 1777 } 1778 } 1779 1780 // make sure result is the exact decoded length 1781 return output ? 1782 (j - offset) : 1783 out.subarray(0, j); 1784}; 1785 1786// text encoding/decoding tools 1787// FIXME: Experimental. Do not use yet. 1788util.text = { 1789 utf8: {}, 1790 utf16: {} 1791}; 1792 1793/** 1794 * Encodes the given string as UTF-8 in a Uint8Array. 1795 * 1796 * @param str the string to encode. 1797 * @param [output] an optional Uint8Array to write the output to; if it 1798 * is too small, an exception will be thrown. 1799 * @param [offset] the start offset for writing to the output (default: 0). 1800 * 1801 * @return the Uint8Array or the number of bytes written if output was given. 1802 */ 1803util.text.utf8.encode = function(str, output, offset) { 1804 str = util.encodeUtf8(str); 1805 var out = output; 1806 if(!out) { 1807 out = new Uint8Array(str.length); 1808 } 1809 offset = offset || 0; 1810 var j = offset; 1811 for(var i = 0; i < str.length; ++i) { 1812 out[j++] = str.charCodeAt(i); 1813 } 1814 return output ? (j - offset) : out; 1815}; 1816 1817/** 1818 * Decodes the UTF-8 contents from a Uint8Array. 1819 * 1820 * @param bytes the Uint8Array to decode. 1821 * 1822 * @return the resulting string. 1823 */ 1824util.text.utf8.decode = function(bytes) { 1825 return util.decodeUtf8(String.fromCharCode.apply(null, bytes)); 1826}; 1827 1828/** 1829 * Encodes the given string as UTF-16 in a Uint8Array. 1830 * 1831 * @param str the string to encode. 1832 * @param [output] an optional Uint8Array to write the output to; if it 1833 * is too small, an exception will be thrown. 1834 * @param [offset] the start offset for writing to the output (default: 0). 1835 * 1836 * @return the Uint8Array or the number of bytes written if output was given. 1837 */ 1838util.text.utf16.encode = function(str, output, offset) { 1839 var out = output; 1840 if(!out) { 1841 out = new Uint8Array(str.length * 2); 1842 } 1843 var view = new Uint16Array(out.buffer); 1844 offset = offset || 0; 1845 var j = offset; 1846 var k = offset; 1847 for(var i = 0; i < str.length; ++i) { 1848 view[k++] = str.charCodeAt(i); 1849 j += 2; 1850 } 1851 return output ? (j - offset) : out; 1852}; 1853 1854/** 1855 * Decodes the UTF-16 contents from a Uint8Array. 1856 * 1857 * @param bytes the Uint8Array to decode. 1858 * 1859 * @return the resulting string. 1860 */ 1861util.text.utf16.decode = function(bytes) { 1862 return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer)); 1863}; 1864 1865/** 1866 * Deflates the given data using a flash interface. 1867 * 1868 * @param api the flash interface. 1869 * @param bytes the data. 1870 * @param raw true to return only raw deflate data, false to include zlib 1871 * header and trailer. 1872 * 1873 * @return the deflated data as a string. 1874 */ 1875util.deflate = function(api, bytes, raw) { 1876 bytes = util.decode64(api.deflate(util.encode64(bytes)).rval); 1877 1878 // strip zlib header and trailer if necessary 1879 if(raw) { 1880 // zlib header is 2 bytes (CMF,FLG) where FLG indicates that 1881 // there is a 4-byte DICT (alder-32) block before the data if 1882 // its 5th bit is set 1883 var start = 2;
1884 var flg = bytes.charCodeAt(1); 1885 if(flg & 0x20) { 1886 start = 6; 1887 } 1888 // zlib trailer is 4 bytes of adler-32 1889 bytes = bytes.substring(start, bytes.length - 4); 1890 } 1891 1892 return bytes; 1893}; 1894 1895/** 1896 * Inflates the given data using a flash interface. 1897 * 1898 * @param api the flash interface. 1899 * @param bytes the data. 1900 * @param raw true if the incoming data has no zlib header or trailer and is 1901 * raw DEFLATE data. 1902 * 1903 * @return the inflated data as a string, null on error. 1904 */ 1905util.inflate = function(api, bytes, raw) { 1906 // TODO: add zlib header and trailer if necessary/possible 1907 var rval = api.inflate(util.encode64(bytes)).rval; 1908 return (rval === null) ? null : util.decode64(rval); 1909}; 1910 1911/** 1912 * Sets a storage object. 1913 * 1914 * @param api the storage interface. 1915 * @param id the storage ID to use. 1916 * @param obj the storage object, null to remove. 1917 */ 1918var _setStorageObject = function(api, id, obj) { 1919 if(!api) { 1920 throw new Error('WebStorage not available.'); 1921 } 1922 1923 var rval; 1924 if(obj === null) { 1925 rval = api.removeItem(id); 1926 } else { 1927 // json-encode and base64-encode object 1928 obj = util.encode64(JSON.stringify(obj)); 1929 rval = api.setItem(id, obj); 1930 } 1931 1932 // handle potential flash error 1933 if(typeof(rval) !== 'undefined' && rval.rval !== true) { 1934 var error = new Error(rval.error.message); 1935 error.id = rval.error.id; 1936 error.name = rval.error.name; 1937 throw error; 1938 } 1939}; 1940 1941/** 1942 * Gets a storage object. 1943 * 1944 * @param api the storage interface. 1945 * @param id the storage ID to use. 1946 * 1947 * @return the storage object entry or null if none exists. 1948 */ 1949var _getStorageObject = function(api, id) { 1950 if(!api) { 1951 throw new Error('WebStorage not available.'); 1952 } 1953 1954 // get the existing entry 1955 var rval = api.getItem(id); 1956 1957 /* Note: We check api.init because we can't do (api == localStorage) 1958 on IE because of "Class doesn't support Automation" exception. Only 1959 the flash api has an init method so this works too, but we need a 1960 better solution in the future. */ 1961 1962 // flash returns item wrapped in an object, handle special case 1963 if(api.init) { 1964 if(rval.rval === null) { 1965 if(rval.error) { 1966 var error = new Error(rval.error.message); 1967 error.id = rval.error.id; 1968 error.name = rval.error.name; 1969 throw error; 1970 } 1971 // no error, but also no item 1972 rval = null; 1973 } else { 1974 rval = rval.rval; 1975 } 1976 } 1977 1978 // handle decoding 1979 if(rval !== null) { 1980 // base64-decode and json-decode data 1981 rval = JSON.parse(util.decode64(rval)); 1982 } 1983 1984 return rval; 1985}; 1986 1987/** 1988 * Stores an item in local storage. 1989 * 1990 * @param api the storage interface. 1991 * @param id the storage ID to use. 1992 * @param key the key for the item. 1993 * @param data the data for the item (any javascript object/primitive). 1994 */ 1995var _setItem = function(api, id, key, data) { 1996 // get storage object 1997 var obj = _getStorageObject(api, id); 1998 if(obj === null) { 1999 // create a new storage object 2000 obj = {}; 2001 } 2002 // update key 2003 obj[key] = data; 2004 2005 // set storage object 2006 _setStorageObject(api, id, obj); 2007}; 2008 2009/** 2010 * Gets an item from local storage. 2011 * 2012 * @param api the storage interface. 2013 * @param id the storage ID to use. 2014 * @param key the key for the item. 2015 * 2016 * @return the item. 2017 */ 2018var _getItem = function(api, id, key) { 2019 // get storage object 2020 var rval = _getStorageObject(api, id); 2021 if(rval !== null) { 2022 // return data at key 2023 rval = (key in rval) ? rval[key] : null; 2024 } 2025 2026 return rval; 2027}; 2028 2029/** 2030 * Removes an item from local storage. 2031 * 2032 * @param api the storage interface. 2033 * @param id the storage ID to use. 2034 * @param key the key for the item. 2035 */ 2036var _removeItem = function(api, id, key) { 2037 // get storage object 2038 var obj = _getStorageObject(api, id); 2039 if(obj !== null && key in obj) { 2040 // remove key 2041 delete obj[key]; 2042 2043 // see if entry has no keys remaining 2044 var empty = true; 2045 for(var prop in obj) { 2046 empty = false; 2047 break; 2048 } 2049 if(empty) { 2050 // remove entry entirely if no keys are left 2051 obj = null; 2052 } 2053 2054 // set storage object 2055 _setStorageObject(api, id, obj); 2056 } 2057}; 2058 2059/** 2060 * Clears the local disk storage identified by the given ID. 2061 * 2062 * @param api the storage interface. 2063 * @param id the storage ID to use. 2064 */ 2065var _clearItems = function(api, id) { 2066 _setStorageObject(api, id, null); 2067}; 2068 2069/** 2070 * Calls a storage function. 2071 * 2072 * @param func the function to call. 2073 * @param args the arguments for the function. 2074 * @param location the location argument. 2075 * 2076 * @return the return value from the function. 2077 */ 2078var _callStorageFunction = function(func, args, location) { 2079 var rval = null; 2080 2081 // default storage types 2082 if(typeof(location) === 'undefined') { 2083 location = ['web', 'flash']; 2084 } 2085 2086 // apply storage types in order of preference 2087 var type; 2088 var done = false;
2089 var exception = null; 2090 for(var idx in location) { 2091 type = location[idx]; 2092 try { 2093 if(type === 'flash' || type === 'both') { 2094 if(args[0] === null) { 2095 throw new Error('Flash local storage not available.'); 2096 } 2097 rval = func.apply(this, args); 2098 done = (type === 'flash'); 2099 } 2100 if(type === 'web' || type === 'both') { 2101 args[0] = localStorage; 2102 rval = func.apply(this, args); 2103 done = true; 2104 } 2105 } catch(ex) { 2106 exception = ex; 2107 } 2108 if(done) { 2109 break; 2110 } 2111 } 2112 2113 if(!done) { 2114 throw exception; 2115 } 2116 2117 return rval; 2118}; 2119 2120/** 2121 * Stores an item on local disk. 2122 * 2123 * The available types of local storage include 'flash', 'web', and 'both'. 2124 * 2125 * The type 'flash' refers to flash local storage (SharedObject). In order 2126 * to use flash local storage, the 'api' parameter must be valid. The type 2127 * 'web' refers to WebStorage, if supported by the browser. The type 'both' 2128 * refers to storing using both 'flash' and 'web', not just one or the 2129 * other. 2130 * 2131 * The location array should list the storage types to use in order of 2132 * preference: 2133 * 2134 * ['flash']: flash only storage 2135 * ['web']: web only storage 2136 * ['both']: try to store in both 2137 * ['flash','web']: store in flash first, but if not available, 'web' 2138 * ['web','flash']: store in web first, but if not available, 'flash' 2139 * 2140 * The location array defaults to: ['web', 'flash'] 2141 * 2142 * @param api the flash interface, null to use only WebStorage. 2143 * @param id the storage ID to use. 2144 * @param key the key for the item. 2145 * @param data the data for the item (any javascript object/primitive). 2146 * @param location an array with the preferred types of storage to use. 2147 */ 2148util.setItem = function(api, id, key, data, location) { 2149 _callStorageFunction(_setItem, arguments, location); 2150}; 2151 2152/** 2153 * Gets an item on local disk. 2154 * 2155 * Set setItem() for details on storage types. 2156 * 2157 * @param api the flash interface, null to use only WebStorage. 2158 * @param id the storage ID to use. 2159 * @param key the key for the item. 2160 * @param location an array with the preferred types of storage to use. 2161 * 2162 * @return the item. 2163 */ 2164util.getItem = function(api, id, key, location) { 2165 return _callStorageFunction(_getItem, arguments, location); 2166}; 2167 2168/** 2169 * Removes an item on local disk. 2170 * 2171 * Set setItem() for details on storage types. 2172 * 2173 * @param api the flash interface. 2174 * @param id the storage ID to use. 2175 * @param key the key for the item. 2176 * @param location an array with the preferred types of storage to use. 2177 */ 2178util.removeItem = function(api, id, key, location) { 2179 _callStorageFunction(_removeItem, arguments, location); 2180}; 2181 2182/** 2183 * Clears the local disk storage identified by the given ID. 2184 * 2185 * Set setItem() for details on storage types. 2186 * 2187 * @param api the flash interface if flash is available. 2188 * @param id the storage ID to use. 2189 * @param location an array with the preferred types of storage to use. 2190 */ 2191util.clearItems = function(api, id, location) { 2192 _callStorageFunction(_clearItems, arguments, location); 2193}; 2194 2195/** 2196 * Parses the scheme, host, and port from an http(s) url. 2197 * 2198 * @param str the url string. 2199 * 2200 * @return the parsed url object or null if the url is invalid. 2201 */ 2202util.parseUrl = function(str) { 2203 // FIXME: this regex looks a bit broken 2204 var regex = /^(https?):\/\/([^:&^\/]*):?(\d*)(.*)$/g; 2205 regex.lastIndex = 0; 2206 var m = regex.exec(str); 2207 var url = (m === null) ? null : { 2208 full: str, 2209 scheme: m[1], 2210 host: m[2], 2211 port: m[3], 2212 path: m[4] 2213 }; 2214 if(url) { 2215 url.fullHost = url.host; 2216 if(url.port) { 2217 if(url.port !== 80 && url.scheme === 'http') { 2218 url.fullHost += ':' + url.port; 2219 } else if(url.port !== 443 && url.scheme === 'https') { 2220 url.fullHost += ':' + url.port; 2221 } 2222 } else if(url.scheme === 'http') { 2223 url.port = 80; 2224 } else if(url.scheme === 'https') { 2225 url.port = 443; 2226 } 2227 url.full = url.scheme + '://' + url.fullHost; 2228 } 2229 return url; 2230}; 2231 2232/* Storage for query variables */ 2233var _queryVariables = null; 2234 2235/** 2236 * Returns the window location query variables. Query is parsed on the first 2237 * call and the same object is returned on subsequent calls. The mapping 2238 * is from keys to an array of values. Parameters without values will have 2239 * an object key set but no value added to the value array. Values are 2240 * unescaped. 2241 * 2242 * ...?k1=v1&k2=v2: 2243 * { 2244 * "k1": ["v1"], 2245 * "k2": ["v2"] 2246 * } 2247 * 2248 * ...?k1=v1&k1=v2: 2249 * { 2250 * "k1": ["v1", "v2"] 2251 * } 2252 * 2253 * ...?k1=v1&k2: 2254 * { 2255 * "k1": ["v1"], 2256 * "k2": [] 2257 * } 2258 * 2259 * ...?k1=v1&k1: 2260 * { 2261 * "k1": ["v1"] 2262 * } 2263 * 2264 * ...?k1&k1: 2265 * { 2266 * "k1": [] 2267 * } 2268 * 2269 * @param query the query string to parse (optional, default to cached 2270 * results from parsing window location search query). 2271 * 2272 * @return object mapping keys to variables. 2273 */ 2274util.getQueryVariables = function(query) { 2275 var parse = function(q) { 2276 var rval = {}; 2277 var kvpairs = q.split('&'); 2278 for(var i = 0; i < kvpairs.length; i++) { 2279 var pos = kvpairs[i].indexOf('='); 2280 var key; 2281 var val; 2282 if(pos > 0) { 2283 key = kvpairs[i].substring(0, pos); 2284 val = kvpairs[i].substring(pos + 1); 2285 } else { 2286 key = kvpairs[i]; 2287 val = null; 2288 } 2289 if(!(key in rval)) { 2290 rval[key] = []; 2291 } 2292 // disallow overriding object prototype keys 2293 if(!(key in Object.prototype) && val !== null) { 2294 rval[key].push(unescape(val)); 2295 } 2296 } 2297 return rval; 2298 }; 2299 2300 var rval; 2301 if(typeof(query) === 'undefined') { 2302 // set cached variables if needed 2303 if(_queryVariables === null) { 2304 if(typeof(window) !== 'undefined' && window.location && window.location.search) { 2305 // parse window search query 2306 _queryVariables = parse(window.location.search.substring(1)); 2307 } else { 2308 // no query variables available 2309 _queryVariables = {}; 2310 } 2311 } 2312 rval = _queryVariables; 2313 } else { 2314 // parse given query 2315 rval = parse(query); 2316 } 2317 return rval; 2318}; 2319 2320/** 2321 * Parses a fragment into a path and query. This method will take a URI 2322 * fragment and break it up as if it were the main URI. For example: 2323 * /bar/baz?a=1&b=2 2324 * results in: 2325 * { 2326 * path: ["bar", "baz"], 2327 * query: {"k1": ["v1"], "k2": ["v2"]} 2328 * } 2329 * 2330 * @return object with a path array and query object. 2331 */ 2332util.parseFragment = function(fragment) { 2333 // default to whole fragment 2334 var fp = fragment; 2335 var fq = ''; 2336 // split into path and query if possible at the first '?' 2337 var pos = fragment.indexOf('?'); 2338 if(pos > 0) { 2339 fp = fragment.substring(0, pos); 2340 fq = fragment.substring(pos + 1); 2341 } 2342 // split path based on '/' and ignore first element if empty 2343 var path = fp.split('/'); 2344 if(path.length > 0 && path[0] === '') { 2345 path.shift(); 2346 } 2347 // convert query into object 2348 var query = (fq === '') ? {} : util.getQueryVariables(fq); 2349 2350 return { 2351 pathString: fp, 2352 queryString: fq, 2353 path: path, 2354 query: query 2355 }; 2356}; 2357 2358/** 2359 * Makes a request out of a URI-like request string. This is intended to 2360 * be used where a fragment id (after a URI '#') is parsed as a URI with 2361 * path and query parts. The string should have a path beginning and 2362 * delimited by '/' and optional query parameters following a '?'. The 2363 * query should be a standard URL set of key value pairs delimited by 2364 * '&'. For backwards compatibility the initial '/' on the path is not 2365 * required. The request object has the following API, (fully described 2366 * in the method code): 2367 * { 2368 * path: <the path string part>. 2369 * query: <the query string part>, 2370 * getPath(i): get part or all of the split path array, 2371 * getQuery(k, i): get part or all of a query key array, 2372 * getQueryLast(k, _default): get last element of a query key array. 2373 * } 2374 * 2375 * @return object with request parameters. 2376 */ 2377util.makeRequest = function(reqString) { 2378 var frag = util.parseFragment(reqString); 2379 var req = { 2380 // full path string 2381 path: frag.pathString, 2382 // full query string 2383 query: frag.queryString, 2384 /** 2385 * Get path or element in path. 2386 * 2387 * @param i optional path index. 2388 * 2389 * @return path or part of path if i provided. 2390 */ 2391 getPath: function(i) { 2392 return (typeof(i) === 'undefined') ? frag.path : frag.path[i]; 2393 }, 2394 /** 2395 * Get query, values for a key, or value for a key index. 2396 * 2397 * @param k optional query key. 2398 * @param i optional query key index. 2399 * 2400 * @return query, values for a key, or value for a key index. 2401 */ 2402 getQuery: function(k, i) { 2403 var rval; 2404 if(typeof(k) === 'undefined') { 2405 rval = frag.query; 2406 } else { 2407 rval = frag.query[k]; 2408 if(rval && typeof(i) !== 'undefined') { 2409 rval = rval[i]; 2410 } 2411 } 2412 return rval; 2413 }, 2414 getQueryLast: function(k, _default) { 2415 var rval; 2416 var vals = req.getQuery(k); 2417 if(vals) { 2418 rval = vals[vals.length - 1]; 2419 } else { 2420 rval = _default; 2421 } 2422 return rval; 2423 } 2424 }; 2425 return req; 2426}; 2427 2428/** 2429 * Makes a URI out of a path, an object with query parameters, and a 2430 * fragment. Uses jQuery.param() internally for query string creation. 2431 * If the path is an array, it will be joined with '/'. 2432 *
2433 * @param path string path or array of strings. 2434 * @param query object with query parameters. (optional) 2435 * @param fragment fragment string. (optional) 2436 * 2437 * @return string object with request parameters. 2438 */ 2439util.makeLink = function(path, query, fragment) { 2440 // join path parts if needed 2441 path = jQuery.isArray(path) ? path.join('/') : path; 2442 2443 var qstr = jQuery.param(query || {}); 2444 fragment = fragment || ''; 2445 return path + 2446 ((qstr.length > 0) ? ('?' + qstr) : '') + 2447 ((fragment.length > 0) ? ('#' + fragment) : ''); 2448}; 2449 2450/** 2451 * Follows a path of keys deep into an object hierarchy and set a value. 2452 * If a key does not exist or it's value is not an object, create an 2453 * object in it's place. This can be destructive to a object tree if 2454 * leaf nodes are given as non-final path keys. 2455 * Used to avoid exceptions from missing parts of the path. 2456 * 2457 * @param object the starting object. 2458 * @param keys an array of string keys. 2459 * @param value the value to set. 2460 */ 2461util.setPath = function(object, keys, value) { 2462 // need to start at an object 2463 if(typeof(object) === 'object' && object !== null) { 2464 var i = 0; 2465 var len = keys.length; 2466 while(i < len) { 2467 var next = keys[i++]; 2468 if(i == len) { 2469 // last 2470 object[next] = value; 2471 } else { 2472 // more 2473 var hasNext = (next in object); 2474 if(!hasNext || 2475 (hasNext && typeof(object[next]) !== 'object') || 2476 (hasNext && object[next] === null)) { 2477 object[next] = {}; 2478 } 2479 object = object[next]; 2480 } 2481 } 2482 } 2483}; 2484 2485/** 2486 * Follows a path of keys deep into an object hierarchy and return a value. 2487 * If a key does not exist, create an object in it's place. 2488 * Used to avoid exceptions from missing parts of the path. 2489 * 2490 * @param object the starting object. 2491 * @param keys an array of string keys. 2492 * @param _default value to return if path not found. 2493 * 2494 * @return the value at the path if found, else default if given, else 2495 * undefined. 2496 */ 2497util.getPath = function(object, keys, _default) { 2498 var i = 0; 2499 var len = keys.length; 2500 var hasNext = true; 2501 while(hasNext && i < len && 2502 typeof(object) === 'object' && object !== null) { 2503 var next = keys[i++]; 2504 hasNext = next in object; 2505 if(hasNext) { 2506 object = object[next]; 2507 } 2508 } 2509 return (hasNext ? object : _default); 2510}; 2511 2512/** 2513 * Follow a path of keys deep into an object hierarchy and delete the 2514 * last one. If a key does not exist, do nothing. 2515 * Used to avoid exceptions from missing parts of the path. 2516 * 2517 * @param object the starting object. 2518 * @param keys an array of string keys. 2519 */ 2520util.deletePath = function(object, keys) { 2521 // need to start at an object 2522 if(typeof(object) === 'object' && object !== null) { 2523 var i = 0; 2524 var len = keys.length; 2525 while(i < len) { 2526 var next = keys[i++]; 2527 if(i == len) { 2528 // last 2529 delete object[next]; 2530 } else { 2531 // more 2532 if(!(next in object) || 2533 (typeof(object[next]) !== 'object') || 2534 (object[next] === null)) { 2535 break; 2536 } 2537 object = object[next]; 2538 } 2539 } 2540 } 2541}; 2542 2543/** 2544 * Check if an object is empty. 2545 * 2546 * Taken from: 2547 * http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object-from-json/679937#679937 2548 * 2549 * @param object the object to check. 2550 */ 2551util.isEmpty = function(obj) { 2552 for(var prop in obj) { 2553 if(obj.hasOwnProperty(prop)) { 2554 return false; 2555 } 2556 } 2557 return true; 2558}; 2559 2560/** 2561 * Format with simple printf-style interpolation. 2562 * 2563 * %%: literal '%' 2564 * %s,%o: convert next argument into a string. 2565 * 2566 * @param format the string to format. 2567 * @param ... arguments to interpolate into the format string. 2568 */ 2569util.format = function(format) { 2570 var re = /%./g; 2571 // current match 2572 var match; 2573 // current part 2574 var part; 2575 // current arg index 2576 var argi = 0; 2577 // collected parts to recombine later 2578 var parts = []; 2579 // last index found 2580 var last = 0; 2581 // loop while matches remain 2582 while((match = re.exec(format))) { 2583 part = format.substring(last, re.lastIndex - 2); 2584 // don't add empty strings (ie, parts between %s%s) 2585 if(part.length > 0) { 2586 parts.push(part); 2587 } 2588 last = re.lastIndex; 2589 // switch on % code 2590 var code = match[0][1]; 2591 switch(code) { 2592 case 's': 2593 case 'o': 2594 // check if enough arguments were given 2595 if(argi < arguments.length) { 2596 parts.push(arguments[argi++ + 1]); 2597 } else { 2598 parts.push('<?>'); 2599 } 2600 break; 2601 // FIXME: do proper formating for numbers, etc 2602 //case 'f': 2603 //case 'd': 2604 case '%': 2605 parts.push('%'); 2606 break; 2607 default: 2608 parts.push('<%' + code + '?>'); 2609 } 2610 }
2611 // add trailing part of format string 2612 parts.push(format.substring(last)); 2613 return parts.join(''); 2614}; 2615 2616/** 2617 * Formats a number. 2618 * 2619 * http://snipplr.com/view/5945/javascript-numberformat--ported-from-php/ 2620 */ 2621util.formatNumber = function(number, decimals, dec_point, thousands_sep) { 2622 // http://kevin.vanzonneveld.net 2623 // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) 2624 // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 2625 // + bugfix by: Michael White (http://crestidg.com) 2626 // + bugfix by: Benjamin Lupton 2627 // + bugfix by: Allan Jensen (http://www.winternet.no) 2628 // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) 2629 // * example 1: number_format(1234.5678, 2, '.', ''); 2630 // * returns 1: 1234.57 2631 2632 var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals; 2633 var d = dec_point === undefined ? ',' : dec_point; 2634 var t = thousands_sep === undefined ? 2635 '.' : thousands_sep, s = n < 0 ? '-' : ''; 2636 var i = parseInt((n = Math.abs(+n || 0).toFixed(c)), 10) + ''; 2637 var j = (i.length > 3) ? i.length % 3 : 0; 2638 return s + (j ? i.substr(0, j) + t : '') + 2639 i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + t) + 2640 (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); 2641}; 2642 2643/** 2644 * Formats a byte size. 2645 * 2646 * http://snipplr.com/view/5949/format-humanize-file-byte-size-presentation-in-javascript/ 2647 */ 2648util.formatSize = function(size) { 2649 if(size >= 1073741824) { 2650 size = util.formatNumber(size / 1073741824, 2, '.', '') + ' GiB'; 2651 } else if(size >= 1048576) { 2652 size = util.formatNumber(size / 1048576, 2, '.', '') + ' MiB'; 2653 } else if(size >= 1024) { 2654 size = util.formatNumber(size / 1024, 0) + ' KiB'; 2655 } else { 2656 size = util.formatNumber(size, 0) + ' bytes'; 2657 } 2658 return size; 2659}; 2660 2661/** 2662 * Converts an IPv4 or IPv6 string representation into bytes (in network order). 2663 * 2664 * @param ip the IPv4 or IPv6 address to convert. 2665 * 2666 * @return the 4-byte IPv6 or 16-byte IPv6 address or null if the address can't 2667 * be parsed. 2668 */ 2669util.bytesFromIP = function(ip) { 2670 if(ip.indexOf('.') !== -1) { 2671 return util.bytesFromIPv4(ip); 2672 } 2673 if(ip.indexOf(':') !== -1) { 2674 return util.bytesFromIPv6(ip); 2675 } 2676 return null; 2677}; 2678 2679/** 2680 * Converts an IPv4 string representation into bytes (in network order). 2681 * 2682 * @param ip the IPv4 address to convert. 2683 * 2684 * @return the 4-byte address or null if the address can't be parsed. 2685 */ 2686util.bytesFromIPv4 = function(ip) { 2687 ip = ip.split('.'); 2688 if(ip.length !== 4) { 2689 return null; 2690 } 2691 var b = util.createBuffer(); 2692 for(var i = 0; i < ip.length; ++i) { 2693 var num = parseInt(ip[i], 10); 2694 if(isNaN(num)) { 2695 return null; 2696 } 2697 b.putByte(num); 2698 } 2699 return b.getBytes(); 2700}; 2701 2702/** 2703 * Converts an IPv6 string representation into bytes (in network order). 2704 * 2705 * @param ip the IPv6 address to convert. 2706 * 2707 * @return the 16-byte address or null if the address can't be parsed. 2708 */ 2709util.bytesFromIPv6 = function(ip) { 2710 var blanks = 0; 2711 ip = ip.split(':').filter(function(e) { 2712 if(e.length === 0) ++blanks; 2713 return true; 2714 }); 2715 var zeros = (8 - ip.length + blanks) * 2; 2716 var b = util.createBuffer(); 2717 for(var i = 0; i < 8; ++i) { 2718 if(!ip[i] || ip[i].length === 0) { 2719 b.fillWithByte(0, zeros); 2720 zeros = 0; 2721 continue; 2722 } 2723 var bytes = util.hexToBytes(ip[i]); 2724 if(bytes.length < 2) { 2725 b.putByte(0); 2726 } 2727 b.putBytes(bytes); 2728 } 2729 return b.getBytes(); 2730}; 2731 2732/** 2733 * Converts 4-bytes into an IPv4 string representation or 16-bytes into 2734 * an IPv6 string representation. The bytes must be in network order. 2735 * 2736 * @param bytes the bytes to convert. 2737 * 2738 * @return the IPv4 or IPv6 string representation if 4 or 16 bytes, 2739 * respectively, are given, otherwise null. 2740 */ 2741util.bytesToIP = function(bytes) { 2742 if(bytes.length === 4) { 2743 return util.bytesToIPv4(bytes); 2744 } 2745 if(bytes.length === 16) { 2746 return util.bytesToIPv6(bytes); 2747 } 2748 return null; 2749}; 2750 2751/** 2752 * Converts 4-bytes into an IPv4 string representation. The bytes must be 2753 * in network order. 2754 * 2755 * @param bytes the bytes to convert. 2756 *
2757 * @return the IPv4 string representation or null for an invalid # of bytes. 2758 */ 2759util.bytesToIPv4 = function(bytes) { 2760 if(bytes.length !== 4) { 2761 return null; 2762 } 2763 var ip = []; 2764 for(var i = 0; i < bytes.length; ++i) { 2765 ip.push(bytes.charCodeAt(i)); 2766 } 2767 return ip.join('.'); 2768}; 2769 2770/** 2771 * Converts 16-bytes into an IPv16 string representation. The bytes must be 2772 * in network order. 2773 * 2774 * @param bytes the bytes to convert. 2775 * 2776 * @return the IPv16 string representation or null for an invalid # of bytes. 2777 */ 2778util.bytesToIPv6 = function(bytes) { 2779 if(bytes.length !== 16) { 2780 return null; 2781 } 2782 var ip = []; 2783 var zeroGroups = []; 2784 var zeroMaxGroup = 0; 2785 for(var i = 0; i < bytes.length; i += 2) { 2786 var hex = util.bytesToHex(bytes[i] + bytes[i + 1]); 2787 // canonicalize zero representation 2788 while(hex[0] === '0' && hex !== '0') { 2789 hex = hex.substr(1); 2790 } 2791 if(hex === '0') { 2792 var last = zeroGroups[zeroGroups.length - 1]; 2793 var idx = ip.length; 2794 if(!last || idx !== last.end + 1) { 2795 zeroGroups.push({start: idx, end: idx}); 2796 } else { 2797 last.end = idx; 2798 if((last.end - last.start) > 2799 (zeroGroups[zeroMaxGroup].end - zeroGroups[zeroMaxGroup].start)) { 2800 zeroMaxGroup = zeroGroups.length - 1; 2801 } 2802 } 2803 } 2804 ip.push(hex); 2805 } 2806 if(zeroGroups.length > 0) { 2807 var group = zeroGroups[zeroMaxGroup]; 2808 // only shorten group of length > 0 2809 if(group.end - group.start > 0) { 2810 ip.splice(group.start, group.end - group.start + 1, ''); 2811 if(group.start === 0) { 2812 ip.unshift(''); 2813 } 2814 if(group.end === 7) { 2815 ip.push(''); 2816 } 2817 } 2818 } 2819 return ip.join(':'); 2820}; 2821 2822/** 2823 * Estimates the number of processes that can be run concurrently. If 2824 * creating Web Workers, keep in mind that the main JavaScript process needs 2825 * its own core. 2826 * 2827 * @param options the options to use: 2828 * update true to force an update (not use the cached value). 2829 * @param callback(err, max) called once the operation completes. 2830 */ 2831util.estimateCores = function(options, callback) { 2832 if(typeof options === 'function') { 2833 callback = options; 2834 options = {}; 2835 } 2836 options = options || {}; 2837 if('cores' in util && !options.update) { 2838 return callback(null, util.cores); 2839 } 2840 if(typeof navigator !== 'undefined' && 2841 'hardwareConcurrency' in navigator && 2842 navigator.hardwareConcurrency > 0) { 2843 util.cores = navigator.hardwareConcurrency; 2844 return callback(null, util.cores); 2845 } 2846 if(typeof Worker === 'undefined') { 2847 // workers not available 2848 util.cores = 1; 2849 return callback(null, util.cores); 2850 } 2851 if(typeof Blob === 'undefined') { 2852 // can't estimate, default to 2 2853 util.cores = 2; 2854 return callback(null, util.cores); 2855 } 2856 2857 // create worker concurrency estimation code as blob 2858 var blobUrl = URL.createObjectURL(new Blob(['(', 2859 function() { 2860 self.addEventListener('message', function(e) { 2861 // run worker for 4 ms 2862 var st = Date.now(); 2863 var et = st + 4; 2864 while(Date.now() < et); 2865 self.postMessage({st: st, et: et}); 2866 }); 2867 }.toString(), 2868 ')()'], {type: 'application/javascript'})); 2869 2870 // take 5 samples using 16 workers 2871 sample([], 5, 16); 2872 2873 function sample(max, samples, numWorkers) { 2874 if(samples === 0) { 2875 // get overlap average 2876 var avg = Math.floor(max.reduce(function(avg, x) { 2877 return avg + x; 2878 }, 0) / max.length); 2879 util.cores = Math.max(1, avg); 2880 URL.revokeObjectURL(blobUrl); 2881 return callback(null, util.cores); 2882 } 2883 map(numWorkers, function(err, results) { 2884 max.push(reduce(numWorkers, results)); 2885 sample(max, samples - 1, numWorkers); 2886 }); 2887 } 2888 2889 function map(numWorkers, callback) { 2890 var workers = []; 2891 var results = []; 2892 for(var i = 0; i < numWorkers; ++i) { 2893 var worker = new Worker(blobUrl); 2894 worker.addEventListener('message', function(e) { 2895 results.push(e.data); 2896 if(results.length === numWorkers) { 2897 for(var i = 0; i < numWorkers; ++i) { 2898 workers[i].terminate(); 2899 } 2900 callback(null, results); 2901 } 2902 }); 2903 workers.push(worker); 2904 } 2905 for(var i = 0; i < numWorkers; ++i) { 2906 workers[i].postMessage(i); 2907 } 2908 } 2909 2910 function reduce(numWorkers, results) { 2911 // find overlapping time windows 2912 var overlaps = []; 2913 for(var n = 0; n < numWorkers; ++n) { 2914 var r1 = results[n]; 2915 var overlap = overlaps[n] = []; 2916 for(var i = 0; i < numWorkers; ++i) { 2917 if(n === i) { 2918 continue; 2919 } 2920 var r2 = results[i]; 2921 if((r1.st > r2.st && r1.st < r2.et) || 2922 (r2.st > r1.st && r2.st < r1.et)) { 2923 overlap.push(i); 2924 } 2925 } 2926 } 2927 // get maximum overlaps ... don't include overlapping worker itself 2928 // as the main JS process was also being scheduled during the work and 2929 // would have to be subtracted from the estimate anyway 2930 return overlaps.reduce(function(max, overlap) { 2931 return Math.max(max, overlap.length); 2932 }, 0); 2933 } 2934}; 2935 2936} // end module implementation 2937 2938/* ########## Begin module wrapper ########## */ 2939var name = 'util'; 2940if(typeof define !== 'function') { 2941 // NodeJS -> AMD 2942 if(typeof module === 'object' && module.exports) { 2943 var nodeJS = true; 2944 define = function(ids, factory) { 2945 factory(require, module); 2946 }; 2947 } else { 2948 // <script> 2949 if(typeof forge === 'undefined') { 2950 forge = {}; 2951 } 2952 return initModule(forge); 2953 } 2954} 2955// AMD 2956var deps;
2957var defineFunc = function(require, module) { 2958 module.exports = function(forge) { 2959 var mods = deps.map(function(dep) { 2960 return require(dep); 2961 }).concat(initModule); 2962 // handle circular dependencies 2963 forge = forge || {}; 2964 forge.defined = forge.defined || {}; 2965 if(forge.defined[name]) { 2966 return forge[name]; 2967 } 2968 forge.defined[name] = true; 2969 for(var i = 0; i < mods.length; ++i) { 2970 mods[i](forge); 2971 } 2972 return forge[name]; 2973 }; 2974}; 2975var tmpDefine = define; 2976define = function(ids, factory) { 2977 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 2978 if(nodeJS) { 2979 delete define; 2980 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 2981 } 2982 define = tmpDefine; 2983 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 2984}; 2985define(['require', 'module'], function() { 2986 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 2987}); 2988})(); 2989 2990/** 2991 * Message Digest Algorithm 5 with 128-bit digest (MD5) implementation. 2992 * 2993 * @author Dave Longley 2994 * 2995 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 2996 */ 2997(function() { 2998/* ########## Begin module implementation ########## */ 2999function initModule(forge) { 3000 3001var md5 = forge.md5 = forge.md5 || {}; 3002forge.md = forge.md || {}; 3003forge.md.algorithms = forge.md.algorithms || {}; 3004forge.md.md5 = forge.md.algorithms.md5 = md5; 3005 3006/** 3007 * Creates an MD5 message digest object. 3008 * 3009 * @return a message digest object. 3010 */ 3011md5.create = function() { 3012 // do initialization as necessary 3013 if(!_initialized) { 3014 _init(); 3015 } 3016 3017 // MD5 state contains four 32-bit integers 3018 var _state = null; 3019 3020 // input buffer 3021 var _input = forge.util.createBuffer(); 3022 3023 // used for word storage 3024 var _w = new Array(16); 3025 3026 // message digest object 3027 var md = { 3028 algorithm: 'md5', 3029 blockLength: 64, 3030 digestLength: 16, 3031 // 56-bit length of message so far (does not including padding) 3032 messageLength: 0, 3033 // true message length 3034 fullMessageLength: null, 3035 // size of message length in bytes 3036 messageLengthSize: 8 3037 }; 3038 3039 /** 3040 * Starts the digest. 3041 * 3042 * @return this digest object. 3043 */ 3044 md.start = function() { 3045 // up to 56-bit message length for convenience 3046 md.messageLength = 0; 3047 3048 // full message length (set md.messageLength64 for backwards-compatibility) 3049 md.fullMessageLength = md.messageLength64 = []; 3050 var int32s = md.messageLengthSize / 4; 3051 for(var i = 0; i < int32s; ++i) { 3052 md.fullMessageLength.push(0); 3053 } 3054 _input = forge.util.createBuffer(); 3055 _state = { 3056 h0: 0x67452301, 3057 h1: 0xEFCDAB89, 3058 h2: 0x98BADCFE, 3059 h3: 0x10325476 3060 }; 3061 return md; 3062 }; 3063 // start digest automatically for first time 3064 md.start(); 3065 3066 /** 3067 * Updates the digest with the given message input. The given input can 3068 * treated as raw input (no encoding will be applied) or an encoding of 3069 * 'utf8' maybe given to encode the input using UTF-8. 3070 * 3071 * @param msg the message input to update with. 3072 * @param encoding the encoding to use (default: 'raw', other: 'utf8'). 3073 * 3074 * @return this digest object. 3075 */ 3076 md.update = function(msg, encoding) { 3077 if(encoding === 'utf8') { 3078 msg = forge.util.encodeUtf8(msg); 3079 } 3080 3081 // update message length 3082 var len = msg.length; 3083 md.messageLength += len; 3084 len = [(len / 0x100000000) >>> 0, len >>> 0]; 3085 for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { 3086 md.fullMessageLength[i] += len[1]; 3087 len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0); 3088 md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; 3089 len[0] = (len[1] / 0x100000000) >>> 0; 3090 } 3091 3092 // add bytes to input buffer 3093 _input.putBytes(msg); 3094 3095 // process bytes 3096 _update(_state, _w, _input); 3097 3098 // compact input buffer every 2K or if empty 3099 if(_input.read > 2048 || _input.length() === 0) { 3100 _input.compact(); 3101 } 3102 3103 return md; 3104 }; 3105 3106 /** 3107 * Produces the digest. 3108 * 3109 * @return a byte buffer containing the digest value. 3110 */ 3111 md.digest = function() { 3112 /* Note: Here we copy the remaining bytes in the input buffer and 3113 add the appropriate MD5 padding. Then we do the final update 3114 on a copy of the state so that if the user wants to get 3115 intermediate digests they can do so. */ 3116 3117 /* Determine the number of bytes that must be added to the message 3118 to ensure its length is congruent to 448 mod 512. In other words, 3119 the data to be digested must be a multiple of 512 bits (or 128 bytes). 3120 This data includes the message, some padding, and the length of the 3121 message. Since the length of the message will be encoded as 8 bytes (64 3122 bits), that means that the last segment of the data must have 56 bytes 3123 (448 bits) of message and padding. Therefore, the length of the message 3124 plus the padding must be congruent to 448 mod 512 because 3125 512 - 128 = 448. 3126 3127 In order to fill up the message length it must be filled with 3128 padding that begins with 1 bit followed by all 0 bits. Padding 3129 must *always* be present, so if the message length is already 3130 congruent to 448 mod 512, then 512 padding bits must be added. */ 3131 3132 var finalBlock = forge.util.createBuffer(); 3133 finalBlock.putBytes(_input.bytes()); 3134 3135 // compute remaining size to be digested (include message length size) 3136 var remaining = ( 3137 md.fullMessageLength[md.fullMessageLength.length - 1] + 3138 md.messageLengthSize); 3139 3140 // add padding for overflow blockSize - overflow 3141 // _padding starts with 1 byte with first bit is set (byte value 128), then 3142 // there may be up to (blockSize - 1) other pad bytes 3143 var overflow = remaining & (md.blockLength - 1); 3144 finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow)); 3145 3146 // serialize message length in bits in little-endian order; since length 3147 // is stored in bytes we multiply by 8 and add carry 3148 var bits, carry = 0; 3149 for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { 3150 bits = md.fullMessageLength[i] * 8 + carry; 3151 carry = (bits / 0x100000000) >>> 0; 3152 finalBlock.putInt32Le(bits >>> 0); 3153 } 3154 3155 var s2 = { 3156 h0: _state.h0, 3157 h1: _state.h1, 3158 h2: _state.h2, 3159 h3: _state.h3 3160 }; 3161 _update(s2, _w, finalBlock); 3162 var rval = forge.util.createBuffer(); 3163 rval.putInt32Le(s2.h0); 3164 rval.putInt32Le(s2.h1); 3165 rval.putInt32Le(s2.h2); 3166 rval.putInt32Le(s2.h3); 3167 return rval; 3168 }; 3169 3170 return md; 3171}; 3172 3173// padding, constant tables for calculating md5 3174var _padding = null; 3175var _g = null; 3176var _r = null; 3177var _k = null; 3178var _initialized = false;
3179 3180/** 3181 * Initializes the constant tables. 3182 */ 3183function _init() { 3184 // create padding 3185 _padding = String.fromCharCode(128); 3186 _padding += forge.util.fillString(String.fromCharCode(0x00), 64); 3187 3188 // g values 3189 _g = [ 3190 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 3191 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 3192 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, 3193 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9]; 3194 3195 // rounds table 3196 _r = [ 3197 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 3198 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 3199 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 3200 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]; 3201 3202 // get the result of abs(sin(i + 1)) as a 32-bit integer 3203 _k = new Array(64); 3204 for(var i = 0; i < 64; ++i) { 3205 _k[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000); 3206 } 3207 3208 // now initialized 3209 _initialized = true; 3210} 3211 3212/** 3213 * Updates an MD5 state with the given byte buffer. 3214 * 3215 * @param s the MD5 state to update. 3216 * @param w the array to use to store words. 3217 * @param bytes the byte buffer to update with. 3218 */ 3219function _update(s, w, bytes) { 3220 // consume 512 bit (64 byte) chunks 3221 var t, a, b, c, d, f, r, i; 3222 var len = bytes.length(); 3223 while(len >= 64) { 3224 // initialize hash value for this chunk 3225 a = s.h0; 3226 b = s.h1; 3227 c = s.h2; 3228 d = s.h3; 3229 3230 // round 1 3231 for(i = 0; i < 16; ++i) { 3232 w[i] = bytes.getInt32Le(); 3233 f = d ^ (b & (c ^ d)); 3234 t = (a + f + _k[i] + w[i]); 3235 r = _r[i]; 3236 a = d; 3237 d = c; 3238 c = b; 3239 b += (t << r) | (t >>> (32 - r)); 3240 } 3241 // round 2 3242 for(; i < 32; ++i) { 3243 f = c ^ (d & (b ^ c)); 3244 t = (a + f + _k[i] + w[_g[i]]); 3245 r = _r[i]; 3246 a = d; 3247 d = c; 3248 c = b; 3249 b += (t << r) | (t >>> (32 - r)); 3250 } 3251 // round 3 3252 for(; i < 48; ++i) { 3253 f = b ^ c ^ d; 3254 t = (a + f + _k[i] + w[_g[i]]); 3255 r = _r[i]; 3256 a = d; 3257 d = c; 3258 c = b; 3259 b += (t << r) | (t >>> (32 - r)); 3260 } 3261 // round 4 3262 for(; i < 64; ++i) { 3263 f = c ^ (b | ~d); 3264 t = (a + f + _k[i] + w[_g[i]]); 3265 r = _r[i]; 3266 a = d; 3267 d = c; 3268 c = b; 3269 b += (t << r) | (t >>> (32 - r)); 3270 } 3271 3272 // update hash state 3273 s.h0 = (s.h0 + a) | 0; 3274 s.h1 = (s.h1 + b) | 0; 3275 s.h2 = (s.h2 + c) | 0; 3276 s.h3 = (s.h3 + d) | 0; 3277 3278 len -= 64; 3279 } 3280} 3281 3282} // end module implementation 3283 3284/* ########## Begin module wrapper ########## */ 3285var name = 'md5'; 3286if(typeof define !== 'function') { 3287 // NodeJS -> AMD 3288 if(typeof module === 'object' && module.exports) { 3289 var nodeJS = true; 3290 define = function(ids, factory) { 3291 factory(require, module); 3292 }; 3293 } else { 3294 // <script> 3295 if(typeof forge === 'undefined') { 3296 forge = {}; 3297 } 3298 return initModule(forge); 3299 } 3300} 3301// AMD 3302var deps; 3303var defineFunc = function(require, module) { 3304 module.exports = function(forge) { 3305 var mods = deps.map(function(dep) { 3306 return require(dep); 3307 }).concat(initModule); 3308 // handle circular dependencies 3309 forge = forge || {}; 3310 forge.defined = forge.defined || {}; 3311 if(forge.defined[name]) { 3312 return forge[name]; 3313 } 3314 forge.defined[name] = true; 3315 for(var i = 0; i < mods.length; ++i) { 3316 mods[i](forge); 3317 } 3318 return forge[name]; 3319 }; 3320}; 3321var tmpDefine = define; 3322define = function(ids, factory) { 3323 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 3324 if(nodeJS) { 3325 delete define; 3326 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 3327 } 3328 define = tmpDefine; 3329 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 3330}; 3331define(['require', 'module', './util'], function() { 3332 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 3333}); 3334})(); 3335 3336/** 3337 * Secure Hash Algorithm with 160-bit digest (SHA-1) implementation. 3338 * 3339 * @author Dave Longley 3340 * 3341 * Copyright (c) 2010-2015 Digital Bazaar, Inc. 3342 */ 3343(function() { 3344/* ########## Begin module implementation ########## */ 3345function initModule(forge) { 3346 3347var sha1 = forge.sha1 = forge.sha1 || {}; 3348forge.md = forge.md || {}; 3349forge.md.algorithms = forge.md.algorithms || {}; 3350forge.md.sha1 = forge.md.algorithms.sha1 = sha1; 3351 3352/** 3353 * Creates a SHA-1 message digest object. 3354 * 3355 * @return a message digest object. 3356 */ 3357sha1.create = function() { 3358 // do initialization as necessary 3359 if(!_initialized) { 3360 _init(); 3361 } 3362 3363 // SHA-1 state contains five 32-bit integers 3364 var _state = null; 3365 3366 // input buffer 3367 var _input = forge.util.createBuffer(); 3368 3369 // used for word storage 3370 var _w = new Array(80); 3371 3372 // message digest object 3373 var md = { 3374 algorithm: 'sha1', 3375 blockLength: 64, 3376 digestLength: 20, 3377 // 56-bit length of message so far (does not including padding) 3378 messageLength: 0, 3379 // true message length 3380 fullMessageLength: null, 3381 // size of message length in bytes 3382 messageLengthSize: 8 3383 }; 3384 3385 /** 3386 * Starts the digest. 3387 * 3388 * @return this digest object. 3389 */ 3390 md.start = function() { 3391 // up to 56-bit message length for convenience 3392 md.messageLength = 0; 3393 3394 // full message length (set md.messageLength64 for backwards-compatibility) 3395 md.fullMessageLength = md.messageLength64 = []; 3396 var int32s = md.messageLengthSize / 4; 3397 for(var i = 0; i < int32s; ++i) { 3398 md.fullMessageLength.push(0); 3399 } 3400 _input = forge.util.createBuffer(); 3401 _state = { 3402 h0: 0x67452301, 3403 h1: 0xEFCDAB89, 3404 h2: 0x98BADCFE, 3405 h3: 0x10325476, 3406 h4: 0xC3D2E1F0 3407 }; 3408 return md; 3409 }; 3410 // start digest automatically for first time 3411 md.start(); 3412 3413 /** 3414 * Updates the digest with the given message input. The given input can 3415 * treated as raw input (no encoding will be applied) or an encoding of 3416 * 'utf8' maybe given to encode the input using UTF-8. 3417 * 3418 * @param msg the message input to update with. 3419 * @param encoding the encoding to use (default: 'raw', other: 'utf8'). 3420 * 3421 * @return this digest object. 3422 */ 3423 md.update = function(msg, encoding) { 3424 if(encoding === 'utf8') { 3425 msg = forge.util.encodeUtf8(msg); 3426 } 3427 3428 // update message length 3429 var len = msg.length; 3430 md.messageLength += len; 3431 len = [(len / 0x100000000) >>> 0, len >>> 0]; 3432 for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { 3433 md.fullMessageLength[i] += len[1]; 3434 len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0); 3435 md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; 3436 len[0] = ((len[1] / 0x100000000) >>> 0); 3437 } 3438 3439 // add bytes to input buffer 3440 _input.putBytes(msg); 3441 3442 // process bytes 3443 _update(_state, _w, _input); 3444 3445 // compact input buffer every 2K or if empty 3446 if(_input.read > 2048 || _input.length() === 0) { 3447 _input.compact(); 3448 } 3449 3450 return md; 3451 }; 3452 3453 /** 3454 * Produces the digest. 3455 * 3456 * @return a byte buffer containing the digest value. 3457 */ 3458 md.digest = function() { 3459 /* Note: Here we copy the remaining bytes in the input buffer and 3460 add the appropriate SHA-1 padding. Then we do the final update 3461 on a copy of the state so that if the user wants to get 3462 intermediate digests they can do so. */ 3463 3464 /* Determine the number of bytes that must be added to the message 3465 to ensure its length is congruent to 448 mod 512. In other words, 3466 the data to be digested must be a multiple of 512 bits (or 128 bytes). 3467 This data includes the message, some padding, and the length of the 3468 message. Since the length of the message will be encoded as 8 bytes (64 3469 bits), that means that the last segment of the data must have 56 bytes 3470 (448 bits) of message and padding. Therefore, the length of the message 3471 plus the padding must be congruent to 448 mod 512 because 3472 512 - 128 = 448. 3473 3474 In order to fill up the message length it must be filled with 3475 padding that begins with 1 bit followed by all 0 bits. Padding 3476 must *always* be present, so if the message length is already 3477 congruent to 448 mod 512, then 512 padding bits must be added. */ 3478 3479 var finalBlock = forge.util.createBuffer(); 3480 finalBlock.putBytes(_input.bytes()); 3481 3482 // compute remaining size to be digested (include message length size) 3483 var remaining = ( 3484 md.fullMessageLength[md.fullMessageLength.length - 1] + 3485 md.messageLengthSize); 3486 3487 // add padding for overflow blockSize - overflow 3488 // _padding starts with 1 byte with first bit is set (byte value 128), then 3489 // there may be up to (blockSize - 1) other pad bytes 3490 var overflow = remaining & (md.blockLength - 1); 3491 finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow)); 3492 3493 // serialize message length in bits in big-endian order; since length 3494 // is stored in bytes we multiply by 8 and add carry from next int 3495 var next, carry; 3496 var bits = md.fullMessageLength[0] * 8; 3497 for(var i = 0; i < md.fullMessageLength.length - 1; ++i) { 3498 next = md.fullMessageLength[i + 1] * 8; 3499 carry = (next / 0x100000000) >>> 0; 3500 bits += carry; 3501 finalBlock.putInt32(bits >>> 0); 3502 bits = next >>> 0; 3503 } 3504 finalBlock.putInt32(bits); 3505 3506 var s2 = { 3507 h0: _state.h0, 3508 h1: _state.h1, 3509 h2: _state.h2, 3510 h3: _state.h3, 3511 h4: _state.h4 3512 }; 3513 _update(s2, _w, finalBlock); 3514 var rval = forge.util.createBuffer(); 3515 rval.putInt32(s2.h0); 3516 rval.putInt32(s2.h1); 3517 rval.putInt32(s2.h2); 3518 rval.putInt32(s2.h3); 3519 rval.putInt32(s2.h4); 3520 return rval; 3521 }; 3522 3523 return md; 3524}; 3525 3526// sha-1 padding bytes not initialized yet 3527var _padding = null; 3528var _initialized = false;
3529 3530/** 3531 * Initializes the constant tables. 3532 */ 3533function _init() { 3534 // create padding 3535 _padding = String.fromCharCode(128); 3536 _padding += forge.util.fillString(String.fromCharCode(0x00), 64); 3537 3538 // now initialized 3539 _initialized = true; 3540} 3541 3542/** 3543 * Updates a SHA-1 state with the given byte buffer. 3544 * 3545 * @param s the SHA-1 state to update. 3546 * @param w the array to use to store words. 3547 * @param bytes the byte buffer to update with. 3548 */ 3549function _update(s, w, bytes) { 3550 // consume 512 bit (64 byte) chunks 3551 var t, a, b, c, d, e, f, i; 3552 var len = bytes.length(); 3553 while(len >= 64) { 3554 // the w array will be populated with sixteen 32-bit big-endian words 3555 // and then extended into 80 32-bit words according to SHA-1 algorithm 3556 // and for 32-79 using Max Locktyukhin's optimization 3557 3558 // initialize hash value for this chunk 3559 a = s.h0; 3560 b = s.h1; 3561 c = s.h2; 3562 d = s.h3; 3563 e = s.h4; 3564 3565 // round 1 3566 for(i = 0; i < 16; ++i) { 3567 t = bytes.getInt32(); 3568 w[i] = t; 3569 f = d ^ (b & (c ^ d)); 3570 t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t; 3571 e = d; 3572 d = c; 3573 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 3574 c = ((b << 30) | (b >>> 2)) >>> 0; 3575 b = a; 3576 a = t; 3577 } 3578 for(; i < 20; ++i) { 3579 t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]); 3580 t = (t << 1) | (t >>> 31); 3581 w[i] = t; 3582 f = d ^ (b & (c ^ d)); 3583 t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t; 3584 e = d; 3585 d = c; 3586 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 3587 c = ((b << 30) | (b >>> 2)) >>> 0; 3588 b = a; 3589 a = t; 3590 } 3591 // round 2 3592 for(; i < 32; ++i) { 3593 t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]); 3594 t = (t << 1) | (t >>> 31); 3595 w[i] = t; 3596 f = b ^ c ^ d; 3597 t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; 3598 e = d; 3599 d = c; 3600 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 3601 c = ((b << 30) | (b >>> 2)) >>> 0; 3602 b = a; 3603 a = t; 3604 } 3605 for(; i < 40; ++i) { 3606 t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); 3607 t = (t << 2) | (t >>> 30); 3608 w[i] = t; 3609 f = b ^ c ^ d; 3610 t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; 3611 e = d; 3612 d = c; 3613 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 3614 c = ((b << 30) | (b >>> 2)) >>> 0; 3615 b = a; 3616 a = t; 3617 } 3618 // round 3 3619 for(; i < 60; ++i) { 3620 t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); 3621 t = (t << 2) | (t >>> 30); 3622 w[i] = t; 3623 f = (b & c) | (d & (b ^ c)); 3624 t = ((a << 5) | (a >>> 27)) + f + e + 0x8F1BBCDC + t; 3625 e = d; 3626 d = c; 3627 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 3628 c = ((b << 30) | (b >>> 2)) >>> 0; 3629 b = a; 3630 a = t; 3631 } 3632 // round 4 3633 for(; i < 80; ++i) { 3634 t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); 3635 t = (t << 2) | (t >>> 30); 3636 w[i] = t; 3637 f = b ^ c ^ d; 3638 t = ((a << 5) | (a >>> 27)) + f + e + 0xCA62C1D6 + t; 3639 e = d; 3640 d = c; 3641 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 3642 c = ((b << 30) | (b >>> 2)) >>> 0; 3643 b = a; 3644 a = t; 3645 } 3646 3647 // update hash state 3648 s.h0 = (s.h0 + a) | 0; 3649 s.h1 = (s.h1 + b) | 0; 3650 s.h2 = (s.h2 + c) | 0; 3651 s.h3 = (s.h3 + d) | 0; 3652 s.h4 = (s.h4 + e) | 0; 3653 3654 len -= 64; 3655 } 3656} 3657 3658} // end module implementation 3659 3660/* ########## Begin module wrapper ########## */ 3661var name = 'sha1'; 3662if(typeof define !== 'function') { 3663 // NodeJS -> AMD 3664 if(typeof module === 'object' && module.exports) { 3665 var nodeJS = true; 3666 define = function(ids, factory) { 3667 factory(require, module); 3668 }; 3669 } else { 3670 // <script> 3671 if(typeof forge === 'undefined') { 3672 forge = {}; 3673 } 3674 return initModule(forge); 3675 } 3676} 3677// AMD 3678var deps; 3679var defineFunc = function(require, module) { 3680 module.exports = function(forge) { 3681 var mods = deps.map(function(dep) { 3682 return require(dep); 3683 }).concat(initModule); 3684 // handle circular dependencies 3685 forge = forge || {}; 3686 forge.defined = forge.defined || {}; 3687 if(forge.defined[name]) { 3688 return forge[name]; 3689 } 3690 forge.defined[name] = true; 3691 for(var i = 0; i < mods.length; ++i) { 3692 mods[i](forge); 3693 } 3694 return forge[name]; 3695 }; 3696}; 3697var tmpDefine = define; 3698define = function(ids, factory) { 3699 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 3700 if(nodeJS) { 3701 delete define; 3702 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 3703 } 3704 define = tmpDefine; 3705 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 3706}; 3707define(['require', 'module', './util'], function() { 3708 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 3709}); 3710})(); 3711 3712/** 3713 * Secure Hash Algorithm with 256-bit digest (SHA-256) implementation. 3714 * 3715 * See FIPS 180-2 for details. 3716 * 3717 * @author Dave Longley 3718 * 3719 * Copyright (c) 2010-2015 Digital Bazaar, Inc. 3720 */ 3721(function() { 3722/* ########## Begin module implementation ########## */ 3723function initModule(forge) { 3724 3725var sha256 = forge.sha256 = forge.sha256 || {}; 3726forge.md = forge.md || {}; 3727forge.md.algorithms = forge.md.algorithms || {}; 3728forge.md.sha256 = forge.md.algorithms.sha256 = sha256; 3729 3730/** 3731 * Creates a SHA-256 message digest object. 3732 * 3733 * @return a message digest object. 3734 */ 3735sha256.create = function() { 3736 // do initialization as necessary 3737 if(!_initialized) { 3738 _init(); 3739 } 3740
3741 // SHA-256 state contains eight 32-bit integers 3742 var _state = null; 3743 3744 // input buffer 3745 var _input = forge.util.createBuffer(); 3746 3747 // used for word storage 3748 var _w = new Array(64); 3749 3750 // message digest object 3751 var md = { 3752 algorithm: 'sha256', 3753 blockLength: 64, 3754 digestLength: 32, 3755 // 56-bit length of message so far (does not including padding) 3756 messageLength: 0, 3757 // true message length 3758 fullMessageLength: null, 3759 // size of message length in bytes 3760 messageLengthSize: 8 3761 }; 3762 3763 /** 3764 * Starts the digest. 3765 * 3766 * @return this digest object. 3767 */ 3768 md.start = function() { 3769 // up to 56-bit message length for convenience 3770 md.messageLength = 0; 3771 3772 // full message length (set md.messageLength64 for backwards-compatibility) 3773 md.fullMessageLength = md.messageLength64 = []; 3774 var int32s = md.messageLengthSize / 4; 3775 for(var i = 0; i < int32s; ++i) { 3776 md.fullMessageLength.push(0); 3777 } 3778 _input = forge.util.createBuffer(); 3779 _state = { 3780 h0: 0x6A09E667, 3781 h1: 0xBB67AE85, 3782 h2: 0x3C6EF372, 3783 h3: 0xA54FF53A, 3784 h4: 0x510E527F, 3785 h5: 0x9B05688C, 3786 h6: 0x1F83D9AB, 3787 h7: 0x5BE0CD19 3788 }; 3789 return md; 3790 }; 3791 // start digest automatically for first time 3792 md.start(); 3793 3794 /** 3795 * Updates the digest with the given message input. The given input can 3796 * treated as raw input (no encoding will be applied) or an encoding of 3797 * 'utf8' maybe given to encode the input using UTF-8. 3798 * 3799 * @param msg the message input to update with. 3800 * @param encoding the encoding to use (default: 'raw', other: 'utf8'). 3801 * 3802 * @return this digest object. 3803 */ 3804 md.update = function(msg, encoding) { 3805 if(encoding === 'utf8') { 3806 msg = forge.util.encodeUtf8(msg); 3807 } 3808 3809 // update message length 3810 var len = msg.length; 3811 md.messageLength += len; 3812 len = [(len / 0x100000000) >>> 0, len >>> 0]; 3813 for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { 3814 md.fullMessageLength[i] += len[1]; 3815 len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0); 3816 md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; 3817 len[0] = ((len[1] / 0x100000000) >>> 0); 3818 } 3819 3820 // add bytes to input buffer 3821 _input.putBytes(msg); 3822 3823 // process bytes 3824 _update(_state, _w, _input); 3825 3826 // compact input buffer every 2K or if empty 3827 if(_input.read > 2048 || _input.length() === 0) { 3828 _input.compact(); 3829 } 3830 3831 return md; 3832 }; 3833 3834 /** 3835 * Produces the digest. 3836 * 3837 * @return a byte buffer containing the digest value. 3838 */ 3839 md.digest = function() { 3840 /* Note: Here we copy the remaining bytes in the input buffer and 3841 add the appropriate SHA-256 padding. Then we do the final update 3842 on a copy of the state so that if the user wants to get 3843 intermediate digests they can do so. */ 3844 3845 /* Determine the number of bytes that must be added to the message 3846 to ensure its length is congruent to 448 mod 512. In other words, 3847 the data to be digested must be a multiple of 512 bits (or 128 bytes). 3848 This data includes the message, some padding, and the length of the 3849 message. Since the length of the message will be encoded as 8 bytes (64 3850 bits), that means that the last segment of the data must have 56 bytes 3851 (448 bits) of message and padding. Therefore, the length of the message 3852 plus the padding must be congruent to 448 mod 512 because 3853 512 - 128 = 448. 3854 3855 In order to fill up the message length it must be filled with 3856 padding that begins with 1 bit followed by all 0 bits. Padding 3857 must *always* be present, so if the message length is already 3858 congruent to 448 mod 512, then 512 padding bits must be added. */ 3859 3860 var finalBlock = forge.util.createBuffer(); 3861 finalBlock.putBytes(_input.bytes()); 3862 3863 // compute remaining size to be digested (include message length size) 3864 var remaining = ( 3865 md.fullMessageLength[md.fullMessageLength.length - 1] + 3866 md.messageLengthSize); 3867 3868 // add padding for overflow blockSize - overflow 3869 // _padding starts with 1 byte with first bit is set (byte value 128), then 3870 // there may be up to (blockSize - 1) other pad bytes 3871 var overflow = remaining & (md.blockLength - 1); 3872 finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow)); 3873 3874 // serialize message length in bits in big-endian order; since length 3875 // is stored in bytes we multiply by 8 and add carry from next int 3876 var next, carry; 3877 var bits = md.fullMessageLength[0] * 8; 3878 for(var i = 0; i < md.fullMessageLength.length - 1; ++i) { 3879 next = md.fullMessageLength[i + 1] * 8; 3880 carry = (next / 0x100000000) >>> 0; 3881 bits += carry; 3882 finalBlock.putInt32(bits >>> 0); 3883 bits = next >>> 0; 3884 } 3885 finalBlock.putInt32(bits); 3886 3887 var s2 = { 3888 h0: _state.h0, 3889 h1: _state.h1, 3890 h2: _state.h2, 3891 h3: _state.h3, 3892 h4: _state.h4, 3893 h5: _state.h5, 3894 h6: _state.h6, 3895 h7: _state.h7 3896 }; 3897 _update(s2, _w, finalBlock); 3898 var rval = forge.util.createBuffer(); 3899 rval.putInt32(s2.h0); 3900 rval.putInt32(s2.h1); 3901 rval.putInt32(s2.h2); 3902 rval.putInt32(s2.h3); 3903 rval.putInt32(s2.h4); 3904 rval.putInt32(s2.h5); 3905 rval.putInt32(s2.h6); 3906 rval.putInt32(s2.h7); 3907 return rval; 3908 }; 3909 3910 return md; 3911}; 3912 3913// sha-256 padding bytes not initialized yet 3914var _padding = null; 3915var _initialized = false;
3916 3917// table of constants 3918var _k = null; 3919 3920/** 3921 * Initializes the constant tables. 3922 */ 3923function _init() { 3924 // create padding 3925 _padding = String.fromCharCode(128); 3926 _padding += forge.util.fillString(String.fromCharCode(0x00), 64); 3927 3928 // create K table for SHA-256 3929 _k = [ 3930 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 3931 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 3932 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 3933 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 3934 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 3935 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 3936 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 3937 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 3938 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 3939 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 3940 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 3941 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 3942 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 3943 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 3944 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 3945 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; 3946 3947 // now initialized 3948 _initialized = true; 3949} 3950 3951/** 3952 * Updates a SHA-256 state with the given byte buffer. 3953 * 3954 * @param s the SHA-256 state to update. 3955 * @param w the array to use to store words. 3956 * @param bytes the byte buffer to update with. 3957 */ 3958function _update(s, w, bytes) { 3959 // consume 512 bit (64 byte) chunks 3960 var t1, t2, s0, s1, ch, maj, i, a, b, c, d, e, f, g, h; 3961 var len = bytes.length(); 3962 while(len >= 64) { 3963 // the w array will be populated with sixteen 32-bit big-endian words 3964 // and then extended into 64 32-bit words according to SHA-256 3965 for(i = 0; i < 16; ++i) { 3966 w[i] = bytes.getInt32(); 3967 } 3968 for(; i < 64; ++i) { 3969 // XOR word 2 words ago rot right 17, rot right 19, shft right 10 3970 t1 = w[i - 2]; 3971 t1 = 3972 ((t1 >>> 17) | (t1 << 15)) ^ 3973 ((t1 >>> 19) | (t1 << 13)) ^ 3974 (t1 >>> 10); 3975 // XOR word 15 words ago rot right 7, rot right 18, shft right 3 3976 t2 = w[i - 15]; 3977 t2 = 3978 ((t2 >>> 7) | (t2 << 25)) ^ 3979 ((t2 >>> 18) | (t2 << 14)) ^ 3980 (t2 >>> 3); 3981 // sum(t1, word 7 ago, t2, word 16 ago) modulo 2^32 3982 w[i] = (t1 + w[i - 7] + t2 + w[i - 16]) | 0; 3983 } 3984 3985 // initialize hash value for this chunk 3986 a = s.h0; 3987 b = s.h1; 3988 c = s.h2; 3989 d = s.h3; 3990 e = s.h4; 3991 f = s.h5; 3992 g = s.h6; 3993 h = s.h7; 3994 3995 // round function 3996 for(i = 0; i < 64; ++i) { 3997 // Sum1(e) 3998 s1 = 3999 ((e >>> 6) | (e << 26)) ^ 4000 ((e >>> 11) | (e << 21)) ^ 4001 ((e >>> 25) | (e << 7)); 4002 // Ch(e, f, g) (optimized the same way as SHA-1) 4003 ch = g ^ (e & (f ^ g)); 4004 // Sum0(a) 4005 s0 = 4006 ((a >>> 2) | (a << 30)) ^ 4007 ((a >>> 13) | (a << 19)) ^ 4008 ((a >>> 22) | (a << 10)); 4009 // Maj(a, b, c) (optimized the same way as SHA-1) 4010 maj = (a & b) | (c & (a ^ b)); 4011 4012 // main algorithm 4013 t1 = h + s1 + ch + _k[i] + w[i]; 4014 t2 = s0 + maj; 4015 h = g; 4016 g = f; 4017 f = e; 4018 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 4019 // can't truncate with `| 0` 4020 e = (d + t1) >>> 0; 4021 d = c; 4022 c = b; 4023 b = a; 4024 // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 4025 // can't truncate with `| 0` 4026 a = (t1 + t2) >>> 0; 4027 } 4028 4029 // update hash state 4030 s.h0 = (s.h0 + a) | 0; 4031 s.h1 = (s.h1 + b) | 0; 4032 s.h2 = (s.h2 + c) | 0; 4033 s.h3 = (s.h3 + d) | 0; 4034 s.h4 = (s.h4 + e) | 0; 4035 s.h5 = (s.h5 + f) | 0; 4036 s.h6 = (s.h6 + g) | 0; 4037 s.h7 = (s.h7 + h) | 0; 4038 len -= 64; 4039 } 4040} 4041 4042} // end module implementation 4043 4044/* ########## Begin module wrapper ########## */ 4045var name = 'sha256'; 4046if(typeof define !== 'function') { 4047 // NodeJS -> AMD 4048 if(typeof module === 'object' && module.exports) { 4049 var nodeJS = true; 4050 define = function(ids, factory) { 4051 factory(require, module); 4052 }; 4053 } else { 4054 // <script> 4055 if(typeof forge === 'undefined') { 4056 forge = {}; 4057 } 4058 return initModule(forge); 4059 } 4060} 4061// AMD 4062var deps; 4063var defineFunc = function(require, module) { 4064 module.exports = function(forge) { 4065 var mods = deps.map(function(dep) { 4066 return require(dep); 4067 }).concat(initModule); 4068 // handle circular dependencies 4069 forge = forge || {}; 4070 forge.defined = forge.defined || {}; 4071 if(forge.defined[name]) { 4072 return forge[name]; 4073 } 4074 forge.defined[name] = true; 4075 for(var i = 0; i < mods.length; ++i) { 4076 mods[i](forge); 4077 } 4078 return forge[name]; 4079 }; 4080}; 4081var tmpDefine = define; 4082define = function(ids, factory) { 4083 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 4084 if(nodeJS) { 4085 delete define; 4086 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 4087 } 4088 define = tmpDefine; 4089 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 4090}; 4091define(['require', 'module', './util'], function() { 4092 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 4093}); 4094})(); 4095 4096/** 4097 * Cipher base API. 4098 * 4099 * @author Dave Longley 4100 * 4101 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 4102 */ 4103(function() { 4104/* ########## Begin module implementation ########## */ 4105function initModule(forge) { 4106 4107forge.cipher = forge.cipher || {}; 4108 4109// registered algorithms 4110forge.cipher.algorithms = forge.cipher.algorithms || {}; 4111 4112/** 4113 * Creates a cipher object that can be used to encrypt data using the given 4114 * algorithm and key. The algorithm may be provided as a string value for a 4115 * previously registered algorithm or it may be given as a cipher algorithm 4116 * API object. 4117 * 4118 * @param algorithm the algorithm to use, either a string or an algorithm API 4119 * object. 4120 * @param key the key to use, as a binary-encoded string of bytes or a 4121 * byte buffer. 4122 * 4123 * @return the cipher. 4124 */ 4125forge.cipher.createCipher = function(algorithm, key) { 4126 var api = algorithm; 4127 if(typeof api === 'string') { 4128 api = forge.cipher.getAlgorithm(api); 4129 if(api) { 4130 api = api(); 4131 } 4132 } 4133 if(!api) { 4134 throw new Error('Unsupported algorithm: ' + algorithm); 4135 } 4136 4137 // assume block cipher 4138 return new forge.cipher.BlockCipher({ 4139 algorithm: api, 4140 key: key, 4141 decrypt: false 4142 }); 4143}; 4144 4145/** 4146 * Creates a decipher object that can be used to decrypt data using the given 4147 * algorithm and key. The algorithm may be provided as a string value for a 4148 * previously registered algorithm or it may be given as a cipher algorithm 4149 * API object. 4150 * 4151 * @param algorithm the algorithm to use, either a string or an algorithm API 4152 * object. 4153 * @param key the key to use, as a binary-encoded string of bytes or a 4154 * byte buffer. 4155 * 4156 * @return the cipher. 4157 */ 4158forge.cipher.createDecipher = function(algorithm, key) { 4159 var api = algorithm; 4160 if(typeof api === 'string') { 4161 api = forge.cipher.getAlgorithm(api); 4162 if(api) { 4163 api = api(); 4164 } 4165 } 4166 if(!api) { 4167 throw new Error('Unsupported algorithm: ' + algorithm); 4168 } 4169 4170 // assume block cipher 4171 return new forge.cipher.BlockCipher({ 4172 algorithm: api, 4173 key: key, 4174 decrypt: true 4175 }); 4176}; 4177 4178/** 4179 * Registers an algorithm by name. If the name was already registered, the 4180 * algorithm API object will be overwritten. 4181 * 4182 * @param name the name of the algorithm. 4183 * @param algorithm the algorithm API object. 4184 */ 4185forge.cipher.registerAlgorithm = function(name, algorithm) { 4186 name = name.toUpperCase(); 4187 forge.cipher.algorithms[name] = algorithm; 4188}; 4189 4190/** 4191 * Gets a registered algorithm by name. 4192 * 4193 * @param name the name of the algorithm. 4194 * 4195 * @return the algorithm, if found, null if not. 4196 */ 4197forge.cipher.getAlgorithm = function(name) { 4198 name = name.toUpperCase(); 4199 if(name in forge.cipher.algorithms) { 4200 return forge.cipher.algorithms[name]; 4201 } 4202 return null; 4203}; 4204 4205var BlockCipher = forge.cipher.BlockCipher = function(options) { 4206 this.algorithm = options.algorithm; 4207 this.mode = this.algorithm.mode; 4208 this.blockSize = this.mode.blockSize; 4209 this._finish = false;
4210 this._input = null; 4211 this.output = null; 4212 this._op = options.decrypt ? this.mode.decrypt : this.mode.encrypt; 4213 this._decrypt = options.decrypt; 4214 this.algorithm.initialize(options); 4215}; 4216 4217/** 4218 * Starts or restarts the encryption or decryption process, whichever 4219 * was previously configured. 4220 * 4221 * For non-GCM mode, the IV may be a binary-encoded string of bytes, an array 4222 * of bytes, a byte buffer, or an array of 32-bit integers. If the IV is in 4223 * bytes, then it must be Nb (16) bytes in length. If the IV is given in as 4224 * 32-bit integers, then it must be 4 integers long. 4225 * 4226 * Note: an IV is not required or used in ECB mode. 4227 * 4228 * For GCM-mode, the IV must be given as a binary-encoded string of bytes or 4229 * a byte buffer. The number of bytes should be 12 (96 bits) as recommended 4230 * by NIST SP-800-38D but another length may be given. 4231 * 4232 * @param options the options to use: 4233 * iv the initialization vector to use as a binary-encoded string of 4234 * bytes, null to reuse the last ciphered block from a previous 4235 * update() (this "residue" method is for legacy support only). 4236 * additionalData additional authentication data as a binary-encoded 4237 * string of bytes, for 'GCM' mode, (default: none). 4238 * tagLength desired length of authentication tag, in bits, for 4239 * 'GCM' mode (0-128, default: 128). 4240 * tag the authentication tag to check if decrypting, as a 4241 * binary-encoded string of bytes. 4242 * output the output the buffer to write to, null to create one. 4243 */ 4244BlockCipher.prototype.start = function(options) { 4245 options = options || {}; 4246 var opts = {}; 4247 for(var key in options) { 4248 opts[key] = options[key]; 4249 } 4250 opts.decrypt = this._decrypt; 4251 this._finish = false; 4252 this._input = forge.util.createBuffer(); 4253 this.output = options.output || forge.util.createBuffer(); 4254 this.mode.start(opts); 4255}; 4256 4257/** 4258 * Updates the next block according to the cipher mode. 4259 * 4260 * @param input the buffer to read from. 4261 */ 4262BlockCipher.prototype.update = function(input) { 4263 if(input) { 4264 // input given, so empty it into the input buffer 4265 this._input.putBuffer(input); 4266 } 4267 4268 // do cipher operation until it needs more input and not finished 4269 while(!this._op.call(this.mode, this._input, this.output, this._finish) && 4270 !this._finish) {} 4271 4272 // free consumed memory from input buffer 4273 this._input.compact(); 4274}; 4275 4276/** 4277 * Finishes encrypting or decrypting. 4278 * 4279 * @param pad a padding function to use in CBC mode, null for default, 4280 * signature(blockSize, buffer, decrypt). 4281 * 4282 * @return true if successful, false on error. 4283 */ 4284BlockCipher.prototype.finish = function(pad) { 4285 // backwards-compatibility w/deprecated padding API 4286 // Note: will overwrite padding functions even after another start() call 4287 if(pad && (this.mode.name === 'ECB' || this.mode.name === 'CBC')) { 4288 this.mode.pad = function(input) { 4289 return pad(this.blockSize, input, false); 4290 }; 4291 this.mode.unpad = function(output) { 4292 return pad(this.blockSize, output, true); 4293 }; 4294 } 4295 4296 // build options for padding and afterFinish functions 4297 var options = {}; 4298 options.decrypt = this._decrypt; 4299 4300 // get # of bytes that won't fill a block 4301 options.overflow = this._input.length() % this.blockSize; 4302 4303 if(!this._decrypt && this.mode.pad) { 4304 if(!this.mode.pad(this._input, options)) { 4305 return false; 4306 } 4307 } 4308 4309 // do final update 4310 this._finish = true; 4311 this.update(); 4312 4313 if(this._decrypt && this.mode.unpad) { 4314 if(!this.mode.unpad(this.output, options)) { 4315 return false; 4316 } 4317 } 4318 4319 if(this.mode.afterFinish) { 4320 if(!this.mode.afterFinish(this.output, options)) { 4321 return false; 4322 } 4323 } 4324 4325 return true; 4326}; 4327 4328 4329} // end module implementation 4330 4331/* ########## Begin module wrapper ########## */ 4332var name = 'cipher'; 4333if(typeof define !== 'function') { 4334 // NodeJS -> AMD 4335 if(typeof module === 'object' && module.exports) { 4336 var nodeJS = true; 4337 define = function(ids, factory) { 4338 factory(require, module); 4339 }; 4340 } else { 4341 // <script> 4342 if(typeof forge === 'undefined') { 4343 forge = {}; 4344 } 4345 return initModule(forge); 4346 } 4347} 4348// AMD 4349var deps;
4350var defineFunc = function(require, module) { 4351 module.exports = function(forge) { 4352 var mods = deps.map(function(dep) { 4353 return require(dep); 4354 }).concat(initModule); 4355 // handle circular dependencies 4356 forge = forge || {}; 4357 forge.defined = forge.defined || {}; 4358 if(forge.defined[name]) { 4359 return forge[name]; 4360 } 4361 forge.defined[name] = true; 4362 for(var i = 0; i < mods.length; ++i) { 4363 mods[i](forge); 4364 } 4365 return forge[name]; 4366 }; 4367}; 4368var tmpDefine = define; 4369define = function(ids, factory) { 4370 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 4371 if(nodeJS) { 4372 delete define; 4373 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 4374 } 4375 define = tmpDefine; 4376 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 4377}; 4378define(['require', 'module', './util'], function() { 4379 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 4380}); 4381})(); 4382 4383/** 4384 * Supported cipher modes. 4385 * 4386 * @author Dave Longley 4387 * 4388 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 4389 */ 4390(function() { 4391/* ########## Begin module implementation ########## */ 4392function initModule(forge) { 4393 4394forge.cipher = forge.cipher || {}; 4395 4396// supported cipher modes 4397var modes = forge.cipher.modes = forge.cipher.modes || {}; 4398 4399 4400/** Electronic codebook (ECB) (Don't use this; it's not secure) **/ 4401 4402modes.ecb = function(options) { 4403 options = options || {}; 4404 this.name = 'ECB'; 4405 this.cipher = options.cipher; 4406 this.blockSize = options.blockSize || 16; 4407 this._ints = this.blockSize / 4; 4408 this._inBlock = new Array(this._ints); 4409 this._outBlock = new Array(this._ints); 4410}; 4411 4412modes.ecb.prototype.start = function(options) {}; 4413 4414modes.ecb.prototype.encrypt = function(input, output, finish) { 4415 // not enough input to encrypt 4416 if(input.length() < this.blockSize && !(finish && input.length() > 0)) { 4417 return true; 4418 } 4419 4420 // get next block 4421 for(var i = 0; i < this._ints; ++i) { 4422 this._inBlock[i] = input.getInt32(); 4423 } 4424 4425 // encrypt block 4426 this.cipher.encrypt(this._inBlock, this._outBlock); 4427 4428 // write output 4429 for(var i = 0; i < this._ints; ++i) { 4430 output.putInt32(this._outBlock[i]); 4431 } 4432}; 4433 4434modes.ecb.prototype.decrypt = function(input, output, finish) { 4435 // not enough input to decrypt 4436 if(input.length() < this.blockSize && !(finish && input.length() > 0)) { 4437 return true; 4438 } 4439 4440 // get next block 4441 for(var i = 0; i < this._ints; ++i) { 4442 this._inBlock[i] = input.getInt32(); 4443 } 4444 4445 // decrypt block 4446 this.cipher.decrypt(this._inBlock, this._outBlock); 4447 4448 // write output 4449 for(var i = 0; i < this._ints; ++i) { 4450 output.putInt32(this._outBlock[i]); 4451 } 4452}; 4453 4454modes.ecb.prototype.pad = function(input, options) { 4455 // add PKCS#7 padding to block (each pad byte is the 4456 // value of the number of pad bytes) 4457 var padding = (input.length() === this.blockSize ? 4458 this.blockSize : (this.blockSize - input.length())); 4459 input.fillWithByte(padding, padding); 4460 return true; 4461}; 4462 4463modes.ecb.prototype.unpad = function(output, options) { 4464 // check for error: input data not a multiple of blockSize 4465 if(options.overflow > 0) { 4466 return false; 4467 } 4468 4469 // ensure padding byte count is valid 4470 var len = output.length(); 4471 var count = output.at(len - 1); 4472 if(count > (this.blockSize << 2)) { 4473 return false; 4474 } 4475 4476 // trim off padding bytes 4477 output.truncate(count); 4478 return true; 4479}; 4480 4481 4482/** Cipher-block Chaining (CBC) **/ 4483 4484modes.cbc = function(options) { 4485 options = options || {}; 4486 this.name = 'CBC'; 4487 this.cipher = options.cipher; 4488 this.blockSize = options.blockSize || 16; 4489 this._ints = this.blockSize / 4; 4490 this._inBlock = new Array(this._ints); 4491 this._outBlock = new Array(this._ints); 4492}; 4493 4494modes.cbc.prototype.start = function(options) { 4495 // Note: legacy support for using IV residue (has security flaws) 4496 // if IV is null, reuse block from previous processing 4497 if(options.iv === null) { 4498 // must have a previous block 4499 if(!this._prev) { 4500 throw new Error('Invalid IV parameter.'); 4501 } 4502 this._iv = this._prev.slice(0); 4503 } else if(!('iv' in options)) { 4504 throw new Error('Invalid IV parameter.'); 4505 } else { 4506 // save IV as "previous" block 4507 this._iv = transformIV(options.iv); 4508 this._prev = this._iv.slice(0); 4509 } 4510}; 4511 4512modes.cbc.prototype.encrypt = function(input, output, finish) { 4513 // not enough input to encrypt 4514 if(input.length() < this.blockSize && !(finish && input.length() > 0)) { 4515 return true; 4516 } 4517 4518 // get next block 4519 // CBC XOR's IV (or previous block) with plaintext 4520 for(var i = 0; i < this._ints; ++i) { 4521 this._inBlock[i] = this._prev[i] ^ input.getInt32(); 4522 } 4523 4524 // encrypt block 4525 this.cipher.encrypt(this._inBlock, this._outBlock); 4526 4527 // write output, save previous block 4528 for(var i = 0; i < this._ints; ++i) { 4529 output.putInt32(this._outBlock[i]); 4530 } 4531 this._prev = this._outBlock; 4532}; 4533 4534modes.cbc.prototype.decrypt = function(input, output, finish) { 4535 // not enough input to decrypt 4536 if(input.length() < this.blockSize && !(finish && input.length() > 0)) { 4537 return true; 4538 } 4539 4540 // get next block 4541 for(var i = 0; i < this._ints; ++i) { 4542 this._inBlock[i] = input.getInt32(); 4543 } 4544 4545 // decrypt block 4546 this.cipher.decrypt(this._inBlock, this._outBlock); 4547 4548 // write output, save previous ciphered block 4549 // CBC XOR's IV (or previous block) with ciphertext 4550 for(var i = 0; i < this._ints; ++i) { 4551 output.putInt32(this._prev[i] ^ this._outBlock[i]); 4552 } 4553 this._prev = this._inBlock.slice(0); 4554}; 4555 4556modes.cbc.prototype.pad = function(input, options) { 4557 // add PKCS#7 padding to block (each pad byte is the 4558 // value of the number of pad bytes) 4559 var padding = (input.length() === this.blockSize ? 4560 this.blockSize : (this.blockSize - input.length())); 4561 input.fillWithByte(padding, padding); 4562 return true; 4563}; 4564 4565modes.cbc.prototype.unpad = function(output, options) { 4566 // check for error: input data not a multiple of blockSize 4567 if(options.overflow > 0) { 4568 return false;
4569 } 4570 4571 // ensure padding byte count is valid 4572 var len = output.length(); 4573 var count = output.at(len - 1); 4574 if(count > (this.blockSize << 2)) { 4575 return false; 4576 } 4577 4578 // trim off padding bytes 4579 output.truncate(count); 4580 return true; 4581}; 4582 4583 4584/** Cipher feedback (CFB) **/ 4585 4586modes.cfb = function(options) { 4587 options = options || {}; 4588 this.name = 'CFB'; 4589 this.cipher = options.cipher; 4590 this.blockSize = options.blockSize || 16; 4591 this._ints = this.blockSize / 4; 4592 this._inBlock = null; 4593 this._outBlock = new Array(this._ints); 4594 this._partialBlock = new Array(this._ints); 4595 this._partialOutput = forge.util.createBuffer(); 4596 this._partialBytes = 0; 4597}; 4598 4599modes.cfb.prototype.start = function(options) { 4600 if(!('iv' in options)) { 4601 throw new Error('Invalid IV parameter.'); 4602 } 4603 // use IV as first input 4604 this._iv = transformIV(options.iv); 4605 this._inBlock = this._iv.slice(0); 4606 this._partialBytes = 0; 4607}; 4608 4609modes.cfb.prototype.encrypt = function(input, output, finish) { 4610 // not enough input to encrypt 4611 var inputLength = input.length(); 4612 if(inputLength === 0) { 4613 return true; 4614 } 4615 4616 // encrypt block 4617 this.cipher.encrypt(this._inBlock, this._outBlock); 4618 4619 // handle full block 4620 if(this._partialBytes === 0 && inputLength >= this.blockSize) { 4621 // XOR input with output, write input as output 4622 for(var i = 0; i < this._ints; ++i) { 4623 this._inBlock[i] = input.getInt32() ^ this._outBlock[i]; 4624 output.putInt32(this._inBlock[i]); 4625 } 4626 return; 4627 } 4628 4629 // handle partial block 4630 var partialBytes = (this.blockSize - inputLength) % this.blockSize; 4631 if(partialBytes > 0) { 4632 partialBytes = this.blockSize - partialBytes; 4633 } 4634 4635 // XOR input with output, write input as partial output 4636 this._partialOutput.clear(); 4637 for(var i = 0; i < this._ints; ++i) { 4638 this._partialBlock[i] = input.getInt32() ^ this._outBlock[i]; 4639 this._partialOutput.putInt32(this._partialBlock[i]); 4640 } 4641 4642 if(partialBytes > 0) { 4643 // block still incomplete, restore input buffer 4644 input.read -= this.blockSize; 4645 } else { 4646 // block complete, update input block 4647 for(var i = 0; i < this._ints; ++i) { 4648 this._inBlock[i] = this._partialBlock[i]; 4649 } 4650 } 4651 4652 // skip any previous partial bytes 4653 if(this._partialBytes > 0) { 4654 this._partialOutput.getBytes(this._partialBytes); 4655 } 4656 4657 if(partialBytes > 0 && !finish) { 4658 output.putBytes(this._partialOutput.getBytes( 4659 partialBytes - this._partialBytes)); 4660 this._partialBytes = partialBytes; 4661 return true; 4662 } 4663 4664 output.putBytes(this._partialOutput.getBytes( 4665 inputLength - this._partialBytes)); 4666 this._partialBytes = 0; 4667}; 4668 4669modes.cfb.prototype.decrypt = function(input, output, finish) { 4670 // not enough input to decrypt 4671 var inputLength = input.length(); 4672 if(inputLength === 0) { 4673 return true; 4674 } 4675 4676 // encrypt block (CFB always uses encryption mode) 4677 this.cipher.encrypt(this._inBlock, this._outBlock); 4678 4679 // handle full block 4680 if(this._partialBytes === 0 && inputLength >= this.blockSize) { 4681 // XOR input with output, write input as output 4682 for(var i = 0; i < this._ints; ++i) { 4683 this._inBlock[i] = input.getInt32(); 4684 output.putInt32(this._inBlock[i] ^ this._outBlock[i]); 4685 } 4686 return; 4687 } 4688 4689 // handle partial block 4690 var partialBytes = (this.blockSize - inputLength) % this.blockSize; 4691 if(partialBytes > 0) { 4692 partialBytes = this.blockSize - partialBytes; 4693 } 4694 4695 // XOR input with output, write input as partial output 4696 this._partialOutput.clear(); 4697 for(var i = 0; i < this._ints; ++i) { 4698 this._partialBlock[i] = input.getInt32(); 4699 this._partialOutput.putInt32(this._partialBlock[i] ^ this._outBlock[i]); 4700 } 4701 4702 if(partialBytes > 0) { 4703 // block still incomplete, restore input buffer 4704 input.read -= this.blockSize; 4705 } else { 4706 // block complete, update input block 4707 for(var i = 0; i < this._ints; ++i) { 4708 this._inBlock[i] = this._partialBlock[i]; 4709 } 4710 } 4711 4712 // skip any previous partial bytes 4713 if(this._partialBytes > 0) { 4714 this._partialOutput.getBytes(this._partialBytes); 4715 } 4716 4717 if(partialBytes > 0 && !finish) { 4718 output.putBytes(this._partialOutput.getBytes( 4719 partialBytes - this._partialBytes)); 4720 this._partialBytes = partialBytes; 4721 return true; 4722 } 4723 4724 output.putBytes(this._partialOutput.getBytes( 4725 inputLength - this._partialBytes)); 4726 this._partialBytes = 0; 4727}; 4728 4729/** Output feedback (OFB) **/ 4730 4731modes.ofb = function(options) { 4732 options = options || {}; 4733 this.name = 'OFB'; 4734 this.cipher = options.cipher; 4735 this.blockSize = options.blockSize || 16; 4736 this._ints = this.blockSize / 4; 4737 this._inBlock = null; 4738 this._outBlock = new Array(this._ints); 4739 this._partialOutput = forge.util.createBuffer(); 4740 this._partialBytes = 0; 4741}; 4742 4743modes.ofb.prototype.start = function(options) { 4744 if(!('iv' in options)) { 4745 throw new Error('Invalid IV parameter.'); 4746 } 4747 // use IV as first input 4748 this._iv = transformIV(options.iv); 4749 this._inBlock = this._iv.slice(0); 4750 this._partialBytes = 0; 4751}; 4752 4753modes.ofb.prototype.encrypt = function(input, output, finish) { 4754 // not enough input to encrypt 4755 var inputLength = input.length(); 4756 if(input.length() === 0) { 4757 return true; 4758 } 4759 4760 // encrypt block (OFB always uses encryption mode) 4761 this.cipher.encrypt(this._inBlock, this._outBlock); 4762 4763 // handle full block 4764 if(this._partialBytes === 0 && inputLength >= this.blockSize) { 4765 // XOR input with output and update next input 4766 for(var i = 0; i < this._ints; ++i) { 4767 output.putInt32(input.getInt32() ^ this._outBlock[i]); 4768 this._inBlock[i] = this._outBlock[i]; 4769 } 4770 return; 4771 } 4772 4773 // handle partial block 4774 var partialBytes = (this.blockSize - inputLength) % this.blockSize; 4775 if(partialBytes > 0) { 4776 partialBytes = this.blockSize - partialBytes; 4777 } 4778 4779 // XOR input with output 4780 this._partialOutput.clear(); 4781 for(var i = 0; i < this._ints; ++i) { 4782 this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); 4783 } 4784 4785 if(partialBytes > 0) { 4786 // block still incomplete, restore input buffer 4787 input.read -= this.blockSize; 4788 } else { 4789 // block complete, update input block 4790 for(var i = 0; i < this._ints; ++i) { 4791 this._inBlock[i] = this._outBlock[i]; 4792 } 4793 } 4794
4795 // skip any previous partial bytes 4796 if(this._partialBytes > 0) { 4797 this._partialOutput.getBytes(this._partialBytes); 4798 } 4799 4800 if(partialBytes > 0 && !finish) { 4801 output.putBytes(this._partialOutput.getBytes( 4802 partialBytes - this._partialBytes)); 4803 this._partialBytes = partialBytes; 4804 return true; 4805 } 4806 4807 output.putBytes(this._partialOutput.getBytes( 4808 inputLength - this._partialBytes)); 4809 this._partialBytes = 0; 4810}; 4811 4812modes.ofb.prototype.decrypt = modes.ofb.prototype.encrypt; 4813 4814 4815/** Counter (CTR) **/ 4816 4817modes.ctr = function(options) { 4818 options = options || {}; 4819 this.name = 'CTR'; 4820 this.cipher = options.cipher; 4821 this.blockSize = options.blockSize || 16; 4822 this._ints = this.blockSize / 4; 4823 this._inBlock = null; 4824 this._outBlock = new Array(this._ints); 4825 this._partialOutput = forge.util.createBuffer(); 4826 this._partialBytes = 0; 4827}; 4828 4829modes.ctr.prototype.start = function(options) { 4830 if(!('iv' in options)) { 4831 throw new Error('Invalid IV parameter.'); 4832 } 4833 // use IV as first input 4834 this._iv = transformIV(options.iv); 4835 this._inBlock = this._iv.slice(0); 4836 this._partialBytes = 0; 4837}; 4838 4839modes.ctr.prototype.encrypt = function(input, output, finish) { 4840 // not enough input to encrypt 4841 var inputLength = input.length(); 4842 if(inputLength === 0) { 4843 return true; 4844 } 4845 4846 // encrypt block (CTR always uses encryption mode) 4847 this.cipher.encrypt(this._inBlock, this._outBlock); 4848 4849 // handle full block 4850 if(this._partialBytes === 0 && inputLength >= this.blockSize) { 4851 // XOR input with output 4852 for(var i = 0; i < this._ints; ++i) { 4853 output.putInt32(input.getInt32() ^ this._outBlock[i]); 4854 } 4855 } else { 4856 // handle partial block 4857 var partialBytes = (this.blockSize - inputLength) % this.blockSize; 4858 if(partialBytes > 0) { 4859 partialBytes = this.blockSize - partialBytes; 4860 } 4861 4862 // XOR input with output 4863 this._partialOutput.clear(); 4864 for(var i = 0; i < this._ints; ++i) { 4865 this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); 4866 } 4867 4868 if(partialBytes > 0) { 4869 // block still incomplete, restore input buffer 4870 input.read -= this.blockSize; 4871 } 4872 4873 // skip any previous partial bytes 4874 if(this._partialBytes > 0) { 4875 this._partialOutput.getBytes(this._partialBytes); 4876 } 4877 4878 if(partialBytes > 0 && !finish) { 4879 output.putBytes(this._partialOutput.getBytes( 4880 partialBytes - this._partialBytes)); 4881 this._partialBytes = partialBytes; 4882 return true; 4883 } 4884 4885 output.putBytes(this._partialOutput.getBytes( 4886 inputLength - this._partialBytes)); 4887 this._partialBytes = 0; 4888 } 4889 4890 // block complete, increment counter (input block) 4891 inc32(this._inBlock); 4892}; 4893 4894modes.ctr.prototype.decrypt = modes.ctr.prototype.encrypt; 4895 4896 4897/** Galois/Counter Mode (GCM) **/ 4898 4899modes.gcm = function(options) { 4900 options = options || {}; 4901 this.name = 'GCM'; 4902 this.cipher = options.cipher; 4903 this.blockSize = options.blockSize || 16; 4904 this._ints = this.blockSize / 4; 4905 this._inBlock = new Array(this._ints); 4906 this._outBlock = new Array(this._ints); 4907 this._partialOutput = forge.util.createBuffer(); 4908 this._partialBytes = 0; 4909 4910 // R is actually this value concatenated with 120 more zero bits, but 4911 // we only XOR against R so the other zeros have no effect -- we just 4912 // apply this value to the first integer in a block 4913 this._R = 0xE1000000; 4914}; 4915 4916modes.gcm.prototype.start = function(options) { 4917 if(!('iv' in options)) { 4918 throw new Error('Invalid IV parameter.'); 4919 } 4920 // ensure IV is a byte buffer 4921 var iv = forge.util.createBuffer(options.iv); 4922 4923 // no ciphered data processed yet 4924 this._cipherLength = 0; 4925 4926 // default additional data is none 4927 var additionalData; 4928 if('additionalData' in options) { 4929 additionalData = forge.util.createBuffer(options.additionalData); 4930 } else { 4931 additionalData = forge.util.createBuffer(); 4932 } 4933 4934 // default tag length is 128 bits 4935 if('tagLength' in options) { 4936 this._tagLength = options.tagLength; 4937 } else { 4938 this._tagLength = 128; 4939 } 4940 4941 // if tag is given, ensure tag matches tag length 4942 this._tag = null; 4943 if(options.decrypt) { 4944 // save tag to check later 4945 this._tag = forge.util.createBuffer(options.tag).getBytes(); 4946 if(this._tag.length !== (this._tagLength / 8)) { 4947 throw new Error('Authentication tag does not match tag length.'); 4948 } 4949 } 4950 4951 // create tmp storage for hash calculation 4952 this._hashBlock = new Array(this._ints); 4953 4954 // no tag generated yet 4955 this.tag = null; 4956 4957 // generate hash subkey 4958 // (apply block cipher to "zero" block) 4959 this._hashSubkey = new Array(this._ints); 4960 this.cipher.encrypt([0, 0, 0, 0], this._hashSubkey); 4961 4962 // generate table M 4963 // use 4-bit tables (32 component decomposition of a 16 byte value) 4964 // 8-bit tables take more space and are known to have security 4965 // vulnerabilities (in native implementations) 4966 this.componentBits = 4; 4967 this._m = this.generateHashTable(this._hashSubkey, this.componentBits); 4968 4969 // Note: support IV length different from 96 bits? (only supporting 4970 // 96 bits is recommended by NIST SP-800-38D) 4971 // generate J_0 4972 var ivLength = iv.length(); 4973 if(ivLength === 12) { 4974 // 96-bit IV 4975 this._j0 = [iv.getInt32(), iv.getInt32(), iv.getInt32(), 1]; 4976 } else { 4977 // IV is NOT 96-bits 4978 this._j0 = [0, 0, 0, 0]; 4979 while(iv.length() > 0) { 4980 this._j0 = this.ghash( 4981 this._hashSubkey, this._j0, 4982 [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()]); 4983 } 4984 this._j0 = this.ghash( 4985 this._hashSubkey, this._j0, [0, 0].concat(from64To32(ivLength * 8))); 4986 } 4987 4988 // generate ICB (initial counter block) 4989 this._inBlock = this._j0.slice(0); 4990 inc32(this._inBlock); 4991 this._partialBytes = 0; 4992 4993 // consume authentication data 4994 additionalData = forge.util.createBuffer(additionalData); 4995 // save additional data length as a BE 64-bit number 4996 this._aDataLength = from64To32(additionalData.length() * 8); 4997 // pad additional data to 128 bit (16 byte) block size 4998 var overflow = additionalData.length() % this.blockSize; 4999 if(overflow) { 5000 additionalData.fillWithByte(0, this.blockSize - overflow); 5001 } 5002 this._s = [0, 0, 0, 0]; 5003 while(additionalData.length() > 0) { 5004 this._s = this.ghash(this._hashSubkey, this._s, [ 5005 additionalData.getInt32(), 5006 additionalData.getInt32(), 5007 additionalData.getInt32(), 5008 additionalData.getInt32() 5009 ]); 5010 } 5011}; 5012 5013modes.gcm.prototype.encrypt = function(input, output, finish) { 5014 // not enough input to encrypt 5015 var inputLength = input.length(); 5016 if(inputLength === 0) { 5017 return true; 5018 } 5019 5020 // encrypt block 5021 this.cipher.encrypt(this._inBlock, this._outBlock); 5022 5023 // handle full block 5024 if(this._partialBytes === 0 && inputLength >= this.blockSize) { 5025 // XOR input with output 5026 for(var i = 0; i < this._ints; ++i) { 5027 output.putInt32(this._outBlock[i] ^= input.getInt32()); 5028 } 5029 this._cipherLength += this.blockSize; 5030 } else { 5031 // handle partial block 5032 var partialBytes = (this.blockSize - inputLength) % this.blockSize; 5033 if(partialBytes > 0) { 5034 partialBytes = this.blockSize - partialBytes; 5035 } 5036 5037 // XOR input with output 5038 this._partialOutput.clear(); 5039 for(var i = 0; i < this._ints; ++i) { 5040 this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); 5041 } 5042 5043 if(partialBytes === 0 || finish) { 5044 // handle overflow prior to hashing 5045 if(finish) { 5046 // get block overflow 5047 var overflow = inputLength % this.blockSize; 5048 this._cipherLength += overflow; 5049 // truncate for hash function 5050 this._partialOutput.truncate(this.blockSize - overflow); 5051 } else { 5052 this._cipherLength += this.blockSize; 5053 } 5054 5055 // get output block for hashing 5056 for(var i = 0; i < this._ints; ++i) { 5057 this._outBlock[i] = this._partialOutput.getInt32(); 5058 } 5059 this._partialOutput.read -= this.blockSize; 5060 } 5061 5062 // skip any previous partial bytes 5063 if(this._partialBytes > 0) { 5064 this._partialOutput.getBytes(this._partialBytes); 5065 } 5066 5067 if(partialBytes > 0 && !finish) { 5068 // block still incomplete, restore input buffer, get partial output, 5069 // and return early 5070 input.read -= this.blockSize; 5071 output.putBytes(this._partialOutput.getBytes( 5072 partialBytes - this._partialBytes)); 5073 this._partialBytes = partialBytes; 5074 return true; 5075 } 5076 5077 output.putBytes(this._partialOutput.getBytes( 5078 inputLength - this._partialBytes)); 5079 this._partialBytes = 0; 5080 } 5081 5082 // update hash block S 5083 this._s = this.ghash(this._hashSubkey, this._s, this._outBlock); 5084 5085 // increment counter (input block) 5086 inc32(this._inBlock); 5087}; 5088 5089modes.gcm.prototype.decrypt = function(input, output, finish) { 5090 // not enough input to decrypt 5091 var inputLength = input.length(); 5092 if(inputLength < this.blockSize && !(finish && inputLength > 0)) { 5093 return true; 5094 } 5095 5096 // encrypt block (GCM always uses encryption mode) 5097 this.cipher.encrypt(this._inBlock, this._outBlock); 5098 5099 // increment counter (input block) 5100 inc32(this._inBlock); 5101 5102 // update hash block S 5103 this._hashBlock[0] = input.getInt32(); 5104 this._hashBlock[1] = input.getInt32(); 5105 this._hashBlock[2] = input.getInt32(); 5106 this._hashBlock[3] = input.getInt32(); 5107 this._s = this.ghash(this._hashSubkey, this._s, this._hashBlock); 5108 5109 // XOR hash input with output 5110 for(var i = 0; i < this._ints; ++i) { 5111 output.putInt32(this._outBlock[i] ^ this._hashBlock[i]); 5112 } 5113 5114 // increment cipher data length 5115 if(inputLength < this.blockSize) {
5116 this._cipherLength += inputLength % this.blockSize; 5117 } else { 5118 this._cipherLength += this.blockSize; 5119 } 5120}; 5121 5122modes.gcm.prototype.afterFinish = function(output, options) { 5123 var rval = true; 5124 5125 // handle overflow 5126 if(options.decrypt && options.overflow) { 5127 output.truncate(this.blockSize - options.overflow); 5128 } 5129 5130 // handle authentication tag 5131 this.tag = forge.util.createBuffer(); 5132 5133 // concatenate additional data length with cipher length 5134 var lengths = this._aDataLength.concat(from64To32(this._cipherLength * 8)); 5135 5136 // include lengths in hash 5137 this._s = this.ghash(this._hashSubkey, this._s, lengths); 5138 5139 // do GCTR(J_0, S) 5140 var tag = []; 5141 this.cipher.encrypt(this._j0, tag); 5142 for(var i = 0; i < this._ints; ++i) { 5143 this.tag.putInt32(this._s[i] ^ tag[i]); 5144 } 5145 5146 // trim tag to length 5147 this.tag.truncate(this.tag.length() % (this._tagLength / 8)); 5148 5149 // check authentication tag 5150 if(options.decrypt && this.tag.bytes() !== this._tag) { 5151 rval = false; 5152 } 5153 5154 return rval; 5155}; 5156 5157/** 5158 * See NIST SP-800-38D 6.3 (Algorithm 1). This function performs Galois 5159 * field multiplication. The field, GF(2^128), is defined by the polynomial: 5160 * 5161 * x^128 + x^7 + x^2 + x + 1 5162 * 5163 * Which is represented in little-endian binary form as: 11100001 (0xe1). When 5164 * the value of a coefficient is 1, a bit is set. The value R, is the 5165 * concatenation of this value and 120 zero bits, yielding a 128-bit value 5166 * which matches the block size. 5167 * 5168 * This function will multiply two elements (vectors of bytes), X and Y, in 5169 * the field GF(2^128). The result is initialized to zero. For each bit of 5170 * X (out of 128), x_i, if x_i is set, then the result is multiplied (XOR'd) 5171 * by the current value of Y. For each bit, the value of Y will be raised by 5172 * a power of x (multiplied by the polynomial x). This can be achieved by 5173 * shifting Y once to the right. If the current value of Y, prior to being 5174 * multiplied by x, has 0 as its LSB, then it is a 127th degree polynomial. 5175 * Otherwise, we must divide by R after shifting to find the remainder. 5176 * 5177 * @param x the first block to multiply by the second. 5178 * @param y the second block to multiply by the first. 5179 * 5180 * @return the block result of the multiplication. 5181 */ 5182modes.gcm.prototype.multiply = function(x, y) { 5183 var z_i = [0, 0, 0, 0]; 5184 var v_i = y.slice(0); 5185 5186 // calculate Z_128 (block has 128 bits) 5187 for(var i = 0; i < 128; ++i) { 5188 // if x_i is 0, Z_{i+1} = Z_i (unchanged) 5189 // else Z_{i+1} = Z_i ^ V_i 5190 // get x_i by finding 32-bit int position, then left shift 1 by remainder 5191 var x_i = x[(i / 32) | 0] & (1 << (31 - i % 32)); 5192 if(x_i) { 5193 z_i[0] ^= v_i[0]; 5194 z_i[1] ^= v_i[1]; 5195 z_i[2] ^= v_i[2]; 5196 z_i[3] ^= v_i[3]; 5197 } 5198 5199 // if LSB(V_i) is 1, V_i = V_i >> 1 5200 // else V_i = (V_i >> 1) ^ R 5201 this.pow(v_i, v_i); 5202 } 5203 5204 return z_i; 5205}; 5206 5207modes.gcm.prototype.pow = function(x, out) { 5208 // if LSB(x) is 1, x = x >>> 1 5209 // else x = (x >>> 1) ^ R 5210 var lsb = x[3] & 1; 5211 5212 // always do x >>> 1: 5213 // starting with the rightmost integer, shift each integer to the right 5214 // one bit, pulling in the bit from the integer to the left as its top 5215 // most bit (do this for the last 3 integers) 5216 for(var i = 3; i > 0; --i) { 5217 out[i] = (x[i] >>> 1) | ((x[i - 1] & 1) << 31); 5218 } 5219 // shift the first integer normally 5220 out[0] = x[0] >>> 1; 5221 5222 // if lsb was not set, then polynomial had a degree of 127 and doesn't 5223 // need to divided; otherwise, XOR with R to find the remainder; we only 5224 // need to XOR the first integer since R technically ends w/120 zero bits 5225 if(lsb) { 5226 out[0] ^= this._R; 5227 } 5228}; 5229 5230modes.gcm.prototype.tableMultiply = function(x) { 5231 // assumes 4-bit tables are used 5232 var z = [0, 0, 0, 0]; 5233 for(var i = 0; i < 32; ++i) { 5234 var idx = (i / 8) | 0; 5235 var x_i = (x[idx] >>> ((7 - (i % 8)) * 4)) & 0xF; 5236 var ah = this._m[i][x_i]; 5237 z[0] ^= ah[0]; 5238 z[1] ^= ah[1]; 5239 z[2] ^= ah[2]; 5240 z[3] ^= ah[3]; 5241 } 5242 return z; 5243}; 5244 5245/** 5246 * A continuing version of the GHASH algorithm that operates on a single 5247 * block. The hash block, last hash value (Ym) and the new block to hash 5248 * are given. 5249 * 5250 * @param h the hash block. 5251 * @param y the previous value for Ym, use [0, 0, 0, 0] for a new hash. 5252 * @param x the block to hash. 5253 * 5254 * @return the hashed value (Ym). 5255 */ 5256modes.gcm.prototype.ghash = function(h, y, x) { 5257 y[0] ^= x[0]; 5258 y[1] ^= x[1]; 5259 y[2] ^= x[2]; 5260 y[3] ^= x[3]; 5261 return this.tableMultiply(y); 5262 //return this.multiply(y, h); 5263}; 5264 5265/** 5266 * Precomputes a table for multiplying against the hash subkey. This 5267 * mechanism provides a substantial speed increase over multiplication 5268 * performed without a table. The table-based multiplication this table is 5269 * for solves X * H by multiplying each component of X by H and then 5270 * composing the results together using XOR. 5271 * 5272 * This function can be used to generate tables with different bit sizes 5273 * for the components, however, this implementation assumes there are 5274 * 32 components of X (which is a 16 byte vector), therefore each component 5275 * takes 4-bits (so the table is constructed with bits=4). 5276 * 5277 * @param h the hash subkey. 5278 * @param bits the bit size for a component. 5279 */ 5280modes.gcm.prototype.generateHashTable = function(h, bits) { 5281 // TODO: There are further optimizations that would use only the 5282 // first table M_0 (or some variant) along with a remainder table; 5283 // this can be explored in the future 5284 var multiplier = 8 / bits; 5285 var perInt = 4 * multiplier; 5286 var size = 16 * multiplier; 5287 var m = new Array(size); 5288 for(var i = 0; i < size; ++i) { 5289 var tmp = [0, 0, 0, 0]; 5290 var idx = (i / perInt) | 0; 5291 var shft = ((perInt - 1 - (i % perInt)) * bits); 5292 tmp[idx] = (1 << (bits - 1)) << shft; 5293 m[i] = this.generateSubHashTable(this.multiply(tmp, h), bits); 5294 } 5295 return m; 5296}; 5297 5298/** 5299 * Generates a table for multiplying against the hash subkey for one 5300 * particular component (out of all possible component values). 5301 * 5302 * @param mid the pre-multiplied value for the middle key of the table. 5303 * @param bits the bit size for a component. 5304 */ 5305modes.gcm.prototype.generateSubHashTable = function(mid, bits) { 5306 // compute the table quickly by minimizing the number of 5307 // POW operations -- they only need to be performed for powers of 2, 5308 // all other entries can be composed from those powers using XOR 5309 var size = 1 << bits; 5310 var half = size >>> 1; 5311 var m = new Array(size); 5312 m[half] = mid.slice(0); 5313 var i = half >>> 1; 5314 while(i > 0) { 5315 // raise m0[2 * i] and store in m0[i] 5316 this.pow(m[2 * i], m[i] = []); 5317 i >>= 1; 5318 } 5319 i = 2; 5320 while(i < half) { 5321 for(var j = 1; j < i; ++j) { 5322 var m_i = m[i]; 5323 var m_j = m[j]; 5324 m[i + j] = [ 5325 m_i[0] ^ m_j[0], 5326 m_i[1] ^ m_j[1], 5327 m_i[2] ^ m_j[2], 5328 m_i[3] ^ m_j[3] 5329 ]; 5330 } 5331 i *= 2; 5332 } 5333 m[0] = [0, 0, 0, 0]; 5334 /* Note: We could avoid storing these by doing composition during multiply 5335 calculate top half using composition by speed is preferred. */ 5336 for(i = half + 1; i < size; ++i) { 5337 var c = m[i ^ half]; 5338 m[i] = [mid[0] ^ c[0], mid[1] ^ c[1], mid[2] ^ c[2], mid[3] ^ c[3]]; 5339 } 5340 return m; 5341}; 5342 5343 5344/** Utility functions */ 5345 5346function transformIV(iv) { 5347 if(typeof iv === 'string') { 5348 // convert iv string into byte buffer 5349 iv = forge.util.createBuffer(iv); 5350 } 5351 5352 if(forge.util.isArray(iv) && iv.length > 4) { 5353 // convert iv byte array into byte buffer 5354 var tmp = iv; 5355 iv = forge.util.createBuffer(); 5356 for(var i = 0; i < tmp.length; ++i) { 5357 iv.putByte(tmp[i]); 5358 } 5359 } 5360 if(!forge.util.isArray(iv)) { 5361 // convert iv byte buffer into 32-bit integer array 5362 iv = [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()]; 5363 } 5364 5365 return iv; 5366} 5367 5368function inc32(block) { 5369 // increment last 32 bits of block only 5370 block[block.length - 1] = (block[block.length - 1] + 1) & 0xFFFFFFFF; 5371} 5372 5373function from64To32(num) { 5374 // convert 64-bit number to two BE Int32s 5375 return [(num / 0x100000000) | 0, num & 0xFFFFFFFF]; 5376} 5377 5378 5379} // end module implementation 5380 5381/* ########## Begin module wrapper ########## */ 5382var name = 'cipherModes'; 5383if(typeof define !== 'function') { 5384 // NodeJS -> AMD 5385 if(typeof module === 'object' && module.exports) { 5386 var nodeJS = true; 5387 define = function(ids, factory) { 5388 factory(require, module); 5389 }; 5390 } else { 5391 // <script> 5392 if(typeof forge === 'undefined') { 5393 forge = {}; 5394 } 5395 return initModule(forge); 5396 } 5397} 5398// AMD 5399var deps;
5400var defineFunc = function(require, module) { 5401 module.exports = function(forge) { 5402 var mods = deps.map(function(dep) { 5403 return require(dep); 5404 }).concat(initModule); 5405 // handle circular dependencies 5406 forge = forge || {}; 5407 forge.defined = forge.defined || {}; 5408 if(forge.defined[name]) { 5409 return forge[name]; 5410 } 5411 forge.defined[name] = true; 5412 for(var i = 0; i < mods.length; ++i) { 5413 mods[i](forge); 5414 } 5415 return forge[name]; 5416 }; 5417}; 5418var tmpDefine = define; 5419define = function(ids, factory) { 5420 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 5421 if(nodeJS) { 5422 delete define; 5423 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 5424 } 5425 define = tmpDefine; 5426 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 5427}; 5428define(['require', 'module', './util'], function() { 5429 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 5430}); 5431})(); 5432 5433/** 5434 * RC2 implementation. 5435 * 5436 * @author Stefan Siegl 5437 * 5438 * Copyright (c) 2012 Stefan Siegl <[email protected]> 5439 * 5440 * Information on the RC2 cipher is available from RFC #2268, 5441 * http://www.ietf.org/rfc/rfc2268.txt 5442 */ 5443(function() { 5444/* ########## Begin module implementation ########## */ 5445function initModule(forge) { 5446 5447var piTable = [ 5448 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 5449 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 5450 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, 5451 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 5452 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
5453 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 5454 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, 5455 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 5456 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 5457 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, 5458 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 5459 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 5460 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 5461 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 5462 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 5463 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad 5464]; 5465 5466var s = [1, 2, 3, 5]; 5467 5468 5469/** 5470 * Rotate a word left by given number of bits. 5471 * 5472 * Bits that are shifted out on the left are put back in on the right 5473 * hand side. 5474 * 5475 * @param word The word to shift left. 5476 * @param bits The number of bits to shift by. 5477 * @return The rotated word. 5478 */ 5479var rol = function(word, bits) { 5480 return ((word << bits) & 0xffff) | ((word & 0xffff) >> (16 - bits)); 5481}; 5482 5483/** 5484 * Rotate a word right by given number of bits. 5485 * 5486 * Bits that are shifted out on the right are put back in on the left 5487 * hand side. 5488 * 5489 * @param word The word to shift right. 5490 * @param bits The number of bits to shift by. 5491 * @return The rotated word. 5492 */ 5493var ror = function(word, bits) { 5494 return ((word & 0xffff) >> bits) | ((word << (16 - bits)) & 0xffff); 5495}; 5496 5497 5498/* RC2 API */ 5499forge.rc2 = forge.rc2 || {}; 5500 5501/** 5502 * Perform RC2 key expansion as per RFC #2268, section 2. 5503 * 5504 * @param key variable-length user key (between 1 and 128 bytes) 5505 * @param effKeyBits number of effective key bits (default: 128) 5506 * @return the expanded RC2 key (ByteBuffer of 128 bytes) 5507 */ 5508forge.rc2.expandKey = function(key, effKeyBits) { 5509 if(typeof key === 'string') { 5510 key = forge.util.createBuffer(key); 5511 } 5512 effKeyBits = effKeyBits || 128; 5513 5514 /* introduce variables that match the names used in RFC #2268 */ 5515 var L = key; 5516 var T = key.length(); 5517 var T1 = effKeyBits; 5518 var T8 = Math.ceil(T1 / 8); 5519 var TM = 0xff >> (T1 & 0x07); 5520 var i; 5521 5522 for(i = T; i < 128; i ++) { 5523 L.putByte(piTable[(L.at(i - 1) + L.at(i - T)) & 0xff]); 5524 } 5525 5526 L.setAt(128 - T8, piTable[L.at(128 - T8) & TM]); 5527 5528 for(i = 127 - T8; i >= 0; i --) { 5529 L.setAt(i, piTable[L.at(i + 1) ^ L.at(i + T8)]); 5530 } 5531 5532 return L; 5533}; 5534 5535 5536/** 5537 * Creates a RC2 cipher object. 5538 * 5539 * @param key the symmetric key to use (as base for key generation). 5540 * @param bits the number of effective key bits. 5541 * @param encrypt false for decryption, true for encryption. 5542 * 5543 * @return the cipher. 5544 */ 5545var createCipher = function(key, bits, encrypt) { 5546 var _finish = false, _input = null, _output = null, _iv = null; 5547 var mixRound, mashRound; 5548 var i, j, K = []; 5549 5550 /* Expand key and fill into K[] Array */ 5551 key = forge.rc2.expandKey(key, bits); 5552 for(i = 0; i < 64; i ++) { 5553 K.push(key.getInt16Le()); 5554 } 5555 5556 if(encrypt) { 5557 /** 5558 * Perform one mixing round "in place". 5559 * 5560 * @param R Array of four words to perform mixing on. 5561 */ 5562 mixRound = function(R) { 5563 for(i = 0; i < 4; i++) { 5564 R[i] += K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + 5565 ((~R[(i + 3) % 4]) & R[(i + 1) % 4]); 5566 R[i] = rol(R[i], s[i]); 5567 j ++; 5568 } 5569 }; 5570 5571 /** 5572 * Perform one mashing round "in place". 5573 * 5574 * @param R Array of four words to perform mashing on. 5575 */ 5576 mashRound = function(R) { 5577 for(i = 0; i < 4; i ++) { 5578 R[i] += K[R[(i + 3) % 4] & 63]; 5579 } 5580 }; 5581 } else { 5582 /** 5583 * Perform one r-mixing round "in place". 5584 * 5585 * @param R Array of four words to perform mixing on. 5586 */ 5587 mixRound = function(R) { 5588 for(i = 3; i >= 0; i--) {
5589 R[i] = ror(R[i], s[i]); 5590 R[i] -= K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + 5591 ((~R[(i + 3) % 4]) & R[(i + 1) % 4]); 5592 j --; 5593 } 5594 }; 5595 5596 /** 5597 * Perform one r-mashing round "in place". 5598 * 5599 * @param R Array of four words to perform mashing on. 5600 */ 5601 mashRound = function(R) { 5602 for(i = 3; i >= 0; i--) { 5603 R[i] -= K[R[(i + 3) % 4] & 63]; 5604 } 5605 }; 5606 } 5607 5608 /** 5609 * Run the specified cipher execution plan. 5610 * 5611 * This function takes four words from the input buffer, applies the IV on 5612 * it (if requested) and runs the provided execution plan. 5613 * 5614 * The plan must be put together in form of a array of arrays. Where the 5615 * outer one is simply a list of steps to perform and the inner one needs 5616 * to have two elements: the first one telling how many rounds to perform, 5617 * the second one telling what to do (i.e. the function to call). 5618 * 5619 * @param {Array} plan The plan to execute. 5620 */ 5621 var runPlan = function(plan) { 5622 var R = []; 5623 5624 /* Get data from input buffer and fill the four words into R */ 5625 for(i = 0; i < 4; i ++) { 5626 var val = _input.getInt16Le(); 5627 5628 if(_iv !== null) { 5629 if(encrypt) { 5630 /* We're encrypting, apply the IV first. */ 5631 val ^= _iv.getInt16Le(); 5632 } else { 5633 /* We're decryption, keep cipher text for next block. */ 5634 _iv.putInt16Le(val); 5635 } 5636 } 5637 5638 R.push(val & 0xffff); 5639 } 5640 5641 /* Reset global "j" variable as per spec. */ 5642 j = encrypt ? 0 : 63; 5643 5644 /* Run execution plan. */ 5645 for(var ptr = 0; ptr < plan.length; ptr ++) { 5646 for(var ctr = 0; ctr < plan[ptr][0]; ctr ++) { 5647 plan[ptr][1](R); 5648 } 5649 } 5650 5651 /* Write back result to output buffer. */ 5652 for(i = 0; i < 4; i ++) { 5653 if(_iv !== null) { 5654 if(encrypt) { 5655 /* We're encrypting in CBC-mode, feed back encrypted bytes into 5656 IV buffer to carry it forward to next block. */ 5657 _iv.putInt16Le(R[i]); 5658 } else { 5659 R[i] ^= _iv.getInt16Le(); 5660 } 5661 } 5662 5663 _output.putInt16Le(R[i]); 5664 } 5665 }; 5666 5667 5668 /* Create cipher object */ 5669 var cipher = null; 5670 cipher = { 5671 /** 5672 * Starts or restarts the encryption or decryption process, whichever 5673 * was previously configured. 5674 * 5675 * To use the cipher in CBC mode, iv may be given either as a string 5676 * of bytes, or as a byte buffer. For ECB mode, give null as iv. 5677 * 5678 * @param iv the initialization vector to use, null for ECB mode. 5679 * @param output the output the buffer to write to, null to create one. 5680 */ 5681 start: function(iv, output) { 5682 if(iv) { 5683 /* CBC mode */ 5684 if(typeof iv === 'string') { 5685 iv = forge.util.createBuffer(iv); 5686 } 5687 } 5688 5689 _finish = false; 5690 _input = forge.util.createBuffer(); 5691 _output = output || new forge.util.createBuffer(); 5692 _iv = iv; 5693 5694 cipher.output = _output; 5695 }, 5696 5697 /** 5698 * Updates the next block. 5699 * 5700 * @param input the buffer to read from. 5701 */ 5702 update: function(input) { 5703 if(!_finish) { 5704 // not finishing, so fill the input buffer with more input 5705 _input.putBuffer(input); 5706 } 5707 5708 while(_input.length() >= 8) { 5709 runPlan([ 5710 [ 5, mixRound ], 5711 [ 1, mashRound ], 5712 [ 6, mixRound ], 5713 [ 1, mashRound ], 5714 [ 5, mixRound ] 5715 ]); 5716 } 5717 }, 5718 5719 /** 5720 * Finishes encrypting or decrypting. 5721 * 5722 * @param pad a padding function to use, null for PKCS#7 padding, 5723 * signature(blockSize, buffer, decrypt). 5724 * 5725 * @return true if successful, false on error. 5726 */ 5727 finish: function(pad) { 5728 var rval = true; 5729 5730 if(encrypt) { 5731 if(pad) { 5732 rval = pad(8, _input, !encrypt); 5733 } else { 5734 // add PKCS#7 padding to block (each pad byte is the 5735 // value of the number of pad bytes) 5736 var padding = (_input.length() === 8) ? 8 : (8 - _input.length()); 5737 _input.fillWithByte(padding, padding); 5738 } 5739 } 5740 5741 if(rval) { 5742 // do final update 5743 _finish = true;
5744 cipher.update(); 5745 } 5746 5747 if(!encrypt) { 5748 // check for error: input data not a multiple of block size 5749 rval = (_input.length() === 0); 5750 if(rval) { 5751 if(pad) { 5752 rval = pad(8, _output, !encrypt); 5753 } else { 5754 // ensure padding byte count is valid 5755 var len = _output.length(); 5756 var count = _output.at(len - 1); 5757 5758 if(count > len) { 5759 rval = false; 5760 } else { 5761 // trim off padding bytes 5762 _output.truncate(count); 5763 } 5764 } 5765 } 5766 } 5767 5768 return rval; 5769 } 5770 }; 5771 5772 return cipher; 5773}; 5774 5775 5776/** 5777 * Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the 5778 * given symmetric key. The output will be stored in the 'output' member 5779 * of the returned cipher. 5780 * 5781 * The key and iv may be given as a string of bytes or a byte buffer. 5782 * The cipher is initialized to use 128 effective key bits. 5783 * 5784 * @param key the symmetric key to use. 5785 * @param iv the initialization vector to use. 5786 * @param output the buffer to write to, null to create one. 5787 * 5788 * @return the cipher. 5789 */ 5790forge.rc2.startEncrypting = function(key, iv, output) { 5791 var cipher = forge.rc2.createEncryptionCipher(key, 128); 5792 cipher.start(iv, output); 5793 return cipher; 5794}; 5795 5796/** 5797 * Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the 5798 * given symmetric key. 5799 * 5800 * The key may be given as a string of bytes or a byte buffer. 5801 * 5802 * To start encrypting call start() on the cipher with an iv and optional 5803 * output buffer. 5804 * 5805 * @param key the symmetric key to use. 5806 * 5807 * @return the cipher. 5808 */ 5809forge.rc2.createEncryptionCipher = function(key, bits) { 5810 return createCipher(key, bits, true); 5811}; 5812 5813/** 5814 * Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the 5815 * given symmetric key. The output will be stored in the 'output' member 5816 * of the returned cipher. 5817 * 5818 * The key and iv may be given as a string of bytes or a byte buffer. 5819 * The cipher is initialized to use 128 effective key bits. 5820 * 5821 * @param key the symmetric key to use. 5822 * @param iv the initialization vector to use. 5823 * @param output the buffer to write to, null to create one. 5824 * 5825 * @return the cipher. 5826 */ 5827forge.rc2.startDecrypting = function(key, iv, output) { 5828 var cipher = forge.rc2.createDecryptionCipher(key, 128); 5829 cipher.start(iv, output); 5830 return cipher; 5831}; 5832 5833/** 5834 * Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the 5835 * given symmetric key. 5836 * 5837 * The key may be given as a string of bytes or a byte buffer. 5838 * 5839 * To start decrypting call start() on the cipher with an iv and optional 5840 * output buffer. 5841 * 5842 * @param key the symmetric key to use. 5843 * 5844 * @return the cipher. 5845 */ 5846forge.rc2.createDecryptionCipher = function(key, bits) { 5847 return createCipher(key, bits, false); 5848}; 5849 5850} // end module implementation 5851 5852/* ########## Begin module wrapper ########## */ 5853var name = 'rc2'; 5854if(typeof define !== 'function') { 5855 // NodeJS -> AMD 5856 if(typeof module === 'object' && module.exports) { 5857 var nodeJS = true; 5858 define = function(ids, factory) { 5859 factory(require, module); 5860 }; 5861 } else { 5862 // <script> 5863 if(typeof forge === 'undefined') { 5864 forge = {}; 5865 } 5866 return initModule(forge); 5867 } 5868} 5869// AMD 5870var deps; 5871var defineFunc = function(require, module) { 5872 module.exports = function(forge) { 5873 var mods = deps.map(function(dep) { 5874 return require(dep); 5875 }).concat(initModule); 5876 // handle circular dependencies 5877 forge = forge || {}; 5878 forge.defined = forge.defined || {}; 5879 if(forge.defined[name]) { 5880 return forge[name]; 5881 } 5882 forge.defined[name] = true; 5883 for(var i = 0; i < mods.length; ++i) { 5884 mods[i](forge); 5885 } 5886 return forge[name]; 5887 }; 5888}; 5889var tmpDefine = define; 5890define = function(ids, factory) { 5891 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 5892 if(nodeJS) { 5893 delete define; 5894 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 5895 } 5896 define = tmpDefine; 5897 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 5898}; 5899define(['require', 'module', './util'], function() { 5900 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 5901}); 5902})(); 5903 5904/** 5905 * DES (Data Encryption Standard) implementation. 5906 * 5907 * This implementation supports DES as well as 3DES-EDE in ECB and CBC mode.
5908 * It is based on the BSD-licensed implementation by Paul Tero: 5909 * 5910 * Paul Tero, July 2001 5911 * http://www.tero.co.uk/des/ 5912 * 5913 * Optimised for performance with large blocks by Michael Hayworth, November 2001 5914 * http://www.netdealing.com 5915 * 5916 * THIS SOFTWARE IS PROVIDED "AS IS" AND 5917 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5918 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5919 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 5920 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5921 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5922 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5923 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5924 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5925 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5926 * SUCH DAMAGE. 5927 * 5928 * @author Stefan Siegl 5929 * @author Dave Longley 5930 * 5931 * Copyright (c) 2012 Stefan Siegl <[email protected]> 5932 * Copyright (c) 2012-2014 Digital Bazaar, Inc. 5933 */ 5934(function() { 5935/* ########## Begin module implementation ########## */ 5936function initModule(forge) { 5937 5938/* DES API */ 5939forge.des = forge.des || {}; 5940 5941/** 5942 * Deprecated. Instead, use: 5943 * 5944 * var cipher = forge.cipher.createCipher('DES-<mode>', key); 5945 * cipher.start({iv: iv}); 5946 * 5947 * Creates an DES cipher object to encrypt data using the given symmetric key. 5948 * The output will be stored in the 'output' member of the returned cipher. 5949 * 5950 * The key and iv may be given as binary-encoded strings of bytes or 5951 * byte buffers. 5952 * 5953 * @param key the symmetric key to use (64 or 192 bits). 5954 * @param iv the initialization vector to use. 5955 * @param output the buffer to write to, null to create one. 5956 * @param mode the cipher mode to use (default: 'CBC' if IV is 5957 * given, 'ECB' if null). 5958 * 5959 * @return the cipher. 5960 */ 5961forge.des.startEncrypting = function(key, iv, output, mode) { 5962 var cipher = _createCipher({ 5963 key: key, 5964 output: output, 5965 decrypt: false, 5966 mode: mode || (iv === null ? 'ECB' : 'CBC') 5967 }); 5968 cipher.start(iv); 5969 return cipher; 5970}; 5971 5972/** 5973 * Deprecated. Instead, use: 5974 * 5975 * var cipher = forge.cipher.createCipher('DES-<mode>', key); 5976 * 5977 * Creates an DES cipher object to encrypt data using the given symmetric key. 5978 * 5979 * The key may be given as a binary-encoded string of bytes or a byte buffer. 5980 * 5981 * @param key the symmetric key to use (64 or 192 bits). 5982 * @param mode the cipher mode to use (default: 'CBC'). 5983 * 5984 * @return the cipher. 5985 */ 5986forge.des.createEncryptionCipher = function(key, mode) { 5987 return _createCipher({ 5988 key: key, 5989 output: null, 5990 decrypt: false, 5991 mode: mode 5992 }); 5993}; 5994 5995/** 5996 * Deprecated. Instead, use: 5997 * 5998 * var decipher = forge.cipher.createDecipher('DES-<mode>', key); 5999 * decipher.start({iv: iv}); 6000 * 6001 * Creates an DES cipher object to decrypt data using the given symmetric key. 6002 * The output will be stored in the 'output' member of the returned cipher. 6003 * 6004 * The key and iv may be given as binary-encoded strings of bytes or 6005 * byte buffers. 6006 * 6007 * @param key the symmetric key to use (64 or 192 bits). 6008 * @param iv the initialization vector to use. 6009 * @param output the buffer to write to, null to create one. 6010 * @param mode the cipher mode to use (default: 'CBC' if IV is 6011 * given, 'ECB' if null). 6012 * 6013 * @return the cipher. 6014 */ 6015forge.des.startDecrypting = function(key, iv, output, mode) { 6016 var cipher = _createCipher({ 6017 key: key, 6018 output: output, 6019 decrypt: true, 6020 mode: mode || (iv === null ? 'ECB' : 'CBC') 6021 }); 6022 cipher.start(iv); 6023 return cipher; 6024}; 6025 6026/** 6027 * Deprecated. Instead, use: 6028 * 6029 * var decipher = forge.cipher.createDecipher('DES-<mode>', key); 6030 * 6031 * Creates an DES cipher object to decrypt data using the given symmetric key. 6032 * 6033 * The key may be given as a binary-encoded string of bytes or a byte buffer. 6034 * 6035 * @param key the symmetric key to use (64 or 192 bits). 6036 * @param mode the cipher mode to use (default: 'CBC'). 6037 * 6038 * @return the cipher. 6039 */ 6040forge.des.createDecryptionCipher = function(key, mode) { 6041 return _createCipher({ 6042 key: key, 6043 output: null, 6044 decrypt: true, 6045 mode: mode 6046 }); 6047}; 6048 6049/** 6050 * Creates a new DES cipher algorithm object. 6051 * 6052 * @param name the name of the algorithm. 6053 * @param mode the mode factory function. 6054 * 6055 * @return the DES algorithm object. 6056 */ 6057forge.des.Algorithm = function(name, mode) { 6058 var self = this; 6059 self.name = name; 6060 self.mode = new mode({ 6061 blockSize: 8, 6062 cipher: { 6063 encrypt: function(inBlock, outBlock) { 6064 return _updateBlock(self._keys, inBlock, outBlock, false); 6065 }, 6066 decrypt: function(inBlock, outBlock) { 6067 return _updateBlock(self._keys, inBlock, outBlock, true); 6068 } 6069 } 6070 }); 6071 self._init = false;
6072}; 6073 6074/** 6075 * Initializes this DES algorithm by expanding its key. 6076 * 6077 * @param options the options to use. 6078 * key the key to use with this algorithm. 6079 * decrypt true if the algorithm should be initialized for decryption, 6080 * false for encryption. 6081 */ 6082forge.des.Algorithm.prototype.initialize = function(options) { 6083 if(this._init) { 6084 return; 6085 } 6086 6087 var key = forge.util.createBuffer(options.key); 6088 if(this.name.indexOf('3DES') === 0) { 6089 if(key.length() !== 24) { 6090 throw new Error('Invalid Triple-DES key size: ' + key.length() * 8); 6091 } 6092 } 6093 6094 // do key expansion to 16 or 48 subkeys (single or triple DES) 6095 this._keys = _createKeys(key); 6096 this._init = true; 6097}; 6098 6099 6100/** Register DES algorithms **/ 6101 6102registerAlgorithm('DES-ECB', forge.cipher.modes.ecb); 6103registerAlgorithm('DES-CBC', forge.cipher.modes.cbc); 6104registerAlgorithm('DES-CFB', forge.cipher.modes.cfb); 6105registerAlgorithm('DES-OFB', forge.cipher.modes.ofb); 6106registerAlgorithm('DES-CTR', forge.cipher.modes.ctr); 6107 6108registerAlgorithm('3DES-ECB', forge.cipher.modes.ecb); 6109registerAlgorithm('3DES-CBC', forge.cipher.modes.cbc); 6110registerAlgorithm('3DES-CFB', forge.cipher.modes.cfb); 6111registerAlgorithm('3DES-OFB', forge.cipher.modes.ofb); 6112registerAlgorithm('3DES-CTR', forge.cipher.modes.ctr); 6113 6114function registerAlgorithm(name, mode) { 6115 var factory = function() { 6116 return new forge.des.Algorithm(name, mode); 6117 }; 6118 forge.cipher.registerAlgorithm(name, factory); 6119} 6120 6121 6122/** DES implementation **/ 6123 6124var spfunction1 = [0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004]; 6125var spfunction2 = [-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000]; 6126var spfunction3 = [0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200]; 6127var spfunction4 = [0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080]; 6128var spfunction5 = [0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,
61280x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100]; 6129var spfunction6 = [0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010]; 6130var spfunction7 = [0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002]; 6131var spfunction8 = [0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000]; 6132 6133/** 6134 * Create necessary sub keys. 6135 * 6136 * @param key the 64-bit or 192-bit key. 6137 * 6138 * @return the expanded keys. 6139 */ 6140function _createKeys(key) { 6141 var pc2bytes0 = [0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x2
614100,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204], 6142 pc2bytes1 = [0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101], 6143 pc2bytes2 = [0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808], 6144 pc2bytes3 = [0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000], 6145 pc2bytes4 = [0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010], 6146 pc2bytes5 = [0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420], 6147 pc2bytes6 = [0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002], 6148 pc2bytes7 = [0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800], 6149 pc2bytes8 = [0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002], 6150 pc2bytes9 = [0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408], 6151 pc2bytes10 = [0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020], 6152 pc2bytes11 = [0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200], 6153 pc2bytes12 = [0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010], 6154 pc2bytes13 = [0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105]; 6155 6156 // how many iterations (1 for des, 3 for triple des) 6157 // changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys 6158 var iterations = key.length() > 8 ? 3 : 1; 6159 6160 // stores the return keys 6161 var keys = []; 6162 6163 // now define the left shifts which need to be done 6164 var shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; 6165 6166 var n = 0, tmp; 6167 for(var j = 0; j < iterations; j ++) { 6168 var left = key.getInt32(); 6169 var right = key.getInt32(); 6170 6171 tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f; 6172 right ^= tmp; 6173 left ^= (tmp << 4); 6174 6175 tmp = ((right >>> -16) ^ left) & 0x0000ffff; 6176 left ^= tmp; 6177 right ^= (tmp << -16); 6178 6179 tmp = ((left >>> 2) ^ right) & 0x33333333; 6180 right ^= tmp; 6181 left ^= (tmp << 2); 6182 6183 tmp = ((right >>> -16) ^ left) & 0x0000ffff; 6184 left ^= tmp; 6185 right ^= (tmp << -16); 6186 6187 tmp = ((left >>> 1) ^ right) & 0x55555555; 6188 right ^= tmp; 6189 left ^= (tmp << 1); 6190 6191 tmp = ((right >>> 8) ^ left) & 0x00ff00ff; 6192 left ^= tmp; 6193 right ^= (tmp << 8); 6194 6195 tmp = ((left >>> 1) ^ right) & 0x55555555; 6196 right ^= tmp; 6197 left ^= (tmp << 1); 6198 6199 // right needs to be shifted and OR'd with last four bits of left 6200 tmp = (left << 8) | ((right >>> 20) & 0x000000f0); 6201 6202 // left needs to be put upside down 6203 left = ((right << 24) | ((right << 8) & 0xff0000) | 6204 ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0)); 6205 right = tmp; 6206 6207 // now go through and perform these shifts on the left and right keys 6208 for(var i = 0; i < shifts.length; ++i) {
6209 //shift the keys either one or two bits to the left 6210 if(shifts[i]) { 6211 left = (left << 2) | (left >>> 26); 6212 right = (right << 2) | (right >>> 26); 6213 } else { 6214 left = (left << 1) | (left >>> 27); 6215 right = (right << 1) | (right >>> 27); 6216 } 6217 left &= -0xf; 6218 right &= -0xf; 6219 6220 // now apply PC-2, in such a way that E is easier when encrypting or 6221 // decrypting this conversion will look like PC-2 except only the last 6 6222 // bits of each byte are used rather than 48 consecutive bits and the 6223 // order of lines will be according to how the S selection functions will 6224 // be applied: S2, S4, S6, S8, S1, S3, S5, S7 6225 var lefttmp = ( 6226 pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | 6227 pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf] | 6228 pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | 6229 pc2bytes6[(left >>> 4) & 0xf]); 6230 var righttmp = ( 6231 pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | 6232 pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf] | 6233 pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | 6234 pc2bytes13[(right >>> 4) & 0xf]); 6235 tmp = ((righttmp >>> 16) ^ lefttmp) & 0x0000ffff; 6236 keys[n++] = lefttmp ^ tmp; 6237 keys[n++] = righttmp ^ (tmp << 16); 6238 } 6239 } 6240 6241 return keys; 6242} 6243 6244/** 6245 * Updates a single block (1 byte) using DES. The update will either 6246 * encrypt or decrypt the block. 6247 * 6248 * @param keys the expanded keys. 6249 * @param input the input block (an array of 32-bit words). 6250 * @param output the updated output block. 6251 * @param decrypt true to decrypt the block, false to encrypt it. 6252 */ 6253function _updateBlock(keys, input, output, decrypt) { 6254 // set up loops for single or triple DES 6255 var iterations = keys.length === 32 ? 3 : 9; 6256 var looping; 6257 if(iterations === 3) { 6258 looping = decrypt ? [30, -2, -2] : [0, 32, 2]; 6259 } else { 6260 looping = (decrypt ? 6261 [94, 62, -2, 32, 64, 2, 30, -2, -2] : 6262 [0, 32, 2, 62, 30, -2, 64, 96, 2]); 6263 } 6264 6265 var tmp; 6266 6267 var left = input[0]; 6268 var right = input[1]; 6269 6270 // first each 64 bit chunk of the message must be permuted according to IP 6271 tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f; 6272 right ^= tmp; 6273 left ^= (tmp << 4); 6274 6275 tmp = ((left >>> 16) ^ right) & 0x0000ffff; 6276 right ^= tmp; 6277 left ^= (tmp << 16); 6278 6279 tmp = ((right >>> 2) ^ left) & 0x33333333; 6280 left ^= tmp; 6281 right ^= (tmp << 2); 6282 6283 tmp = ((right >>> 8) ^ left) & 0x00ff00ff; 6284 left ^= tmp; 6285 right ^= (tmp << 8); 6286 6287 tmp = ((left >>> 1) ^ right) & 0x55555555; 6288 right ^= tmp; 6289 left ^= (tmp << 1); 6290 6291 // rotate left 1 bit 6292 left = ((left << 1) | (left >>> 31)); 6293 right = ((right << 1) | (right >>> 31)); 6294 6295 for(var j = 0; j < iterations; j += 3) { 6296 var endloop = looping[j + 1]; 6297 var loopinc = looping[j + 2]; 6298 6299 // now go through and perform the encryption or decryption 6300 for(var i = looping[j]; i != endloop; i += loopinc) { 6301 var right1 = right ^ keys[i]; 6302 var right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; 6303 6304 // passing these bytes through the S selection functions 6305 tmp = left; 6306 left = right; 6307 right = tmp ^ ( 6308 spfunction2[(right1 >>> 24) & 0x3f] | 6309 spfunction4[(right1 >>> 16) & 0x3f] | 6310 spfunction6[(right1 >>> 8) & 0x3f] | 6311 spfunction8[right1 & 0x3f] | 6312 spfunction1[(right2 >>> 24) & 0x3f] | 6313 spfunction3[(right2 >>> 16) & 0x3f] | 6314 spfunction5[(right2 >>> 8) & 0x3f] | 6315 spfunction7[right2 & 0x3f]); 6316 } 6317 // unreverse left and right 6318 tmp = left; 6319 left = right; 6320 right = tmp; 6321 } 6322 6323 // rotate right 1 bit 6324 left = ((left >>> 1) | (left << 31)); 6325 right = ((right >>> 1) | (right << 31)); 6326 6327 // now perform IP-1, which is IP in the opposite direction 6328 tmp = ((left >>> 1) ^ right) & 0x55555555; 6329 right ^= tmp; 6330 left ^= (tmp << 1); 6331 6332 tmp = ((right >>> 8) ^ left) & 0x00ff00ff; 6333 left ^= tmp; 6334 right ^= (tmp << 8); 6335 6336 tmp = ((right >>> 2) ^ left) & 0x33333333; 6337 left ^= tmp; 6338 right ^= (tmp << 2); 6339 6340 tmp = ((left >>> 16) ^ right) & 0x0000ffff; 6341 right ^= tmp; 6342 left ^= (tmp << 16); 6343 6344 tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f; 6345 right ^= tmp; 6346 left ^= (tmp << 4); 6347 6348 output[0] = left; 6349 output[1] = right; 6350} 6351 6352/** 6353 * Deprecated. Instead, use: 6354 * 6355 * forge.cipher.createCipher('DES-<mode>', key); 6356 * forge.cipher.createDecipher('DES-<mode>', key); 6357 * 6358 * Creates a deprecated DES cipher object. This object's mode will default to 6359 * CBC (cipher-block-chaining). 6360 * 6361 * The key may be given as a binary-encoded string of bytes or a byte buffer. 6362 * 6363 * @param options the options to use. 6364 * key the symmetric key to use (64 or 192 bits). 6365 * output the buffer to write to. 6366 * decrypt true for decryption, false for encryption. 6367 * mode the cipher mode to use (default: 'CBC'). 6368 * 6369 * @return the cipher. 6370 */ 6371function _createCipher(options) { 6372 options = options || {}; 6373 var mode = (options.mode || 'CBC').toUpperCase(); 6374 var algorithm = 'DES-' + mode; 6375 6376 var cipher; 6377 if(options.decrypt) { 6378 cipher = forge.cipher.createDecipher(algorithm, options.key); 6379 } else { 6380 cipher = forge.cipher.createCipher(algorithm, options.key); 6381 } 6382 6383 // backwards compatible start API 6384 var start = cipher.start; 6385 cipher.start = function(iv, options) { 6386 // backwards compatibility: support second arg as output buffer 6387 var output = null; 6388 if(options instanceof forge.util.ByteBuffer) { 6389 output = options; 6390 options = {}; 6391 } 6392 options = options || {}; 6393 options.output = output; 6394 options.iv = iv; 6395 start.call(cipher, options); 6396 }; 6397 6398 return cipher; 6399} 6400 6401 6402} // end module implementation 6403 6404/* ########## Begin module wrapper ########## */
6405var name = 'des'; 6406if(typeof define !== 'function') { 6407 // NodeJS -> AMD 6408 if(typeof module === 'object' && module.exports) { 6409 var nodeJS = true; 6410 define = function(ids, factory) { 6411 factory(require, module); 6412 }; 6413 } else { 6414 // <script> 6415 if(typeof forge === 'undefined') { 6416 forge = {}; 6417 } 6418 return initModule(forge); 6419 } 6420} 6421// AMD 6422var deps; 6423var defineFunc = function(require, module) { 6424 module.exports = function(forge) { 6425 var mods = deps.map(function(dep) { 6426 return require(dep); 6427 }).concat(initModule); 6428 // handle circular dependencies 6429 forge = forge || {}; 6430 forge.defined = forge.defined || {}; 6431 if(forge.defined[name]) { 6432 return forge[name]; 6433 } 6434 forge.defined[name] = true; 6435 for(var i = 0; i < mods.length; ++i) { 6436 mods[i](forge); 6437 } 6438 return forge[name]; 6439 }; 6440}; 6441var tmpDefine = define; 6442define = function(ids, factory) { 6443 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 6444 if(nodeJS) { 6445 delete define; 6446 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 6447 } 6448 define = tmpDefine; 6449 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 6450}; 6451define( 6452 ['require', 'module', './cipher', './cipherModes', './util'], function() { 6453 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 6454}); 6455})(); 6456 6457/** 6458 * Advanced Encryption Standard (AES) implementation. 6459 * 6460 * This implementation is based on the public domain library 'jscrypto' which 6461 * was written by: 6462 * 6463 * Emily Stark ([email protected]) 6464 * Mike Hamburg ([email protected]) 6465 * Dan Boneh ([email protected]) 6466 * 6467 * Parts of this code are based on the OpenSSL implementation of AES: 6468 * http://www.openssl.org 6469 * 6470 * @author Dave Longley 6471 * 6472 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 6473 */ 6474(function() { 6475/* ########## Begin module implementation ########## */ 6476function initModule(forge) { 6477 6478/* AES API */ 6479forge.aes = forge.aes || {}; 6480 6481/** 6482 * Deprecated. Instead, use: 6483 * 6484 * var cipher = forge.cipher.createCipher('AES-<mode>', key); 6485 * cipher.start({iv: iv}); 6486 * 6487 * Creates an AES cipher object to encrypt data using the given symmetric key. 6488 * The output will be stored in the 'output' member of the returned cipher. 6489 * 6490 * The key and iv may be given as a string of bytes, an array of bytes, 6491 * a byte buffer, or an array of 32-bit words. 6492 * 6493 * @param key the symmetric key to use. 6494 * @param iv the initialization vector to use. 6495 * @param output the buffer to write to, null to create one. 6496 * @param mode the cipher mode to use (default: 'CBC'). 6497 * 6498 * @return the cipher. 6499 */ 6500forge.aes.startEncrypting = function(key, iv, output, mode) { 6501 var cipher = _createCipher({ 6502 key: key, 6503 output: output, 6504 decrypt: false, 6505 mode: mode 6506 }); 6507 cipher.start(iv); 6508 return cipher; 6509}; 6510 6511/** 6512 * Deprecated. Instead, use: 6513 * 6514 * var cipher = forge.cipher.createCipher('AES-<mode>', key); 6515 * 6516 * Creates an AES cipher object to encrypt data using the given symmetric key. 6517 * 6518 * The key may be given as a string of bytes, an array of bytes, a 6519 * byte buffer, or an array of 32-bit words. 6520 * 6521 * @param key the symmetric key to use. 6522 * @param mode the cipher mode to use (default: 'CBC'). 6523 * 6524 * @return the cipher. 6525 */ 6526forge.aes.createEncryptionCipher = function(key, mode) { 6527 return _createCipher({ 6528 key: key, 6529 output: null, 6530 decrypt: false, 6531 mode: mode 6532 }); 6533}; 6534 6535/** 6536 * Deprecated. Instead, use: 6537 * 6538 * var decipher = forge.cipher.createDecipher('AES-<mode>', key); 6539 * decipher.start({iv: iv}); 6540 * 6541 * Creates an AES cipher object to decrypt data using the given symmetric key. 6542 * The output will be stored in the 'output' member of the returned cipher. 6543 * 6544 * The key and iv may be given as a string of bytes, an array of bytes, 6545 * a byte buffer, or an array of 32-bit words. 6546 * 6547 * @param key the symmetric key to use. 6548 * @param iv the initialization vector to use. 6549 * @param output the buffer to write to, null to create one. 6550 * @param mode the cipher mode to use (default: 'CBC'). 6551 * 6552 * @return the cipher. 6553 */ 6554forge.aes.startDecrypting = function(key, iv, output, mode) { 6555 var cipher = _createCipher({ 6556 key: key, 6557 output: output, 6558 decrypt: true, 6559 mode: mode 6560 }); 6561 cipher.start(iv); 6562 return cipher; 6563}; 6564 6565/** 6566 * Deprecated. Instead, use: 6567 * 6568 * var decipher = forge.cipher.createDecipher('AES-<mode>', key); 6569 * 6570 * Creates an AES cipher object to decrypt data using the given symmetric key. 6571 * 6572 * The key may be given as a string of bytes, an array of bytes, a 6573 * byte buffer, or an array of 32-bit words. 6574 * 6575 * @param key the symmetric key to use. 6576 * @param mode the cipher mode to use (default: 'CBC'). 6577 * 6578 * @return the cipher. 6579 */ 6580forge.aes.createDecryptionCipher = function(key, mode) { 6581 return _createCipher({ 6582 key: key, 6583 output: null, 6584 decrypt: true, 6585 mode: mode 6586 }); 6587}; 6588 6589/** 6590 * Creates a new AES cipher algorithm object. 6591 * 6592 * @param name the name of the algorithm. 6593 * @param mode the mode factory function. 6594 * 6595 * @return the AES algorithm object. 6596 */ 6597forge.aes.Algorithm = function(name, mode) { 6598 if(!init) { 6599 initialize(); 6600 } 6601 var self = this; 6602 self.name = name; 6603 self.mode = new mode({ 6604 blockSize: 16, 6605 cipher: { 6606 encrypt: function(inBlock, outBlock) { 6607 return _updateBlock(self._w, inBlock, outBlock, false); 6608 }, 6609 decrypt: function(inBlock, outBlock) { 6610 return _updateBlock(self._w, inBlock, outBlock, true); 6611 } 6612 } 6613 }); 6614 self._init = false;
6615}; 6616 6617/** 6618 * Initializes this AES algorithm by expanding its key. 6619 * 6620 * @param options the options to use. 6621 * key the key to use with this algorithm. 6622 * decrypt true if the algorithm should be initialized for decryption, 6623 * false for encryption. 6624 */ 6625forge.aes.Algorithm.prototype.initialize = function(options) { 6626 if(this._init) { 6627 return; 6628 } 6629 6630 var key = options.key; 6631 var tmp; 6632 6633 /* Note: The key may be a string of bytes, an array of bytes, a byte 6634 buffer, or an array of 32-bit integers. If the key is in bytes, then 6635 it must be 16, 24, or 32 bytes in length. If it is in 32-bit 6636 integers, it must be 4, 6, or 8 integers long. */ 6637 6638 if(typeof key === 'string' && 6639 (key.length === 16 || key.length === 24 || key.length === 32)) { 6640 // convert key string into byte buffer 6641 key = forge.util.createBuffer(key); 6642 } else if(forge.util.isArray(key) && 6643 (key.length === 16 || key.length === 24 || key.length === 32)) { 6644 // convert key integer array into byte buffer 6645 tmp = key; 6646 key = forge.util.createBuffer(); 6647 for(var i = 0; i < tmp.length; ++i) { 6648 key.putByte(tmp[i]); 6649 } 6650 } 6651 6652 // convert key byte buffer into 32-bit integer array 6653 if(!forge.util.isArray(key)) { 6654 tmp = key; 6655 key = []; 6656 6657 // key lengths of 16, 24, 32 bytes allowed 6658 var len = tmp.length(); 6659 if(len === 16 || len === 24 || len === 32) { 6660 len = len >>> 2; 6661 for(var i = 0; i < len; ++i) { 6662 key.push(tmp.getInt32()); 6663 } 6664 } 6665 } 6666 6667 // key must be an array of 32-bit integers by now 6668 if(!forge.util.isArray(key) || 6669 !(key.length === 4 || key.length === 6 || key.length === 8)) { 6670 throw new Error('Invalid key parameter.'); 6671 } 6672 6673 // encryption operation is always used for these modes 6674 var mode = this.mode.name; 6675 var encryptOp = (['CFB', 'OFB', 'CTR', 'GCM'].indexOf(mode) !== -1); 6676 6677 // do key expansion 6678 this._w = _expandKey(key, options.decrypt && !encryptOp); 6679 this._init = true; 6680}; 6681 6682/** 6683 * Expands a key. Typically only used for testing. 6684 * 6685 * @param key the symmetric key to expand, as an array of 32-bit words. 6686 * @param decrypt true to expand for decryption, false for encryption. 6687 * 6688 * @return the expanded key. 6689 */ 6690forge.aes._expandKey = function(key, decrypt) { 6691 if(!init) { 6692 initialize(); 6693 } 6694 return _expandKey(key, decrypt); 6695}; 6696 6697/** 6698 * Updates a single block. Typically only used for testing. 6699 * 6700 * @param w the expanded key to use. 6701 * @param input an array of block-size 32-bit words. 6702 * @param output an array of block-size 32-bit words. 6703 * @param decrypt true to decrypt, false to encrypt. 6704 */ 6705forge.aes._updateBlock = _updateBlock; 6706 6707 6708/** Register AES algorithms **/ 6709 6710registerAlgorithm('AES-ECB', forge.cipher.modes.ecb); 6711registerAlgorithm('AES-CBC', forge.cipher.modes.cbc); 6712registerAlgorithm('AES-CFB', forge.cipher.modes.cfb); 6713registerAlgorithm('AES-OFB', forge.cipher.modes.ofb); 6714registerAlgorithm('AES-CTR', forge.cipher.modes.ctr); 6715registerAlgorithm('AES-GCM', forge.cipher.modes.gcm); 6716 6717function registerAlgorithm(name, mode) { 6718 var factory = function() { 6719 return new forge.aes.Algorithm(name, mode); 6720 }; 6721 forge.cipher.registerAlgorithm(name, factory); 6722} 6723 6724 6725/** AES implementation **/ 6726 6727var init = false; // not yet initialized 6728var Nb = 4; // number of words comprising the state (AES = 4) 6729var sbox; // non-linear substitution table used in key expansion 6730var isbox; // inversion of sbox 6731var rcon; // round constant word array 6732var mix; // mix-columns table 6733var imix; // inverse mix-columns table 6734 6735/** 6736 * Performs initialization, ie: precomputes tables to optimize for speed. 6737 * 6738 * One way to understand how AES works is to imagine that 'addition' and 6739 * 'multiplication' are interfaces that require certain mathematical 6740 * properties to hold true (ie: they are associative) but they might have 6741 * different implementations and produce different kinds of results ... 6742 * provided that their mathematical properties remain true. AES defines 6743 * its own methods of addition and multiplication but keeps some important 6744 * properties the same, ie: associativity and distributivity. The 6745 * explanation below tries to shed some light on how AES defines addition 6746 * and multiplication of bytes and 32-bit words in order to perform its 6747 * encryption and decryption algorithms. 6748 * 6749 * The basics: 6750 * 6751 * The AES algorithm views bytes as binary representations of polynomials 6752 * that have either 1 or 0 as the coefficients. It defines the addition 6753 * or subtraction of two bytes as the XOR operation. It also defines the 6754 * multiplication of two bytes as a finite field referred to as GF(2^8) 6755 * (Note: 'GF' means "Galois Field" which is a field that contains a finite 6756 * number of elements so GF(2^8) has 256 elements). 6757 * 6758 * This means that any two bytes can be represented as binary polynomials; 6759 * when they multiplied together and modularly reduced by an irreducible 6760 * polynomial of the 8th degree, the results are the field GF(2^8). The 6761 * specific irreducible polynomial that AES uses in hexadecimal is 0x11b. 6762 * This multiplication is associative with 0x01 as the identity: 6763 * 6764 * (b * 0x01 = GF(b, 0x01) = b). 6765 * 6766 * The operation GF(b, 0x02) can be performed at the byte level by left 6767 * shifting b once and then XOR'ing it (to perform the modular reduction) 6768 * with 0x11b if b is >= 128. Repeated application of the multiplication 6769 * of 0x02 can be used to implement the multiplication of any two bytes. 6770 * 6771 * For instance, multiplying 0x57 and 0x13, denoted as GF(0x57, 0x13), can 6772 * be performed by factoring 0x13 into 0x01, 0x02, and 0x10. Then these 6773 * factors can each be multiplied by 0x57 and then added together. To do 6774 * the multiplication, values for 0x57 multiplied by each of these 3 factors 6775 * can be precomputed and stored in a table. To add them, the values from 6776 * the table are XOR'd together. 6777 * 6778 * AES also defines addition and multiplication of words, that is 4-byte 6779 * numbers represented as polynomials of 3 degrees where the coefficients 6780 * are the values of the bytes. 6781 * 6782 * The word [a0, a1, a2, a3] is a polynomial a3x^3 + a2x^2 + a1x + a0. 6783 * 6784 * Addition is performed by XOR'ing like powers of x. Multiplication 6785 * is performed in two steps, the first is an algebriac expansion as
6786 * you would do normally (where addition is XOR). But the result is 6787 * a polynomial larger than 3 degrees and thus it cannot fit in a word. So 6788 * next the result is modularly reduced by an AES-specific polynomial of 6789 * degree 4 which will always produce a polynomial of less than 4 degrees 6790 * such that it will fit in a word. In AES, this polynomial is x^4 + 1. 6791 * 6792 * The modular product of two polynomials 'a' and 'b' is thus: 6793 * 6794 * d(x) = d3x^3 + d2x^2 + d1x + d0 6795 * with 6796 * d0 = GF(a0, b0) ^ GF(a3, b1) ^ GF(a2, b2) ^ GF(a1, b3) 6797 * d1 = GF(a1, b0) ^ GF(a0, b1) ^ GF(a3, b2) ^ GF(a2, b3) 6798 * d2 = GF(a2, b0) ^ GF(a1, b1) ^ GF(a0, b2) ^ GF(a3, b3) 6799 * d3 = GF(a3, b0) ^ GF(a2, b1) ^ GF(a1, b2) ^ GF(a0, b3) 6800 * 6801 * As a matrix: 6802 * 6803 * [d0] = [a0 a3 a2 a1][b0] 6804 * [d1] [a1 a0 a3 a2][b1] 6805 * [d2] [a2 a1 a0 a3][b2] 6806 * [d3] [a3 a2 a1 a0][b3] 6807 * 6808 * Special polynomials defined by AES (0x02 == {02}): 6809 * a(x) = {03}x^3 + {01}x^2 + {01}x + {02} 6810 * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. 6811 * 6812 * These polynomials are used in the MixColumns() and InverseMixColumns() 6813 * operations, respectively, to cause each element in the state to affect 6814 * the output (referred to as diffusing). 6815 * 6816 * RotWord() uses: a0 = a1 = a2 = {00} and a3 = {01}, which is the 6817 * polynomial x3. 6818 * 6819 * The ShiftRows() method modifies the last 3 rows in the state (where 6820 * the state is 4 words with 4 bytes per word) by shifting bytes cyclically. 6821 * The 1st byte in the second row is moved to the end of the row. The 1st 6822 * and 2nd bytes in the third row are moved to the end of the row. The 1st, 6823 * 2nd, and 3rd bytes are moved in the fourth row. 6824 * 6825 * More details on how AES arithmetic works: 6826 * 6827 * In the polynomial representation of binary numbers, XOR performs addition 6828 * and subtraction and multiplication in GF(2^8) denoted as GF(a, b) 6829 * corresponds with the multiplication of polynomials modulo an irreducible 6830 * polynomial of degree 8. In other words, for AES, GF(a, b) will multiply 6831 * polynomial 'a' with polynomial 'b' and then do a modular reduction by 6832 * an AES-specific irreducible polynomial of degree 8. 6833 * 6834 * A polynomial is irreducible if its only divisors are one and itself. For 6835 * the AES algorithm, this irreducible polynomial is: 6836 *
6837 * m(x) = x^8 + x^4 + x^3 + x + 1, 6838 * 6839 * or {01}{1b} in hexadecimal notation, where each coefficient is a bit: 6840 * 100011011 = 283 = 0x11b. 6841 * 6842 * For example, GF(0x57, 0x83) = 0xc1 because 6843 * 6844 * 0x57 = 87 = 01010111 = x^6 + x^4 + x^2 + x + 1 6845 * 0x85 = 131 = 10000101 = x^7 + x + 1 6846 * 6847 * (x^6 + x^4 + x^2 + x + 1) * (x^7 + x + 1) 6848 * = x^13 + x^11 + x^9 + x^8 + x^7 + 6849 * x^7 + x^5 + x^3 + x^2 + x + 6850 * x^6 + x^4 + x^2 + x + 1 6851 * = x^13 + x^11 + x^9 + x^8 + x^6 + x^5 + x^4 + x^3 + 1 = y 6852 * y modulo (x^8 + x^4 + x^3 + x + 1) 6853 * = x^7 + x^6 + 1. 6854 * 6855 * The modular reduction by m(x) guarantees the result will be a binary 6856 * polynomial of less than degree 8, so that it can fit in a byte. 6857 * 6858 * The operation to multiply a binary polynomial b with x (the polynomial 6859 * x in binary representation is 00000010) is: 6860 * 6861 * b_7x^8 + b_6x^7 + b_5x^6 + b_4x^5 + b_3x^4 + b_2x^3 + b_1x^2 + b_0x^1 6862 * 6863 * To get GF(b, x) we must reduce that by m(x). If b_7 is 0 (that is the 6864 * most significant bit is 0 in b) then the result is already reduced. If 6865 * it is 1, then we can reduce it by subtracting m(x) via an XOR. 6866 * 6867 * It follows that multiplication by x (00000010 or 0x02) can be implemented 6868 * by performing a left shift followed by a conditional bitwise XOR with 6869 * 0x1b. This operation on bytes is denoted by xtime(). Multiplication by 6870 * higher powers of x can be implemented by repeated application of xtime(). 6871 * 6872 * By adding intermediate results, multiplication by any constant can be 6873 * implemented. For instance: 6874 * 6875 * GF(0x57, 0x13) = 0xfe because: 6876 * 6877 * xtime(b) = (b & 128) ? (b << 1 ^ 0x11b) : (b << 1) 6878 * 6879 * Note: We XOR with 0x11b instead of 0x1b because in javascript our 6880 * datatype for b can be larger than 1 byte, so a left shift will not 6881 * automatically eliminate bits that overflow a byte ... by XOR'ing the 6882 * overflow bit with 1 (the extra one from 0x11b) we zero it out. 6883 * 6884 * GF(0x57, 0x02) = xtime(0x57) = 0xae 6885 * GF(0x57, 0x04) = xtime(0xae) = 0x47 6886 * GF(0x57, 0x08) = xtime(0x47) = 0x8e 6887 * GF(0x57, 0x10) = xtime(0x8e) = 0x07 6888 * 6889 * GF(0x57, 0x13) = GF(0x57, (0x01 ^ 0x02 ^ 0x10)) 6890 * 6891 * And by the distributive property (since XOR is addition and GF() is 6892 * multiplication): 6893 * 6894 * = GF(0x57, 0x01) ^ GF(0x57, 0x02) ^ GF(0x57, 0x10) 6895 * = 0x57 ^ 0xae ^ 0x07 6896 * = 0xfe. 6897 */ 6898function initialize() { 6899 init = true; 6900 6901 /* Populate the Rcon table. These are the values given by 6902 [x^(i-1),{00},{00},{00}] where x^(i-1) are powers of x (and x = 0x02) 6903 in the field of GF(2^8), where i starts at 1. 6904 6905 rcon[0] = [0x00, 0x00, 0x00, 0x00] 6906 rcon[1] = [0x01, 0x00, 0x00, 0x00] 2^(1-1) = 2^0 = 1 6907 rcon[2] = [0x02, 0x00, 0x00, 0x00] 2^(2-1) = 2^1 = 2 6908 ... 6909 rcon[9] = [0x1B, 0x00, 0x00, 0x00] 2^(9-1) = 2^8 = 0x1B 6910 rcon[10] = [0x36, 0x00, 0x00, 0x00] 2^(10-1) = 2^9 = 0x36 6911 6912 We only store the first byte because it is the only one used. 6913 */ 6914 rcon = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]; 6915 6916 // compute xtime table which maps i onto GF(i, 0x02) 6917 var xtime = new Array(256); 6918 for(var i = 0; i < 128; ++i) { 6919 xtime[i] = i << 1; 6920 xtime[i + 128] = (i + 128) << 1 ^ 0x11B; 6921 } 6922 6923 // compute all other tables 6924 sbox = new Array(256); 6925 isbox = new Array(256); 6926 mix = new Array(4); 6927 imix = new Array(4); 6928 for(var i = 0; i < 4; ++i) { 6929 mix[i] = new Array(256); 6930 imix[i] = new Array(256); 6931 } 6932 var e = 0, ei = 0, e2, e4, e8, sx, sx2, me, ime; 6933 for(var i = 0; i < 256; ++i) { 6934 /* We need to generate the SubBytes() sbox and isbox tables so that 6935 we can perform byte substitutions. This requires us to traverse 6936 all of the elements in GF, find their multiplicative inverses, 6937 and apply to each the following affine transformation: 6938 6939 bi' = bi ^ b(i + 4) mod 8 ^ b(i + 5) mod 8 ^ b(i + 6) mod 8 ^ 6940 b(i + 7) mod 8 ^ ci 6941 for 0 <= i < 8, where bi is the ith bit of the byte, and ci is the 6942 ith bit of a byte c with the value {63} or {01100011}. 6943 6944 It is possible to traverse every possible value in a Galois field 6945 using what is referred to as a 'generator'. There are many 6946 generators (128 out of 256): 3,5,6,9,11,82 to name a few. To fully 6947 traverse GF we iterate 255 times, multiplying by our generator 6948 each time. 6949 6950 On each iteration we can determine the multiplicative inverse for 6951 the current element. 6952 6953 Suppose there is an element in GF 'e'. For a given generator 'g', 6954 e = g^x. The multiplicative inverse of e is g^(255 - x). It turns 6955 out that if use the inverse of a generator as another generator 6956 it will produce all of the corresponding multiplicative inverses 6957 at the same time. For this reason, we choose 5 as our inverse 6958 generator because it only requires 2 multiplies and 1 add and its 6959 inverse, 82, requires relatively few operations as well. 6960 6961 In order to apply the affine transformation, the multiplicative 6962 inverse 'ei' of 'e' can be repeatedly XOR'd (4 times) with a 6963 bit-cycling of 'ei'. To do this 'ei' is first stored in 's' and 6964 'x'. Then 's' is left shifted and the high bit of 's' is made the 6965 low bit. The resulting value is stored in 's'. Then 'x' is XOR'd 6966 with 's' and stored in 'x'. On each subsequent iteration the same 6967 operation is performed. When 4 iterations are complete, 'x' is 6968 XOR'd with 'c' (0x63) and the transformed value is stored in 'x'. 6969 For example: 6970 6971 s = 01000001 6972 x = 01000001 6973 6974 iteration 1: s = 10000010, x ^= s 6975 iteration 2: s = 00000101, x ^= s 6976 iteration 3: s = 00001010, x ^= s 6977 iteration 4: s = 00010100, x ^= s 6978 x ^= 0x63 6979 6980 This can be done with a loop where s = (s << 1) | (s >> 7). However, 6981 it can also be done by using a single 16-bit (in this case 32-bit) 6982 number 'sx'. Since XOR is an associative operation, we can set 'sx' 6983 to 'ei' and then XOR it with 'sx' left-shifted 1,2,3, and 4 times. 6984 The most significant bits will flow into the high 8 bit positions 6985 and be correctly XOR'd with one another. All that remains will be 6986 to cycle the high 8 bits by XOR'ing them all with the lower 8 bits 6987 afterwards. 6988 6989 At the same time we're populating sbox and isbox we can precompute 6990 the multiplication we'll need to do to do MixColumns() later. 6991 */ 6992 6993 // apply affine transformation 6994 sx = ei ^ (ei << 1) ^ (ei << 2) ^ (ei << 3) ^ (ei << 4); 6995 sx = (sx >> 8) ^ (sx & 255) ^ 0x63; 6996 6997 // update tables 6998 sbox[e] = sx; 6999 isbox[sx] = e; 7000 7001 /* Mixing columns is done using matrix multiplication. The columns 7002 that are to be mixed are each a single word in the current state. 7003 The state has Nb columns (4 columns). Therefore each column is a 7004 4 byte word. So to mix the columns in a single column 'c' where 7005 its rows are r0, r1, r2, and r3, we use the following matrix 7006 multiplication: 7007 7008 [2 3 1 1]*[r0,c]=[r'0,c] 7009 [1 2 3 1] [r1,c] [r'1,c] 7010 [1 1 2 3] [r2,c] [r'2,c] 7011 [3 1 1 2] [r3,c] [r'3,c] 7012 7013 r0, r1, r2, and r3 are each 1 byte of one of the words in the 7014 state (a column). To do matrix multiplication for each mixed 7015 column c' we multiply the corresponding row from the left matrix 7016 with the corresponding column from the right matrix. In total, we 7017 get 4 equations: 7018 7019 r0,c' = 2*r0,c + 3*r1,c + 1*r2,c + 1*r3,c 7020 r1,c' = 1*r0,c + 2*r1,c + 3*r2,c + 1*r3,c 7021 r2,c' = 1*r0,c + 1*r1,c + 2*r2,c + 3*r3,c 7022 r3,c' = 3*r0,c + 1*r1,c + 1*r2,c + 2*r3,c 7023 7024 As usual, the multiplication is as previously defined and the
7025 addition is XOR. In order to optimize mixing columns we can store 7026 the multiplication results in tables. If you think of the whole 7027 column as a word (it might help to visualize by mentally rotating 7028 the equations above by counterclockwise 90 degrees) then you can 7029 see that it would be useful to map the multiplications performed on 7030 each byte (r0, r1, r2, r3) onto a word as well. For instance, we 7031 could map 2*r0,1*r0,1*r0,3*r0 onto a word by storing 2*r0 in the 7032 highest 8 bits and 3*r0 in the lowest 8 bits (with the other two 7033 respectively in the middle). This means that a table can be 7034 constructed that uses r0 as an index to the word. We can do the 7035 same with r1, r2, and r3, creating a total of 4 tables. 7036 7037 To construct a full c', we can just look up each byte of c in 7038 their respective tables and XOR the results together. 7039 7040 Also, to build each table we only have to calculate the word 7041 for 2,1,1,3 for every byte ... which we can do on each iteration 7042 of this loop since we will iterate over every byte. After we have 7043 calculated 2,1,1,3 we can get the results for the other tables 7044 by cycling the byte at the end to the beginning. For instance 7045 we can take the result of table 2,1,1,3 and produce table 3,2,1,1 7046 by moving the right most byte to the left most position just like 7047 how you can imagine the 3 moved out of 2,1,1,3 and to the front 7048 to produce 3,2,1,1. 7049 7050 There is another optimization in that the same multiples of 7051 the current element we need in order to advance our generator 7052 to the next iteration can be reused in performing the 2,1,1,3 7053 calculation. We also calculate the inverse mix column tables, 7054 with e,9,d,b being the inverse of 2,1,1,3. 7055 7056 When we're done, and we need to actually mix columns, the first 7057 byte of each state word should be put through mix[0] (2,1,1,3), 7058 the second through mix[1] (3,2,1,1) and so forth. Then they should 7059 be XOR'd together to produce the fully mixed column. 7060 */ 7061 7062 // calculate mix and imix table values 7063 sx2 = xtime[sx]; 7064 e2 = xtime[e]; 7065 e4 = xtime[e2]; 7066 e8 = xtime[e4]; 7067 me = 7068 (sx2 << 24) ^ // 2 7069 (sx << 16) ^ // 1 7070 (sx << 8) ^ // 1 7071 (sx ^ sx2); // 3 7072 ime = 7073 (e2 ^ e4 ^ e8) << 24 ^ // E (14) 7074 (e ^ e8) << 16 ^ // 9 7075 (e ^ e4 ^ e8) << 8 ^ // D (13) 7076 (e ^ e2 ^ e8); // B (11) 7077 // produce each of the mix tables by rotating the 2,1,1,3 value 7078 for(var n = 0; n < 4; ++n) { 7079 mix[n][e] = me; 7080 imix[n][sx] = ime; 7081 // cycle the right most byte to the left most position 7082 // ie: 2,1,1,3 becomes 3,2,1,1 7083 me = me << 24 | me >>> 8; 7084 ime = ime << 24 | ime >>> 8; 7085 } 7086 7087 // get next element and inverse 7088 if(e === 0) { 7089 // 1 is the inverse of 1 7090 e = ei = 1; 7091 } else { 7092 // e = 2e + 2*2*2*(10e)) = multiply e by 82 (chosen generator) 7093 // ei = ei + 2*2*ei = multiply ei by 5 (inverse generator) 7094 e = e2 ^ xtime[xtime[xtime[e2 ^ e8]]]; 7095 ei ^= xtime[xtime[ei]]; 7096 } 7097 } 7098} 7099 7100/** 7101 * Generates a key schedule using the AES key expansion algorithm. 7102 * 7103 * The AES algorithm takes the Cipher Key, K, and performs a Key Expansion 7104 * routine to generate a key schedule. The Key Expansion generates a total 7105 * of Nb*(Nr + 1) words: the algorithm requires an initial set of Nb words, 7106 * and each of the Nr rounds requires Nb words of key data. The resulting 7107 * key schedule consists of a linear array of 4-byte words, denoted [wi ], 7108 * with i in the range 0 ? i < Nb(Nr + 1). 7109 * 7110 * KeyExpansion(byte key[4*Nk], word w[Nb*(Nr+1)], Nk) 7111 * AES-128 (Nb=4, Nk=4, Nr=10) 7112 * AES-192 (Nb=4, Nk=6, Nr=12) 7113 * AES-256 (Nb=4, Nk=8, Nr=14) 7114 * Note: Nr=Nk+6. 7115 * 7116 * Nb is the number of columns (32-bit words) comprising the State (or 7117 * number of bytes in a block). For AES, Nb=4. 7118 * 7119 * @param key the key to schedule (as an array of 32-bit words). 7120 * @param decrypt true to modify the key schedule to decrypt, false not to. 7121 * 7122 * @return the generated key schedule. 7123 */ 7124function _expandKey(key, decrypt) { 7125 // copy the key's words to initialize the key schedule 7126 var w = key.slice(0); 7127 7128 /* RotWord() will rotate a word, moving the first byte to the last 7129 byte's position (shifting the other bytes left). 7130 7131 We will be getting the value of Rcon at i / Nk. 'i' will iterate
7132 from Nk to (Nb * Nr+1). Nk = 4 (4 byte key), Nb = 4 (4 words in 7133 a block), Nr = Nk + 6 (10). Therefore 'i' will iterate from 7134 4 to 44 (exclusive). Each time we iterate 4 times, i / Nk will 7135 increase by 1. We use a counter iNk to keep track of this. 7136 */ 7137 7138 // go through the rounds expanding the key 7139 var temp, iNk = 1; 7140 var Nk = w.length; 7141 var Nr1 = Nk + 6 + 1; 7142 var end = Nb * Nr1; 7143 for(var i = Nk; i < end; ++i) { 7144 temp = w[i - 1]; 7145 if(i % Nk === 0) { 7146 // temp = SubWord(RotWord(temp)) ^ Rcon[i / Nk] 7147 temp = 7148 sbox[temp >>> 16 & 255] << 24 ^ 7149 sbox[temp >>> 8 & 255] << 16 ^ 7150 sbox[temp & 255] << 8 ^ 7151 sbox[temp >>> 24] ^ (rcon[iNk] << 24); 7152 iNk++; 7153 } else if(Nk > 6 && (i % Nk === 4)) { 7154 // temp = SubWord(temp) 7155 temp = 7156 sbox[temp >>> 24] << 24 ^ 7157 sbox[temp >>> 16 & 255] << 16 ^ 7158 sbox[temp >>> 8 & 255] << 8 ^ 7159 sbox[temp & 255]; 7160 } 7161 w[i] = w[i - Nk] ^ temp; 7162 } 7163 7164 /* When we are updating a cipher block we always use the code path for 7165 encryption whether we are decrypting or not (to shorten code and 7166 simplify the generation of look up tables). However, because there 7167 are differences in the decryption algorithm, other than just swapping 7168 in different look up tables, we must transform our key schedule to 7169 account for these changes: 7170 7171 1. The decryption algorithm gets its key rounds in reverse order. 7172 2. The decryption algorithm adds the round key before mixing columns 7173 instead of afterwards. 7174 7175 We don't need to modify our key schedule to handle the first case, 7176 we can just traverse the key schedule in reverse order when decrypting. 7177 7178 The second case requires a little work. 7179 7180 The tables we built for performing rounds will take an input and then 7181 perform SubBytes() and MixColumns() or, for the decrypt version, 7182 InvSubBytes() and InvMixColumns(). But the decrypt algorithm requires 7183 us to AddRoundKey() before InvMixColumns(). This means we'll need to 7184 apply some transformations to the round key to inverse-mix its columns 7185 so they'll be correct for moving AddRoundKey() to after the state has 7186 had its columns inverse-mixed. 7187 7188 To inverse-mix the columns of the state when we're decrypting we use a 7189 lookup table that will apply InvSubBytes() and InvMixColumns() at the 7190 same time. However, the round key's bytes are not inverse-substituted 7191 in the decryption algorithm. To get around this problem, we can first 7192 substitute the bytes in the round key so that when we apply the 7193 transformation via the InvSubBytes()+InvMixColumns() table, it will 7194 undo our substitution leaving us with the original value that we 7195 want -- and then inverse-mix that value. 7196 7197 This change will correctly alter our key schedule so that we can XOR 7198 each round key with our already transformed decryption state. This 7199 allows us to use the same code path as the encryption algorithm. 7200 7201 We make one more change to the decryption key. Since the decryption 7202 algorithm runs in reverse from the encryption algorithm, we reverse 7203 the order of the round keys to avoid having to iterate over the key 7204 schedule backwards when running the encryption algorithm later in 7205 decryption mode. In addition to reversing the order of the round keys, 7206 we also swap each round key's 2nd and 4th rows. See the comments 7207 section where rounds are performed for more details about why this is 7208 done. These changes are done inline with the other substitution 7209 described above. 7210 */ 7211 if(decrypt) { 7212 var tmp; 7213 var m0 = imix[0]; 7214 var m1 = imix[1]; 7215 var m2 = imix[2]; 7216 var m3 = imix[3]; 7217 var wnew = w.slice(0); 7218 end = w.length; 7219 for(var i = 0, wi = end - Nb; i < end; i += Nb, wi -= Nb) { 7220 // do not sub the first or last round key (round keys are Nb 7221 // words) as no column mixing is performed before they are added, 7222 // but do change the key order 7223 if(i === 0 || i === (end - Nb)) { 7224 wnew[i] = w[wi]; 7225 wnew[i + 1] = w[wi + 3]; 7226 wnew[i + 2] = w[wi + 2]; 7227 wnew[i + 3] = w[wi + 1]; 7228 } else { 7229 // substitute each round key byte because the inverse-mix 7230 // table will inverse-substitute it (effectively cancel the 7231 // substitution because round key bytes aren't sub'd in 7232 // decryption mode) and swap indexes 3 and 1 7233 for(var n = 0; n < Nb; ++n) { 7234 tmp = w[wi + n]; 7235 wnew[i + (3&-n)] = 7236 m0[sbox[tmp >>> 24]] ^ 7237 m1[sbox[tmp >>> 16 & 255]] ^ 7238 m2[sbox[tmp >>> 8 & 255]] ^ 7239 m3[sbox[tmp & 255]]; 7240 } 7241 } 7242 } 7243 w = wnew; 7244 } 7245 7246 return w; 7247} 7248 7249/** 7250 * Updates a single block (16 bytes) using AES. The update will either 7251 * encrypt or decrypt the block. 7252 * 7253 * @param w the key schedule. 7254 * @param input the input block (an array of 32-bit words). 7255 * @param output the updated output block. 7256 * @param decrypt true to decrypt the block, false to encrypt it. 7257 */ 7258function _updateBlock(w, input, output, decrypt) { 7259 /* 7260 Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) 7261 begin 7262 byte state[4,Nb] 7263 state = in 7264 AddRoundKey(state, w[0, Nb-1])
7265 for round = 1 step 1 to Nr�1 7266 SubBytes(state) 7267 ShiftRows(state) 7268 MixColumns(state) 7269 AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) 7270 end for 7271 SubBytes(state) 7272 ShiftRows(state) 7273 AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) 7274 out = state 7275 end 7276 7277 InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) 7278 begin 7279 byte state[4,Nb] 7280 state = in 7281 AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) 7282 for round = Nr-1 step -1 downto 1 7283 InvShiftRows(state) 7284 InvSubBytes(state) 7285 AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) 7286 InvMixColumns(state) 7287 end for 7288 InvShiftRows(state) 7289 InvSubBytes(state) 7290 AddRoundKey(state, w[0, Nb-1]) 7291 out = state 7292 end 7293 */ 7294 7295 // Encrypt: AddRoundKey(state, w[0, Nb-1]) 7296 // Decrypt: AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) 7297 var Nr = w.length / 4 - 1; 7298 var m0, m1, m2, m3, sub; 7299 if(decrypt) { 7300 m0 = imix[0]; 7301 m1 = imix[1]; 7302 m2 = imix[2]; 7303 m3 = imix[3]; 7304 sub = isbox; 7305 } else { 7306 m0 = mix[0]; 7307 m1 = mix[1]; 7308 m2 = mix[2]; 7309 m3 = mix[3]; 7310 sub = sbox; 7311 } 7312 var a, b, c, d, a2, b2, c2; 7313 a = input[0] ^ w[0]; 7314 b = input[decrypt ? 3 : 1] ^ w[1]; 7315 c = input[2] ^ w[2]; 7316 d = input[decrypt ? 1 : 3] ^ w[3]; 7317 var i = 3; 7318 7319 /* In order to share code we follow the encryption algorithm when both 7320 encrypting and decrypting. To account for the changes required in the 7321 decryption algorithm, we use different lookup tables when decrypting 7322 and use a modified key schedule to account for the difference in the 7323 order of transformations applied when performing rounds. We also get 7324 key rounds in reverse order (relative to encryption). */ 7325 for(var round = 1; round < Nr; ++round) { 7326 /* As described above, we'll be using table lookups to perform the 7327 column mixing. Each column is stored as a word in the state (the 7328 array 'input' has one column as a word at each index). In order to 7329 mix a column, we perform these transformations on each row in c, 7330 which is 1 byte in each word. The new column for c0 is c'0: 7331 7332 m0 m1 m2 m3 7333 r0,c'0 = 2*r0,c0 + 3*r1,c0 + 1*r2,c0 + 1*r3,c0 7334 r1,c'0 = 1*r0,c0 + 2*r1,c0 + 3*r2,c0 + 1*r3,c0 7335 r2,c'0 = 1*r0,c0 + 1*r1,c0 + 2*r2,c0 + 3*r3,c0 7336 r3,c'0 = 3*r0,c0 + 1*r1,c0 + 1*r2,c0 + 2*r3,c0 7337 7338 So using mix tables where c0 is a word with r0 being its upper 7339 8 bits and r3 being its lower 8 bits: 7340 7341 m0[c0 >> 24] will yield this word: [2*r0,1*r0,1*r0,3*r0] 7342 ... 7343 m3[c0 & 255] will yield this word: [1*r3,1*r3,3*r3,2*r3] 7344 7345 Therefore to mix the columns in each word in the state we 7346 do the following (& 255 omitted for brevity): 7347 c'0,r0 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] 7348 c'0,r1 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] 7349 c'0,r2 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] 7350 c'0,r3 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] 7351 7352 However, before mixing, the algorithm requires us to perform 7353 ShiftRows(). The ShiftRows() transformation cyclically shifts the 7354 last 3 rows of the state over different offsets. The first row 7355 (r = 0) is not shifted. 7356 7357 s'_r,c = s_r,(c + shift(r, Nb) mod Nb 7358 for 0 < r < 4 and 0 <= c < Nb and 7359 shift(1, 4) = 1 7360 shift(2, 4) = 2 7361 shift(3, 4) = 3. 7362 7363 This causes the first byte in r = 1 to be moved to the end of 7364 the row, the first 2 bytes in r = 2 to be moved to the end of 7365 the row, the first 3 bytes in r = 3 to be moved to the end of 7366 the row: 7367 7368 r1: [c0 c1 c2 c3] => [c1 c2 c3 c0] 7369 r2: [c0 c1 c2 c3] [c2 c3 c0 c1] 7370 r3: [c0 c1 c2 c3] [c3 c0 c1 c2] 7371 7372 We can make these substitutions inline with our column mixing to 7373 generate an updated set of equations to produce each word in the 7374 state (note the columns have changed positions): 7375 7376 c0 c1 c2 c3 => c0 c1 c2 c3 7377 c0 c1 c2 c3 c1 c2 c3 c0 (cycled 1 byte) 7378 c0 c1 c2 c3 c2 c3 c0 c1 (cycled 2 bytes) 7379 c0 c1 c2 c3 c3 c0 c1 c2 (cycled 3 bytes) 7380 7381 Therefore: 7382 7383 c'0 = 2*r0,c0 + 3*r1,c1 + 1*r2,c2 + 1*r3,c3 7384 c'0 = 1*r0,c0 + 2*r1,c1 + 3*r2,c2 + 1*r3,c3 7385 c'0 = 1*r0,c0 + 1*r1,c1 + 2*r2,c2 + 3*r3,c3 7386 c'0 = 3*r0,c0 + 1*r1,c1 + 1*r2,c2 + 2*r3,c3 7387 7388 c'1 = 2*r0,c1 + 3*r1,c2 + 1*r2,c3 + 1*r3,c0 7389 c'1 = 1*r0,c1 + 2*r1,c2 + 3*r2,c3 + 1*r3,c0 7390 c'1 = 1*r0,c1 + 1*r1,c2 + 2*r2,c3 + 3*r3,c0 7391 c'1 = 3*r0,c1 + 1*r1,c2 + 1*r2,c3 + 2*r3,c0 7392 7393 ... and so forth for c'2 and c'3. The important distinction is 7394 that the columns are cycling, with c0 being used with the m0 7395 map when calculating c0, but c1 being used with the m0 map when 7396 calculating c1 ... and so forth. 7397 7398 When performing the inverse we transform the mirror image and 7399 skip the bottom row, instead of the top one, and move upwards: 7400 7401 c3 c2 c1 c0 => c0 c3 c2 c1 (cycled 3 bytes) *same as encryption 7402 c3 c2 c1 c0 c1 c0 c3 c2 (cycled 2 bytes) 7403 c3 c2 c1 c0 c2 c1 c0 c3 (cycled 1 byte) *same as encryption 7404 c3 c2 c1 c0 c3 c2 c1 c0 7405 7406 If you compare the resulting matrices for ShiftRows()+MixColumns() 7407 and for InvShiftRows()+InvMixColumns() the 2nd and 4th columns are 7408 different (in encrypt mode vs. decrypt mode). So in order to use 7409 the same code to handle both encryption and decryption, we will 7410 need to do some mapping. 7411 7412 If in encryption mode we let a=c0, b=c1, c=c2, d=c3, and r<N> be 7413 a row number in the state, then the resulting matrix in encryption 7414 mode for applying the above transformations would be: 7415 7416 r1: a b c d 7417 r2: b c d a 7418 r3: c d a b 7419 r4: d a b c 7420 7421 If we did the same in decryption mode we would get: 7422 7423 r1: a d c b 7424 r2: b a d c 7425 r3: c b a d 7426 r4: d c b a 7427 7428 If instead we swap d and b (set b=c3 and d=c1), then we get: 7429 7430 r1: a b c d 7431 r2: d a b c 7432 r3: c d a b 7433 r4: b c d a 7434 7435 Now the 1st and 3rd rows are the same as the encryption matrix. All 7436 we need to do then to make the mapping exactly the same is to swap 7437 the 2nd and 4th rows when in decryption mode. To do this without 7438 having to do it on each iteration, we swapped the 2nd and 4th rows 7439 in the decryption key schedule. We also have to do the swap above 7440 when we first pull in the input and when we set the final output. */ 7441 a2 = 7442 m0[a >>> 24] ^ 7443 m1[b >>> 16 & 255] ^ 7444 m2[c >>> 8 & 255] ^ 7445 m3[d & 255] ^ w[++i]; 7446 b2 = 7447 m0[b >>> 24] ^ 7448 m1[c >>> 16 & 255] ^ 7449 m2[d >>> 8 & 255] ^ 7450 m3[a & 255] ^ w[++i]; 7451 c2 = 7452 m0[c >>> 24] ^ 7453 m1[d >>> 16 & 255] ^ 7454 m2[a >>> 8 & 255] ^ 7455 m3[b & 255] ^ w[++i]; 7456 d = 7457 m0[d >>> 24] ^ 7458 m1[a >>> 16 & 255] ^ 7459 m2[b >>> 8 & 255] ^ 7460 m3[c & 255] ^ w[++i]; 7461 a = a2; 7462 b = b2; 7463 c = c2; 7464 } 7465 7466 /* 7467 Encrypt: 7468 SubBytes(state) 7469 ShiftRows(state) 7470 AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) 7471 7472 Decrypt: 7473 InvShiftRows(state) 7474 InvSubBytes(state) 7475 AddRoundKey(state, w[0, Nb-1]) 7476 */ 7477 // Note: rows are shifted inline 7478 output[0] = 7479 (sub[a >>> 24] << 24) ^ 7480 (sub[b >>> 16 & 255] << 16) ^ 7481 (sub[c >>> 8 & 255] << 8) ^ 7482 (sub[d & 255]) ^ w[++i]; 7483 output[decrypt ? 3 : 1] = 7484 (sub[b >>> 24] << 24) ^ 7485 (sub[c >>> 16 & 255] << 16) ^ 7486 (sub[d >>> 8 & 255] << 8) ^ 7487 (sub[a & 255]) ^ w[++i]; 7488 output[2] = 7489 (sub[c >>> 24] << 24) ^ 7490 (sub[d >>> 16 & 255] << 16) ^ 7491 (sub[a >>> 8 & 255] << 8) ^ 7492 (sub[b & 255]) ^ w[++i]; 7493 output[decrypt ? 1 : 3] = 7494 (sub[d >>> 24] << 24) ^ 7495 (sub[a >>> 16 & 255] << 16) ^ 7496 (sub[b >>> 8 & 255] << 8) ^ 7497 (sub[c & 255]) ^ w[++i]; 7498} 7499 7500/** 7501 * Deprecated. Instead, use: 7502 * 7503 * forge.cipher.createCipher('AES-<mode>', key); 7504 * forge.cipher.createDecipher('AES-<mode>', key); 7505 * 7506 * Creates a deprecated AES cipher object. This object's mode will default to 7507 * CBC (cipher-block-chaining). 7508 * 7509 * The key and iv may be given as a string of bytes, an array of bytes, a 7510 * byte buffer, or an array of 32-bit words. 7511 * 7512 * @param options the options to use. 7513 * key the symmetric key to use. 7514 * output the buffer to write to. 7515 * decrypt true for decryption, false for encryption. 7516 * mode the cipher mode to use (default: 'CBC'). 7517 * 7518 * @return the cipher. 7519 */ 7520function _createCipher(options) { 7521 options = options || {}; 7522 var mode = (options.mode || 'CBC').toUpperCase(); 7523 var algorithm = 'AES-' + mode; 7524 7525 var cipher; 7526 if(options.decrypt) { 7527 cipher = forge.cipher.createDecipher(algorithm, options.key); 7528 } else { 7529 cipher = forge.cipher.createCipher(algorithm, options.key); 7530 } 7531 7532 // backwards compatible start API 7533 var start = cipher.start; 7534 cipher.start = function(iv, options) { 7535 // backwards compatibility: support second arg as output buffer 7536 var output = null; 7537 if(options instanceof forge.util.ByteBuffer) { 7538 output = options; 7539 options = {}; 7540 } 7541 options = options || {}; 7542 options.output = output; 7543 options.iv = iv; 7544 start.call(cipher, options); 7545 }; 7546 7547 return cipher; 7548} 7549 7550} // end module implementation 7551 7552/* ########## Begin module wrapper ########## */ 7553var name = 'aes'; 7554if(typeof define !== 'function') { 7555 // NodeJS -> AMD 7556 if(typeof module === 'object' && module.exports) { 7557 var nodeJS = true; 7558 define = function(ids, factory) { 7559 factory(require, module); 7560 }; 7561 } else { 7562 // <script> 7563 if(typeof forge === 'undefined') { 7564 forge = {}; 7565 } 7566 return initModule(forge); 7567 } 7568} 7569// AMD 7570var deps;
7571var defineFunc = function(require, module) { 7572 module.exports = function(forge) { 7573 var mods = deps.map(function(dep) { 7574 return require(dep); 7575 }).concat(initModule); 7576 // handle circular dependencies 7577 forge = forge || {}; 7578 forge.defined = forge.defined || {}; 7579 if(forge.defined[name]) { 7580 return forge[name]; 7581 } 7582 forge.defined[name] = true; 7583 for(var i = 0; i < mods.length; ++i) { 7584 mods[i](forge); 7585 } 7586 return forge[name]; 7587 }; 7588}; 7589var tmpDefine = define; 7590define = function(ids, factory) { 7591 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 7592 if(nodeJS) { 7593 delete define; 7594 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 7595 } 7596 define = tmpDefine; 7597 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 7598}; 7599define( 7600 ['require', 'module', './cipher', './cipherModes', './util'], function() { 7601 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 7602}); 7603})(); 7604 7605/** 7606 * A javascript implementation of a cryptographically-secure 7607 * Pseudo Random Number Generator (PRNG). The Fortuna algorithm is followed 7608 * here though the use of SHA-256 is not enforced; when generating an 7609 * a PRNG context, the hashing algorithm and block cipher used for 7610 * the generator are specified via a plugin. 7611 * 7612 * @author Dave Longley 7613 * 7614 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 7615 */ 7616(function() { 7617/* ########## Begin module implementation ########## */ 7618function initModule(forge) { 7619 7620var _nodejs = ( 7621 typeof process !== 'undefined' && process.versions && process.versions.node); 7622var _crypto = null; 7623if(!forge.disableNativeCode && _nodejs && !process.versions['node-webkit']) { 7624 _crypto = require('crypto'); 7625} 7626 7627/* PRNG API */ 7628var prng = forge.prng = forge.prng || {}; 7629 7630/** 7631 * Creates a new PRNG context. 7632 * 7633 * A PRNG plugin must be passed in that will provide: 7634 * 7635 * 1. A function that initializes the key and seed of a PRNG context. It 7636 * will be given a 16 byte key and a 16 byte seed. Any key expansion 7637 * or transformation of the seed from a byte string into an array of 7638 * integers (or similar) should be performed. 7639 * 2. The cryptographic function used by the generator. It takes a key and 7640 * a seed. 7641 * 3. A seed increment function. It takes the seed and returns seed + 1. 7642 * 4. An api to create a message digest. 7643 * 7644 * For an example, see random.js. 7645 * 7646 * @param plugin the PRNG plugin to use. 7647 */ 7648prng.create = function(plugin) { 7649 var ctx = { 7650 plugin: plugin, 7651 key: null, 7652 seed: null, 7653 time: null, 7654 // number of reseeds so far 7655 reseeds: 0, 7656 // amount of data generated so far 7657 generated: 0 7658 }; 7659 7660 // create 32 entropy pools (each is a message digest) 7661 var md = plugin.md; 7662 var pools = new Array(32); 7663 for(var i = 0; i < 32; ++i) { 7664 pools[i] = md.create(); 7665 } 7666 ctx.pools = pools; 7667 7668 // entropy pools are written to cyclically, starting at index 0 7669 ctx.pool = 0; 7670 7671 /** 7672 * Generates random bytes. The bytes may be generated synchronously or 7673 * asynchronously. Web workers must use the asynchronous interface or 7674 * else the behavior is undefined. 7675 * 7676 * @param count the number of random bytes to generate. 7677 * @param [callback(err, bytes)] called once the operation completes. 7678 * 7679 * @return count random bytes as a string. 7680 */ 7681 ctx.generate = function(count, callback) { 7682 // do synchronously 7683 if(!callback) { 7684 return ctx.generateSync(count); 7685 } 7686 7687 // simple generator using counter-based CBC 7688 var cipher = ctx.plugin.cipher; 7689 var increment = ctx.plugin.increment; 7690 var formatKey = ctx.plugin.formatKey; 7691 var formatSeed = ctx.plugin.formatSeed; 7692 var b = forge.util.createBuffer(); 7693 7694 // reset key for every request 7695 ctx.key = null; 7696 7697 generate(); 7698 7699 function generate(err) { 7700 if(err) { 7701 return callback(err); 7702 } 7703 7704 // sufficient bytes generated 7705 if(b.length() >= count) { 7706 return callback(null, b.getBytes(count)); 7707 } 7708 7709 // if amount of data generated is greater than 1 MiB, trigger reseed 7710 if(ctx.generated > 0xfffff) { 7711 ctx.key = null; 7712 } 7713 7714 if(ctx.key === null) { 7715 // prevent stack overflow 7716 return forge.util.nextTick(function() { 7717 _reseed(generate); 7718 }); 7719 } 7720 7721 // generate the random bytes 7722 var bytes = cipher(ctx.key, ctx.seed); 7723 ctx.generated += bytes.length; 7724 b.putBytes(bytes); 7725 7726 // generate bytes for a new key and seed 7727 ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed))); 7728 ctx.seed = formatSeed(cipher(ctx.key, ctx.seed)); 7729 7730 forge.util.setImmediate(generate); 7731 } 7732 }; 7733 7734 /** 7735 * Generates random bytes synchronously. 7736 * 7737 * @param count the number of random bytes to generate. 7738 * 7739 * @return count random bytes as a string. 7740 */ 7741 ctx.generateSync = function(count) { 7742 // simple generator using counter-based CBC 7743 var cipher = ctx.plugin.cipher; 7744 var increment = ctx.plugin.increment; 7745 var formatKey = ctx.plugin.formatKey; 7746 var formatSeed = ctx.plugin.formatSeed; 7747 7748 // reset key for every request 7749 ctx.key = null; 7750 7751 var b = forge.util.createBuffer(); 7752 while(b.length() < count) { 7753 // if amount of data generated is greater than 1 MiB, trigger reseed 7754 if(ctx.generated > 0xfffff) { 7755 ctx.key = null; 7756 } 7757 7758 if(ctx.key === null) { 7759 _reseedSync(); 7760 } 7761 7762 // generate the random bytes 7763 var bytes = cipher(ctx.key, ctx.seed); 7764 ctx.generated += bytes.length; 7765 b.putBytes(bytes); 7766 7767 // generate bytes for a new key and seed 7768 ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed))); 7769 ctx.seed = formatSeed(cipher(ctx.key, ctx.seed)); 7770 } 7771 7772 return b.getBytes(count); 7773 }; 7774 7775 /** 7776 * Private function that asynchronously reseeds a generator. 7777 * 7778 * @param callback(err) called once the operation completes. 7779 */ 7780 function _reseed(callback) { 7781 if(ctx.pools[0].messageLength >= 32) { 7782 _seed(); 7783 return callback(); 7784 } 7785 // not enough seed data... 7786 var needed = (32 - ctx.pools[0].messageLength) << 5; 7787 ctx.seedFile(needed, function(err, bytes) { 7788 if(err) { 7789 return callback(err); 7790 } 7791 ctx.collect(bytes); 7792 _seed(); 7793 callback(); 7794 }); 7795 } 7796 7797 /** 7798 * Private function that synchronously reseeds a generator. 7799 */ 7800 function _reseedSync() { 7801 if(ctx.pools[0].messageLength >= 32) { 7802 return _seed(); 7803 } 7804 // not enough seed data... 7805 var needed = (32 - ctx.pools[0].messageLength) << 5; 7806 ctx.collect(ctx.seedFileSync(needed)); 7807 _seed(); 7808 } 7809 7810 /** 7811 * Private function that seeds a generator once enough bytes are available. 7812 */ 7813 function _seed() { 7814 // create a plugin-based message digest 7815 var md = ctx.plugin.md.create(); 7816
7817 // digest pool 0's entropy and restart it 7818 md.update(ctx.pools[0].digest().getBytes()); 7819 ctx.pools[0].start(); 7820 7821 // digest the entropy of other pools whose index k meet the 7822 // condition '2^k mod n == 0' where n is the number of reseeds 7823 var k = 1; 7824 for(var i = 1; i < 32; ++i) { 7825 // prevent signed numbers from being used 7826 k = (k === 31) ? 0x80000000 : (k << 2); 7827 if(k % ctx.reseeds === 0) { 7828 md.update(ctx.pools[i].digest().getBytes()); 7829 ctx.pools[i].start(); 7830 } 7831 } 7832 7833 // get digest for key bytes and iterate again for seed bytes 7834 var keyBytes = md.digest().getBytes(); 7835 md.start(); 7836 md.update(keyBytes); 7837 var seedBytes = md.digest().getBytes(); 7838 7839 // update 7840 ctx.key = ctx.plugin.formatKey(keyBytes); 7841 ctx.seed = ctx.plugin.formatSeed(seedBytes); 7842 ctx.reseeds = (ctx.reseeds === 0xffffffff) ? 0 : ctx.reseeds + 1; 7843 ctx.generated = 0; 7844 } 7845 7846 /** 7847 * The built-in default seedFile. This seedFile is used when entropy 7848 * is needed immediately. 7849 * 7850 * @param needed the number of bytes that are needed. 7851 * 7852 * @return the random bytes. 7853 */ 7854 function defaultSeedFile(needed) { 7855 // use window.crypto.getRandomValues strong source of entropy if available 7856 var getRandomValues = null; 7857 if(typeof window !== 'undefined') { 7858 var _crypto = window.crypto || window.msCrypto; 7859 if(_crypto && _crypto.getRandomValues) { 7860 getRandomValues = function(arr) { 7861 return _crypto.getRandomValues(arr); 7862 }; 7863 } 7864 } 7865 7866 var b = forge.util.createBuffer(); 7867 if(getRandomValues) { 7868 while(b.length() < needed) { 7869 // max byte length is 65536 before QuotaExceededError is thrown 7870 // http://www.w3.org/TR/WebCryptoAPI/#RandomSource-method-getRandomValues 7871 var count = Math.max(1, Math.min(needed - b.length(), 65536) / 4); 7872 var entropy = new Uint32Array(Math.floor(count)); 7873 try { 7874 getRandomValues(entropy); 7875 for(var i = 0; i < entropy.length; ++i) { 7876 b.putInt32(entropy[i]); 7877 } 7878 } catch(e) { 7879 /* only ignore QuotaExceededError */ 7880 if(!(typeof QuotaExceededError !== 'undefined' && 7881 e instanceof QuotaExceededError)) { 7882 throw e; 7883 } 7884 } 7885 } 7886 } 7887 7888 // be sad and add some weak random data 7889 if(b.length() < needed) { 7890 /* Draws from Park-Miller "minimal standard" 31 bit PRNG, 7891 implemented with David G. Carta's optimization: with 32 bit math 7892 and without division (Public Domain). */ 7893 var hi, lo, next; 7894 var seed = Math.floor(Math.random() * 0x010000); 7895 while(b.length() < needed) { 7896 lo = 16807 * (seed & 0xFFFF); 7897 hi = 16807 * (seed >> 16); 7898 lo += (hi & 0x7FFF) << 16; 7899 lo += hi >> 15; 7900 lo = (lo & 0x7FFFFFFF) + (lo >> 31); 7901 seed = lo & 0xFFFFFFFF; 7902 7903 // consume lower 3 bytes of seed 7904 for(var i = 0; i < 3; ++i) { 7905 // throw in more pseudo random 7906 next = seed >>> (i << 3); 7907 next ^= Math.floor(Math.random() * 0x0100); 7908 b.putByte(String.fromCharCode(next & 0xFF)); 7909 } 7910 } 7911 } 7912 7913 return b.getBytes(needed); 7914 } 7915 // initialize seed file APIs 7916 if(_crypto) { 7917 // use nodejs async API 7918 ctx.seedFile = function(needed, callback) { 7919 _crypto.randomBytes(needed, function(err, bytes) { 7920 if(err) { 7921 return callback(err); 7922 } 7923 callback(null, bytes.toString()); 7924 }); 7925 }; 7926 // use nodejs sync API 7927 ctx.seedFileSync = function(needed) { 7928 return _crypto.randomBytes(needed).toString(); 7929 }; 7930 } else { 7931 ctx.seedFile = function(needed, callback) { 7932 try { 7933 callback(null, defaultSeedFile(needed)); 7934 } catch(e) { 7935 callback(e); 7936 } 7937 }; 7938 ctx.seedFileSync = defaultSeedFile; 7939 } 7940 7941 /** 7942 * Adds entropy to a prng ctx's accumulator. 7943 * 7944 * @param bytes the bytes of entropy as a string. 7945 */ 7946 ctx.collect = function(bytes) { 7947 // iterate over pools distributing entropy cyclically 7948 var count = bytes.length; 7949 for(var i = 0; i < count; ++i) { 7950 ctx.pools[ctx.pool].update(bytes.substr(i, 1)); 7951 ctx.pool = (ctx.pool === 31) ? 0 : ctx.pool + 1; 7952 } 7953 }; 7954 7955 /** 7956 * Collects an integer of n bits. 7957 * 7958 * @param i the integer entropy. 7959 * @param n the number of bits in the integer. 7960 */ 7961 ctx.collectInt = function(i, n) { 7962 var bytes = ''; 7963 for(var x = 0; x < n; x += 8) { 7964 bytes += String.fromCharCode((i >> x) & 0xFF); 7965 } 7966 ctx.collect(bytes); 7967 }; 7968 7969 /** 7970 * Registers a Web Worker to receive immediate entropy from the main thread. 7971 * This method is required until Web Workers can access the native crypto 7972 * API. This method should be called twice for each created worker, once in 7973 * the main thread, and once in the worker itself. 7974 * 7975 * @param worker the worker to register. 7976 */ 7977 ctx.registerWorker = function(worker) { 7978 // worker receives random bytes 7979 if(worker === self) { 7980 ctx.seedFile = function(needed, callback) { 7981 function listener(e) { 7982 var data = e.data; 7983 if(data.forge && data.forge.prng) { 7984 self.removeEventListener('message', listener); 7985 callback(data.forge.prng.err, data.forge.prng.bytes); 7986 } 7987 } 7988 self.addEventListener('message', listener); 7989 self.postMessage({forge: {prng: {needed: needed}}}); 7990 }; 7991 } else { 7992 // main thread sends random bytes upon request 7993 var listener = function(e) { 7994 var data = e.data; 7995 if(data.forge && data.forge.prng) { 7996 ctx.seedFile(data.forge.prng.needed, function(err, bytes) { 7997 worker.postMessage({forge: {prng: {err: err, bytes: bytes}}}); 7998 }); 7999 } 8000 }; 8001 // TODO: do we need to remove the event listener when the worker dies? 8002 worker.addEventListener('message', listener); 8003 } 8004 }; 8005 8006 return ctx; 8007}; 8008 8009} // end module implementation 8010 8011/* ########## Begin module wrapper ########## */ 8012var name = 'prng'; 8013if(typeof define !== 'function') { 8014 // NodeJS -> AMD 8015 if(typeof module === 'object' && module.exports) { 8016 var nodeJS = true; 8017 define = function(ids, factory) { 8018 factory(require, module); 8019 }; 8020 } else { 8021 // <script> 8022 if(typeof forge === 'undefined') { 8023 forge = {}; 8024 } 8025 return initModule(forge); 8026 } 8027} 8028// AMD 8029var deps;
8030var defineFunc = function(require, module) { 8031 module.exports = function(forge) { 8032 var mods = deps.map(function(dep) { 8033 return require(dep); 8034 }).concat(initModule); 8035 // handle circular dependencies 8036 forge = forge || {}; 8037 forge.defined = forge.defined || {}; 8038 if(forge.defined[name]) { 8039 return forge[name]; 8040 } 8041 forge.defined[name] = true; 8042 for(var i = 0; i < mods.length; ++i) { 8043 mods[i](forge); 8044 } 8045 return forge[name]; 8046 }; 8047}; 8048var tmpDefine = define; 8049define = function(ids, factory) { 8050 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 8051 if(nodeJS) { 8052 delete define; 8053 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 8054 } 8055 define = tmpDefine; 8056 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 8057}; 8058define(['require', 'module', './md', './util'], function() { 8059 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 8060}); 8061 8062})(); 8063 8064/** 8065 * An API for getting cryptographically-secure random bytes. The bytes are 8066 * generated using the Fortuna algorithm devised by Bruce Schneier and 8067 * Niels Ferguson. 8068 * 8069 * Getting strong random bytes is not yet easy to do in javascript. The only 8070 * truish random entropy that can be collected is from the mouse, keyboard, or 8071 * from timing with respect to page loads, etc. This generator makes a poor 8072 * attempt at providing random bytes when those sources haven't yet provided 8073 * enough entropy to initially seed or to reseed the PRNG. 8074 * 8075 * @author Dave Longley 8076 * 8077 * Copyright (c) 2009-2014 Digital Bazaar, Inc. 8078 */ 8079(function() { 8080/* ########## Begin module implementation ########## */ 8081function initModule(forge) { 8082 8083// forge.random already defined 8084if(forge.random && forge.random.getBytes) { 8085 return; 8086} 8087 8088(function(jQuery) { 8089 8090// the default prng plugin, uses AES-128 8091var prng_aes = {}; 8092var _prng_aes_output = new Array(4); 8093var _prng_aes_buffer = forge.util.createBuffer(); 8094prng_aes.formatKey = function(key) { 8095 // convert the key into 32-bit integers 8096 var tmp = forge.util.createBuffer(key); 8097 key = new Array(4); 8098 key[0] = tmp.getInt32(); 8099 key[1] = tmp.getInt32(); 8100 key[2] = tmp.getInt32(); 8101 key[3] = tmp.getInt32(); 8102 8103 // return the expanded key 8104 return forge.aes._expandKey(key, false); 8105}; 8106prng_aes.formatSeed = function(seed) { 8107 // convert seed into 32-bit integers 8108 var tmp = forge.util.createBuffer(seed); 8109 seed = new Array(4); 8110 seed[0] = tmp.getInt32(); 8111 seed[1] = tmp.getInt32(); 8112 seed[2] = tmp.getInt32(); 8113 seed[3] = tmp.getInt32(); 8114 return seed; 8115}; 8116prng_aes.cipher = function(key, seed) { 8117 forge.aes._updateBlock(key, seed, _prng_aes_output, false); 8118 _prng_aes_buffer.putInt32(_prng_aes_output[0]); 8119 _prng_aes_buffer.putInt32(_prng_aes_output[1]); 8120 _prng_aes_buffer.putInt32(_prng_aes_output[2]); 8121 _prng_aes_buffer.putInt32(_prng_aes_output[3]); 8122 return _prng_aes_buffer.getBytes(); 8123}; 8124prng_aes.increment = function(seed) { 8125 // FIXME: do we care about carry or signed issues? 8126 ++seed[3]; 8127 return seed; 8128}; 8129prng_aes.md = forge.md.sha256; 8130 8131/** 8132 * Creates a new PRNG. 8133 */ 8134function spawnPrng() { 8135 var ctx = forge.prng.create(prng_aes); 8136 8137 /** 8138 * Gets random bytes. If a native secure crypto API is unavailable, this 8139 * method tries to make the bytes more unpredictable by drawing from data that 8140 * can be collected from the user of the browser, eg: mouse movement. 8141 * 8142 * If a callback is given, this method will be called asynchronously. 8143 * 8144 * @param count the number of random bytes to get. 8145 * @param [callback(err, bytes)] called once the operation completes. 8146 * 8147 * @return the random bytes in a string. 8148 */ 8149 ctx.getBytes = function(count, callback) { 8150 return ctx.generate(count, callback); 8151 }; 8152 8153 /** 8154 * Gets random bytes asynchronously. If a native secure crypto API is 8155 * unavailable, this method tries to make the bytes more unpredictable by 8156 * drawing from data that can be collected from the user of the browser, 8157 * eg: mouse movement. 8158 * 8159 * @param count the number of random bytes to get. 8160 * 8161 * @return the random bytes in a string. 8162 */ 8163 ctx.getBytesSync = function(count) { 8164 return ctx.generate(count); 8165 }; 8166 8167 return ctx; 8168} 8169 8170// create default prng context
8171var _ctx = spawnPrng(); 8172 8173// add other sources of entropy only if window.crypto.getRandomValues is not 8174// available -- otherwise this source will be automatically used by the prng 8175var _nodejs = ( 8176 typeof process !== 'undefined' && process.versions && process.versions.node); 8177var getRandomValues = null; 8178if(typeof window !== 'undefined') { 8179 var _crypto = window.crypto || window.msCrypto; 8180 if(_crypto && _crypto.getRandomValues) { 8181 getRandomValues = function(arr) { 8182 return _crypto.getRandomValues(arr); 8183 }; 8184 } 8185} 8186if(forge.disableNativeCode || (!_nodejs && !getRandomValues)) { 8187 // if this is a web worker, do not use weak entropy, instead register to 8188 // receive strong entropy asynchronously from the main thread 8189 if(typeof window === 'undefined' || window.document === undefined) { 8190 // FIXME: 8191 } 8192 8193 // get load time entropy 8194 _ctx.collectInt(+new Date(), 32); 8195 8196 // add some entropy from navigator object 8197 if(typeof(navigator) !== 'undefined') { 8198 var _navBytes = ''; 8199 for(var key in navigator) { 8200 try { 8201 if(typeof(navigator[key]) == 'string') { 8202 _navBytes += navigator[key]; 8203 } 8204 } catch(e) { 8205 /* Some navigator keys might not be accessible, e.g. the geolocation 8206 attribute throws an exception if touched in Mozilla chrome:// 8207 context. 8208 8209 Silently ignore this and just don't use this as a source of 8210 entropy. */ 8211 } 8212 } 8213 _ctx.collect(_navBytes); 8214 _navBytes = null; 8215 } 8216 8217 // add mouse and keyboard collectors if jquery is available 8218 if(jQuery) { 8219 // set up mouse entropy capture 8220 jQuery().mousemove(function(e) { 8221 // add mouse coords 8222 _ctx.collectInt(e.clientX, 16); 8223 _ctx.collectInt(e.clientY, 16); 8224 }); 8225 8226 // set up keyboard entropy capture 8227 jQuery().keypress(function(e) { 8228 _ctx.collectInt(e.charCode, 8); 8229 }); 8230 } 8231} 8232 8233/* Random API */ 8234if(!forge.random) { 8235 forge.random = _ctx; 8236} else { 8237 // extend forge.random with _ctx 8238 for(var key in _ctx) { 8239 forge.random[key] = _ctx[key]; 8240 } 8241} 8242 8243// expose spawn PRNG 8244forge.random.createInstance = spawnPrng; 8245 8246})(typeof(jQuery) !== 'undefined' ? jQuery : null); 8247 8248} // end module implementation 8249 8250/* ########## Begin module wrapper ########## */ 8251var name = 'random'; 8252if(typeof define !== 'function') { 8253 // NodeJS -> AMD 8254 if(typeof module === 'object' && module.exports) { 8255 var nodeJS = true; 8256 define = function(ids, factory) { 8257 factory(require, module); 8258 }; 8259 } else { 8260 // <script> 8261 if(typeof forge === 'undefined') { 8262 forge = {}; 8263 } 8264 return initModule(forge); 8265 } 8266} 8267// AMD 8268var deps; 8269var defineFunc = function(require, module) { 8270 module.exports = function(forge) { 8271 var mods = deps.map(function(dep) { 8272 return require(dep); 8273 }).concat(initModule); 8274 // handle circular dependencies 8275 forge = forge || {}; 8276 forge.defined = forge.defined || {}; 8277 if(forge.defined[name]) { 8278 return forge[name]; 8279 } 8280 forge.defined[name] = true; 8281 for(var i = 0; i < mods.length; ++i) { 8282 mods[i](forge); 8283 } 8284 return forge[name]; 8285 }; 8286}; 8287var tmpDefine = define; 8288define = function(ids, factory) { 8289 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 8290 if(nodeJS) { 8291 delete define; 8292 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 8293 } 8294 define = tmpDefine; 8295 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 8296}; 8297define(['require', 'module', './aes', './md', './prng', './util'], function() { 8298 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 8299}); 8300})(); 8301 8302// Copyright (c) 2005 Tom Wu 8303// All Rights Reserved. 8304// See "LICENSE" for details. 8305 8306// Basic JavaScript BN library - subset useful for RSA encryption. 8307 8308/* 8309Licensing (LICENSE) 8310------------------- 8311 8312This software is covered under the following copyright: 8313*/ 8314/* 8315 * Copyright (c) 2003-2005 Tom Wu 8316 * All Rights Reserved. 8317 * 8318 * Permission is hereby granted, free of charge, to any person obtaining 8319 * a copy of this software and associated documentation files (the 8320 * "Software"), to deal in the Software without restriction, including 8321 * without limitation the rights to use, copy, modify, merge, publish, 8322 * distribute, sublicense, and/or sell copies of the Software, and to 8323 * permit persons to whom the Software is furnished to do so, subject to 8324 * the following conditions: 8325 * 8326 * The above copyright notice and this permission notice shall be 8327 * included in all copies or substantial portions of the Software. 8328 * 8329 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 8330 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 8331 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 8332 * 8333 * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, 8334 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER 8335 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF 8336 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT 8337 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 8338 * 8339 * In addition, the following condition applies: 8340 * 8341 * All redistributions must retain an intact copy of this copyright notice 8342 * and disclaimer. 8343 */ 8344/* 8345Address all questions regarding this license to: 8346 8347 Tom Wu 8348 [email protected] 8349*/ 8350 8351(function() { 8352/* ########## Begin module implementation ########## */ 8353function initModule(forge) { 8354 8355// Bits per digit 8356var dbits; 8357 8358// JavaScript engine analysis 8359var canary = 0xdeadbeefcafe; 8360var j_lm = ((canary&0xffffff)==0xefcafe); 8361 8362// (public) Constructor 8363function BigInteger(a,b,c) { 8364 this.data = []; 8365 if(a != null) 8366 if("number" == typeof a) this.fromNumber(a,b,c); 8367 else if(b == null && "string" != typeof a) this.fromString(a,256); 8368 else this.fromString(a,b); 8369} 8370 8371// return new, unset BigInteger 8372function nbi() { return new BigInteger(null); } 8373 8374// am: Compute w_j += (x*this_i), propagate carries, 8375// c is initial carry, returns final carry. 8376// c < 3*dvalue, x < 2*dvalue, this_i < dvalue 8377// We need to select the fastest one that works in this environment. 8378
8379// am1: use a single mult and divide to get the high bits, 8380// max digit bits should be 26 because 8381// max internal value = 2*dvalue^2-2*dvalue (< 2^53) 8382function am1(i,x,w,j,c,n) { 8383 while(--n >= 0) { 8384 var v = x*this.data[i++]+w.data[j]+c; 8385 c = Math.floor(v/0x4000000); 8386 w.data[j++] = v&0x3ffffff; 8387 } 8388 return c; 8389} 8390// am2 avoids a big mult-and-extract completely. 8391// Max digit bits should be <= 30 because we do bitwise ops 8392// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) 8393function am2(i,x,w,j,c,n) { 8394 var xl = x&0x7fff, xh = x>>15; 8395 while(--n >= 0) { 8396 var l = this.data[i]&0x7fff; 8397 var h = this.data[i++]>>15; 8398 var m = xh*l+h*xl; 8399 l = xl*l+((m&0x7fff)<<15)+w.data[j]+(c&0x3fffffff); 8400 c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); 8401 w.data[j++] = l&0x3fffffff; 8402 } 8403 return c; 8404} 8405// Alternately, set max digit bits to 28 since some 8406// browsers slow down when dealing with 32-bit numbers. 8407function am3(i,x,w,j,c,n) { 8408 var xl = x&0x3fff, xh = x>>14; 8409 while(--n >= 0) { 8410 var l = this.data[i]&0x3fff; 8411 var h = this.data[i++]>>14; 8412 var m = xh*l+h*xl; 8413 l = xl*l+((m&0x3fff)<<14)+w.data[j]+c; 8414 c = (l>>28)+(m>>14)+xh*h; 8415 w.data[j++] = l&0xfffffff; 8416 } 8417 return c; 8418} 8419 8420// node.js (no browser) 8421if(typeof(navigator) === 'undefined') 8422{ 8423 BigInteger.prototype.am = am3; 8424 dbits = 28; 8425} else if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { 8426 BigInteger.prototype.am = am2; 8427 dbits = 30; 8428} else if(j_lm && (navigator.appName != "Netscape")) { 8429 BigInteger.prototype.am = am1; 8430 dbits = 26; 8431} else { // Mozilla/Netscape seems to prefer am3 8432 BigInteger.prototype.am = am3; 8433 dbits = 28; 8434} 8435 8436BigInteger.prototype.DB = dbits; 8437BigInteger.prototype.DM = ((1<<dbits)-1); 8438BigInteger.prototype.DV = (1<<dbits); 8439 8440var BI_FP = 52; 8441BigInteger.prototype.FV = Math.pow(2,BI_FP); 8442BigInteger.prototype.F1 = BI_FP-dbits; 8443BigInteger.prototype.F2 = 2*dbits-BI_FP; 8444 8445// Digit conversions 8446var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; 8447var BI_RC = new Array(); 8448var rr,vv; 8449rr = "0".charCodeAt(0); 8450for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; 8451rr = "a".charCodeAt(0); 8452for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; 8453rr = "A".charCodeAt(0); 8454for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; 8455 8456function int2char(n) { return BI_RM.charAt(n); } 8457function intAt(s,i) { 8458 var c = BI_RC[s.charCodeAt(i)]; 8459 return (c==null)?-1:c; 8460} 8461 8462// (protected) copy this to r 8463function bnpCopyTo(r) { 8464 for(var i = this.t-1; i >= 0; --i) r.data[i] = this.data[i]; 8465 r.t = this.t; 8466 r.s = this.s; 8467} 8468 8469// (protected) set from integer value x, -DV <= x < DV 8470function bnpFromInt(x) { 8471 this.t = 1; 8472 this.s = (x<0)?-1:0; 8473 if(x > 0) this.data[0] = x; 8474 else if(x < -1) this.data[0] = x+this.DV; 8475 else this.t = 0; 8476} 8477 8478// return bigint initialized to value 8479function nbv(i) { var r = nbi(); r.fromInt(i); return r; } 8480 8481// (protected) set from string and radix 8482function bnpFromString(s,b) { 8483 var k; 8484 if(b == 16) k = 4; 8485 else if(b == 8) k = 3; 8486 else if(b == 256) k = 8; // byte array 8487 else if(b == 2) k = 1; 8488 else if(b == 32) k = 5; 8489 else if(b == 4) k = 2; 8490 else { this.fromRadix(s,b); return; } 8491 this.t = 0; 8492 this.s = 0; 8493 var i = s.length, mi = false, sh = 0; 8494 while(--i >= 0) { 8495 var x = (k==8)?s[i]&0xff:intAt(s,i); 8496 if(x < 0) { 8497 if(s.charAt(i) == "-") mi = true; 8498 continue; 8499 } 8500 mi = false; 8501 if(sh == 0) 8502 this.data[this.t++] = x; 8503 else if(sh+k > this.DB) { 8504 this.data[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh; 8505 this.data[this.t++] = (x>>(this.DB-sh)); 8506 } else 8507 this.data[this.t-1] |= x<<sh; 8508 sh += k; 8509 if(sh >= this.DB) sh -= this.DB; 8510 } 8511 if(k == 8 && (s[0]&0x80) != 0) { 8512 this.s = -1; 8513 if(sh > 0) this.data[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh; 8514 } 8515 this.clamp(); 8516 if(mi) BigInteger.ZERO.subTo(this,this); 8517} 8518 8519// (protected) clamp off excess high words 8520function bnpClamp() { 8521 var c = this.s&this.DM; 8522 while(this.t > 0 && this.data[this.t-1] == c) --this.t; 8523} 8524 8525// (public) return string representation in given radix 8526function bnToString(b) { 8527 if(this.s < 0) return "-"+this.negate().toString(b); 8528 var k; 8529 if(b == 16) k = 4; 8530 else if(b == 8) k = 3; 8531 else if(b == 2) k = 1; 8532 else if(b == 32) k = 5; 8533 else if(b == 4) k = 2; 8534 else return this.toRadix(b); 8535 var km = (1<<k)-1, d, m = false, r = "", i = this.t; 8536 var p = this.DB-(i*this.DB)%k; 8537 if(i-- > 0) { 8538 if(p < this.DB && (d = this.data[i]>>p) > 0) { m = true; r = int2char(d); } 8539 while(i >= 0) { 8540 if(p < k) { 8541 d = (this.data[i]&((1<<p)-1))<<(k-p); 8542 d |= this.data[--i]>>(p+=this.DB-k); 8543 } else { 8544 d = (this.data[i]>>(p-=k))&km; 8545 if(p <= 0) { p += this.DB; --i; } 8546 } 8547 if(d > 0) m = true; 8548 if(m) r += int2char(d); 8549 } 8550 } 8551 return m?r:"0"; 8552} 8553 8554// (public) -this 8555function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } 8556 8557// (public) |this| 8558function bnAbs() { return (this.s<0)?this.negate():this; } 8559 8560// (public) return + if this > a, - if this < a, 0 if equal 8561function bnCompareTo(a) { 8562 var r = this.s-a.s; 8563 if(r != 0) return r; 8564 var i = this.t; 8565 r = i-a.t; 8566 if(r != 0) return (this.s<0)?-r:r; 8567 while(--i >= 0) if((r=this.data[i]-a.data[i]) != 0) return r; 8568 return 0; 8569} 8570 8571// returns bit length of the integer x 8572function nbits(x) { 8573 var r = 1, t; 8574 if((t=x>>>16) != 0) { x = t; r += 16; } 8575 if((t=x>>8) != 0) { x = t; r += 8; } 8576 if((t=x>>4) != 0) { x = t; r += 4; } 8577 if((t=x>>2) != 0) { x = t; r += 2; } 8578 if((t=x>>1) != 0) { x = t; r += 1; } 8579 return r; 8580} 8581 8582// (public) return the number of bits in "this" 8583function bnBitLength() { 8584 if(this.t <= 0) return 0; 8585 return this.DB*(this.t-1)+nbits(this.data[this.t-1]^(this.s&this.DM)); 8586} 8587 8588// (protected) r = this << n*DB 8589function bnpDLShiftTo(n,r) { 8590 var i; 8591 for(i = this.t-1; i >= 0; --i) r.data[i+n] = this.data[i]; 8592 for(i = n-1; i >= 0; --i) r.data[i] = 0; 8593 r.t = this.t+n; 8594 r.s = this.s; 8595} 8596 8597// (protected) r = this >> n*DB 8598function bnpDRShiftTo(n,r) { 8599 for(var i = n; i < this.t; ++i) r.data[i-n] = this.data[i]; 8600 r.t = Math.max(this.t-n,0); 8601 r.s = this.s; 8602} 8603 8604// (protected) r = this << n 8605function bnpLShiftTo(n,r) { 8606 var bs = n%this.DB; 8607 var cbs = this.DB-bs; 8608 var bm = (1<<cbs)-1; 8609 var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i; 8610 for(i = this.t-1; i >= 0; --i) { 8611 r.data[i+ds+1] = (this.data[i]>>cbs)|c; 8612 c = (this.data[i]&bm)<<bs; 8613 } 8614 for(i = ds-1; i >= 0; --i) r.data[i] = 0; 8615 r.data[ds] = c; 8616 r.t = this.t+ds+1; 8617 r.s = this.s; 8618 r.clamp(); 8619} 8620 8621// (protected) r = this >> n 8622function bnpRShiftTo(n,r) { 8623 r.s = this.s; 8624 var ds = Math.floor(n/this.DB); 8625 if(ds >= this.t) { r.t = 0; return; } 8626 var bs = n%this.DB; 8627 var cbs = this.DB-bs; 8628 var bm = (1<<bs)-1; 8629 r.data[0] = this.data[ds]>>bs; 8630 for(var i = ds+1; i < this.t; ++i) { 8631 r.data[i-ds-1] |= (this.data[i]&bm)<<cbs; 8632 r.data[i-ds] = this.data[i]>>bs; 8633 } 8634 if(bs >
8634 0) r.data[this.t-ds-1] |= (this.s&bm)<<cbs; 8635 r.t = this.t-ds; 8636 r.clamp(); 8637} 8638 8639// (protected) r = this - a 8640function bnpSubTo(a,r) { 8641 var i = 0, c = 0, m = Math.min(a.t,this.t); 8642 while(i < m) { 8643 c += this.data[i]-a.data[i]; 8644 r.data[i++] = c&this.DM; 8645 c >>= this.DB; 8646 } 8647 if(a.t < this.t) { 8648 c -= a.s; 8649 while(i < this.t) { 8650 c += this.data[i]; 8651 r.data[i++] = c&this.DM; 8652 c >>= this.DB; 8653 } 8654 c += this.s; 8655 } else { 8656 c += this.s; 8657 while(i < a.t) { 8658 c -= a.data[i]; 8659 r.data[i++] = c&this.DM; 8660 c >>= this.DB; 8661 } 8662 c -= a.s; 8663 } 8664 r.s = (c<0)?-1:0; 8665 if(c < -1) r.data[i++] = this.DV+c; 8666 else if(c > 0) r.data[i++] = c; 8667 r.t = i; 8668 r.clamp(); 8669} 8670 8671// (protected) r = this * a, r != this,a (HAC 14.12) 8672// "this" should be the larger one if appropriate. 8673function bnpMultiplyTo(a,r) { 8674 var x = this.abs(), y = a.abs(); 8675 var i = x.t; 8676 r.t = i+y.t; 8677 while(--i >= 0) r.data[i] = 0; 8678 for(i = 0; i < y.t; ++i) r.data[i+x.t] = x.am(0,y.data[i],r,i,0,x.t); 8679 r.s = 0; 8680 r.clamp(); 8681 if(this.s != a.s) BigInteger.ZERO.subTo(r,r); 8682} 8683 8684// (protected) r = this^2, r != this (HAC 14.16) 8685function bnpSquareTo(r) { 8686 var x = this.abs(); 8687 var i = r.t = 2*x.t; 8688 while(--i >= 0) r.data[i] = 0; 8689 for(i = 0; i < x.t-1; ++i) { 8690 var c = x.am(i,x.data[i],r,2*i,0,1); 8691 if((r.data[i+x.t]+=x.am(i+1,2*x.data[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { 8692 r.data[i+x.t] -= x.DV; 8693 r.data[i+x.t+1] = 1; 8694 } 8695 } 8696 if(r.t > 0) r.data[r.t-1] += x.am(i,x.data[i],r,2*i,0,1); 8697 r.s = 0; 8698 r.clamp(); 8699} 8700 8701// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) 8702// r != q, this != m. q or r may be null. 8703function bnpDivRemTo(m,q,r) { 8704 var pm = m.abs(); 8705 if(pm.t <= 0) return; 8706 var pt = this.abs(); 8707 if(pt.t < pm.t) { 8708 if(q != null) q.fromInt(0); 8709 if(r != null) this.copyTo(r); 8710 return; 8711 } 8712 if(r == null) r = nbi(); 8713 var y = nbi(), ts = this.s, ms = m.s; 8714 var nsh = this.DB-nbits(pm.data[pm.t-1]); // normalize modulus 8715 if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } else { pm.copyTo(y); pt.copyTo(r); } 8716 var ys = y.t; 8717 var y0 = y.data[ys-1]; 8718 if(y0 == 0) return; 8719 var yt = y0*(1<<this.F1)+((ys>1)?y.data[ys-2]>>this.F2:0); 8720 var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2; 8721 var i = r.t, j = i-ys, t = (q==null)?nbi():q; 8722 y.dlShiftTo(j,t); 8723 if(r.compareTo(t) >= 0) { 8724 r.data[r.t++] = 1; 8725 r.subTo(t,r); 8726 } 8727 BigInteger.ONE.dlShiftTo(ys,t); 8728 t.subTo(y,y); // "negative" y so we can replace sub with am later 8729 while(y.t < ys) y.data[y.t++] = 0; 8730 while(--j >= 0) { 8731 // Estimate quotient digit 8732 var qd = (r.data[--i]==y0)?this.DM:Math.floor(r.data[i]*d1+(r.data[i-1]+e)*d2); 8733 if((r.data[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out 8734 y.dlShiftTo(j,t); 8735 r.subTo(t,r); 8736 while(r.data[i] < --qd) r.subTo(t,r); 8737 } 8738 } 8739 if(q != null) { 8740 r.drShiftTo(ys,q); 8741 if(ts != ms) BigInteger.ZERO.subTo(q,q); 8742 } 8743 r.t = ys; 8744 r.clamp(); 8745 if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder 8746 if(ts < 0) BigInteger.ZERO.subTo(r,r); 8747} 8748 8749// (public) this mod a 8750function bnMod(a) { 8751 var r = nbi(); 8752 this.abs().divRemTo(a,null,r); 8753 if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); 8754 return r; 8755} 8756 8757// Modular reduction using "classic" algorithm 8758function Classic(m) { this.m = m; } 8759function cConvert(x) { 8760 if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); 8761 else return x; 8762} 8763function cRevert(x) { return x; } 8764function cReduce(x) { x.divRemTo(this.m,null,x); } 8765function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 8766function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 8767 8768Classic.prototype.convert = cConvert; 8769Classic.prototype.revert = cRevert; 8770Classic.prototype.reduce = cReduce; 8771Classic.prototype.mulTo = cMulTo; 8772Classic.prototype.sqrTo = cSqrTo; 8773 8774// (protected) return "-1/this % 2^DB"; useful for Mont. reduction 8775// justification: 8776// xy == 1 (mod m) 8777// xy = 1+km 8778// xy(2-xy) = (1+km)(1-km) 8779// x[y(2-xy)] = 1-k^2m^2 8780// x[y(2-xy)] == 1 (mod m^2) 8781// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 8782// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. 8783// JS multiply "overflows" differently from C/C++, so care is needed here. 8784function bnpInvDigit() { 8785 if(this.t < 1) return 0; 8786 var x = this.data[0]; 8787 if((x&1) == 0) return 0; 8788 var y = x&3; // y == 1/x mod 2^2 8789 y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 8790 y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 8791 y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 8792 // last step - calculate inverse mod DV directly; 8793 // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints 8794 y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits 8795 // we really want the negative inverse, and -DV < y < DV 8796 return (y>0)?this.DV-y:-y; 8797} 8798 8799// Montgomery reduction 8800function Montgomery(m) { 8801 this.m = m; 8802 this.mp = m.invDigit(); 8803 this.mpl = this.mp&0x7fff; 8804 this.mph = this.mp>>15; 8805 this.um = (1<<(m.DB-15))-1; 8806 this.mt2 = 2*m.t; 8807} 8808 8809// xR mod m 8810function montConvert(x) { 8811 var r = nbi(); 8812 x.abs().dlShiftTo(this.m.t,r); 8813 r.divRemTo(this.m,null,r); 8814 if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); 8815 return r; 8816} 8817 8818// x/R mod m 8819function montRevert(x) { 8820 var r = nbi(); 8821 x.copyTo(r); 8822 this.reduce(r); 8823 return r; 8824} 8825 8826// x = x/R mod m (HAC 14.32) 8827function montReduce(x) { 8828 while(x.t <= this.mt2) // pad x so am has enough room later 8829 x.data[x.t++] = 0; 8830 for(var i = 0; i < this.m.t; ++i) { 8831 // faster way of calculating u0 = x.data[i]*mp mod DV 8832 var j = x.data[i]&0x7fff; 8833 var u0 = (j*this.mpl+(((j*this.mph+(x.data[i]>>15)*this.mpl)&this.um)<<15))&x.DM; 8834 // use am to combine the multiply-shift-add into one call 8835 j = i+this.m.t; 8836 x.data[j] += this.m.am(0,u0,x,i,0,this.m.t); 8837 // propagate carry 8838 while(x.data[j] >= x.DV) { x.data[j] -= x.DV; x.data[++j]++; } 8839 } 8840 x.clamp(); 8841 x.drShiftTo(this.m.t,x); 8842 if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 8843} 8844 8845// r = "x^2/R mod m"; x != r 8846function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 8847 8848// r = "xy/R mod m"; x,y != r 8849function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 8850 8851Montgomery.prototype.convert = montConvert; 8852Montgomery.prototype.revert = montRevert; 8853Montgomery.prototype.reduce = montReduce; 8854Montgomery.prototype.mulTo = montMulTo; 8855Montgomery.prototype.sqrTo = montSqrTo; 8856 8857// (protected) true iff this is even 8858function bnpIsEven() { return ((this.t>0)?(this.data[0]&1):this.s) == 0; } 8859 8860// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) 8861function bnpExp(e,z) { 8862 if(e > 0xffffffff || e < 1) return BigInteger.ONE; 8863 var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; 8864 g.copyTo(r); 8865 while(--i >= 0) { 8866 z.sqrTo(r,r2); 8867 if((e&(1<<i)) > 0) z.mulTo(r2,g,r); 8868 else { var t = r; r = r2; r2 = t; } 8869 } 8870 return z.revert(r); 8871} 8872 8873// (public) this^e % m, 0 <= e < 2^32 8874function bnModPowInt(e,m) { 8875 var z; 8876 if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); 8877 return this.exp(e,z); 8878} 8879 8880// protected 8881BigInteger.prototype.copyTo = bnpCopyTo; 8882BigInteger.prototype.fromInt = bnpFromInt; 8883BigInteger.prototype.fromString = bnpFromString; 8884BigInteger.prototype.clamp = bnpClamp; 8885BigInteger.prototype.dlShiftTo = bnpDLShiftTo; 8886BigInteger.prototype.drShiftTo = bnpDRShiftTo; 8887BigInteger.prototype.lShiftTo = bnpLShiftTo; 8888BigInteger.prototype.rShiftTo = bnpRShiftTo; 8889BigInteger.prototype.subTo = bnpSubTo; 8890BigInteger.prototype.multiplyTo = bnpMultiplyTo; 8891BigInteger.prototype.squareTo = bnpSquareTo; 8892BigInteger.prototype.divRemTo = bnpDivRemTo; 8893BigInteger.prototype.invDigit = bnpInvDigit; 8894BigInteger.prototype.isEven = bnpIsEven; 8895BigInteger.prototype.exp = bnpExp; 8896 8897// public 8898BigInteger.prototype.toString = bnToString; 8899BigInteger.prototype.negate = bnNegate; 8900BigInteger.prototype.abs = bnAbs; 8901BigInteger.prototype.compareTo = bnCompareTo; 8902BigInteger.prototype.bitLength = bnBitLength; 8903BigInteger.prototype.mod = bnMod; 8904BigInteger.prototype.modPowInt = bnModPowInt; 8905 8906// "constants" 8907BigInteger.ZERO = nbv(0); 8908BigInteger.ONE = nbv(1); 8909 8910// jsbn2 lib 8911 8912//Copyright (c) 2005-2009 Tom Wu 8913//All Rights Reserved. 8914//See "LICENSE" for details (See jsbn.js for LICENSE). 8915 8916//Extended JavaScript BN functions, required for RSA private ops. 8917 8918//Version 1.1: new BigInteger("0", 10) returns "proper" zero 8919 8920//(public) 8921function bnClone() { var r = nbi(); this.copyTo(r); return r; } 8922 8923//(public) return value as integer 8924function bnIntValue() { 8925if(this.s < 0) { 8926 if(this.t == 1) return this.data[0]-this.DV; 8927 else if(this.t == 0) return -1; 8928} else if(this.t == 1) return this.data[0]; 8929else if(this.t == 0) return 0; 8930// assumes 16 < DB < 32 8931return ((this.data[1]&((1<<(32-this.DB))-1))<<this.DB)|this.data[0]; 8932} 8933 8934//(public) return value as byte 8935function bnByteValue() { return (this.t==0)?this.s:(this.data[0]<<24)>>24; } 8936 8937//(public) return value as short (assumes DB>=16) 8938function bnShortValue() { return (this.t==0)?this.s:(this.data[0]<<16)>>16; } 8939 8940//(protected) return x s.t. r^x < DV 8941function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } 8942 8943//(public) 0 if this == 0, 1 if this > 0 8944function bnSigNum() { 8945if(this.s < 0) return -1; 8946else if(this.t <= 0 || (this.t == 1 && this.data[0] <= 0)) return 0; 8947else return 1; 8948} 8949 8950//(protected) convert to radix string 8951function bnpToRadix(b) { 8952if(b == null) b = 10; 8953if(this.signum() == 0 || b < 2 || b > 36) return "0"; 8954var cs = this.chunkSize(b); 8955var a = Math.pow(b,cs); 8956var d = nbv(a), y = nbi(), z = nbi(), r = ""; 8957this.divRemTo(d,y,z); 8958while(y.signum() > 0) { 8959 r = (a+z.intValue()).toString(b).substr(1) + r; 8960 y.divRemTo(d,y,z); 8961} 8962return z.intValue().toString(b) + r; 8963} 8964 8965//(protected) convert from radix string 8966function bnpFromRadix(s,b) { 8967this.fromInt(0); 8968if(b == null) b = 10; 8969var cs = this.chunkSize(b); 8970var d = Math.pow(b,cs), mi = false, j = 0, w = 0; 8971for(var i = 0; i < s.length; ++i) { 8972 var x = intAt(s,i); 8973 if(x < 0) { 8974 if(s.charAt(i) == "-" && this.signum() == 0) mi = true; 8975 continue; 8976 } 8977 w = b*w+x; 8978 if(++j >= cs) { 8979 this.dMultiply(d); 8980 this.dAddOffset(w,0); 8981 j = 0; 8982 w = 0; 8983 } 8984} 8985if(j > 0) { 8986 this.dMultiply(Math.pow(b,j)); 8987 this.dAddOffset(w,0); 8988} 8989if(mi) BigInteger.ZERO.subTo(this,this); 8990} 8991 8992//(protected) alternate constructor 8993function bnpFromNumber(a,b,c) { 8994if("number" == typeof b) { 8995 // new BigInteger(int,int,RNG) 8996 if(a < 2) this.fromInt(1); 8997 else { 8998 this.fromNumber(a,c);
8999 if(!this.testBit(a-1)) // force MSB set 9000 this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); 9001 if(this.isEven()) this.dAddOffset(1,0); // force odd 9002 while(!this.isProbablePrime(b)) { 9003 this.dAddOffset(2,0); 9004 if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); 9005 } 9006 } 9007} else { 9008 // new BigInteger(int,RNG) 9009 var x = new Array(), t = a&7; 9010 x.length = (a>>3)+1; 9011 b.nextBytes(x); 9012 if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0; 9013 this.fromString(x,256); 9014} 9015} 9016 9017//(public) convert to bigendian byte array 9018function bnToByteArray() { 9019var i = this.t, r = new Array(); 9020r[0] = this.s; 9021var p = this.DB-(i*this.DB)%8, d, k = 0; 9022if(i-- > 0) { 9023 if(p < this.DB && (d = this.data[i]>>p) != (this.s&this.DM)>>p) 9024 r[k++] = d|(this.s<<(this.DB-p)); 9025 while(i >= 0) { 9026 if(p < 8) { 9027 d = (this.data[i]&((1<<p)-1))<<(8-p); 9028 d |= this.data[--i]>>(p+=this.DB-8); 9029 } else { 9030 d = (this.data[i]>>(p-=8))&0xff; 9031 if(p <= 0) { p += this.DB; --i; } 9032 } 9033 if((d&0x80) != 0) d |= -256; 9034 if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; 9035 if(k > 0 || d != this.s) r[k++] = d; 9036 } 9037} 9038return r; 9039} 9040 9041function bnEquals(a) { return(this.compareTo(a)==0); } 9042function bnMin(a) { return(this.compareTo(a)<0)?this:a; } 9043function bnMax(a) { return(this.compareTo(a)>0)?this:a; } 9044 9045//(protected) r = this op a (bitwise) 9046function bnpBitwiseTo(a,op,r) { 9047var i, f, m = Math.min(a.t,this.t); 9048for(i = 0; i < m; ++i) r.data[i] = op(this.data[i],a.data[i]); 9049if(a.t < this.t) { 9050 f = a.s&this.DM; 9051 for(i = m; i < this.t; ++i) r.data[i] = op(this.data[i],f); 9052 r.t = this.t; 9053} else { 9054 f = this.s&this.DM; 9055 for(i = m; i < a.t; ++i) r.data[i] = op(f,a.data[i]); 9056 r.t = a.t; 9057} 9058r.s = op(this.s,a.s); 9059r.clamp(); 9060} 9061 9062//(public) this & a 9063function op_and(x,y) { return x&y; } 9064function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } 9065 9066//(public) this | a 9067function op_or(x,y) { return x|y; } 9068function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } 9069 9070//(public) this ^ a 9071function op_xor(x,y) { return x^y; } 9072function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } 9073 9074//(public) this & ~a 9075function op_andnot(x,y) { return x&~y; } 9076function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } 9077 9078//(public) ~this 9079function bnNot() { 9080var r = nbi(); 9081for(var i = 0; i < this.t; ++i) r.data[i] = this.DM&~this.data[i]; 9082r.t = this.t; 9083r.s = ~this.s; 9084return r; 9085} 9086 9087//(public) this << n 9088function bnShiftLeft(n) { 9089var r = nbi(); 9090if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); 9091return r; 9092} 9093 9094//(public) this >> n 9095function bnShiftRight(n) { 9096var r = nbi(); 9097if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); 9098return r; 9099} 9100 9101//return index of lowest 1-bit in x, x < 2^31 9102function lbit(x) { 9103if(x == 0) return -1; 9104var r = 0; 9105if((x&0xffff) == 0) { x >>= 16; r += 16; } 9106if((x&0xff) == 0) { x >>= 8; r += 8; } 9107if((x&0xf) == 0) { x >>= 4; r += 4; } 9108if((x&3) == 0) { x >>= 2; r += 2; } 9109if((x&1) == 0) ++r; 9110return r; 9111} 9112 9113//(public) returns index of lowest 1-bit (or -1 if none) 9114function bnGetLowestSetBit() { 9115for(var i = 0; i < this.t; ++i) 9116 if(this.data[i] != 0) return i*this.DB+lbit(this.data[i]); 9117if(this.s < 0) return this.t*this.DB; 9118return -1; 9119} 9120 9121//return number of 1 bits in x 9122function cbit(x) { 9123var r = 0; 9124while(x != 0) { x &= x-1; ++r; } 9125return r; 9126} 9127 9128//(public) return number of set bits 9129function bnBitCount() { 9130var r = 0, x = this.s&this.DM; 9131for(var i = 0; i < this.t; ++i) r += cbit(this.data[i]^x); 9132return r; 9133} 9134 9135//(public) true iff nth bit is set 9136function bnTestBit(n) { 9137var j = Math.floor(n/this.DB); 9138if(j >= this.t) return(this.s!=0); 9139return((this.data[j]&(1<<(n%this.DB)))!=0); 9140} 9141 9142//(protected) this op (1<<n) 9143function bnpChangeBit(n,op) { 9144var r = BigInteger.ONE.shiftLeft(n); 9145this.bitwiseTo(r,op,r); 9146return r; 9147} 9148 9149//(public) this | (1<<n) 9150function bnSetBit(n) { return this.changeBit(n,op_or); } 9151 9152//(public) this & ~(1<<n) 9153function bnClearBit(n) { return this.changeBit(n,op_andnot); } 9154 9155//(public) this ^ (1<<n) 9156function bnFlipBit(n) { return this.changeBit(n,op_xor); } 9157 9158//(protected) r = this + a 9159function bnpAddTo(a,r) { 9160var i = 0, c = 0, m = Math.min(a.t,this.t); 9161while(i < m) { 9162 c += this.data[i]+a.data[i]; 9163 r.data[i++] = c&this.DM; 9164 c >>= this.DB; 9165} 9166if(a.t < this.t) { 9167 c += a.s; 9168 while(i < this.t) { 9169 c += this.data[i]; 9170 r.data[i++] = c&this.DM; 9171 c >>= this.DB; 9172 } 9173 c += this.s; 9174} else { 9175 c += this.s; 9176 while(i < a.t) { 9177 c += a.data[i]; 9178 r.data[i++] = c&this.DM; 9179 c >>= this.DB; 9180 } 9181 c += a.s; 9182} 9183r.s = (c<0)?-1:0; 9184if(c > 0) r.data[i++] = c; 9185else if(c < -1) r.data[i++] = this.DV+c; 9186r.t = i; 9187r.clamp(); 9188} 9189 9190//(public) this + a 9191function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } 9192 9193//(public) this - a 9194function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } 9195 9196//(public) this * a 9197function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } 9198 9199//(public) this / a 9200function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } 9201 9202//(public) this % a 9203function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } 9204 9205//(public) [this/a,this%a] 9206function bnDivideAndRemainder(a) { 9207var q = nbi(), r = nbi(); 9208this.divRemTo(a,q,r); 9209return new Array(q,r); 9210} 9211 9212//(protected) this *= n, this >= 0, 1 < n < DV 9213function bnpDMultiply(n) { 9214this.data[this.t] = this.am(0,n-1,this,0,0,this.t); 9215++this.t; 9216this.clamp(); 9217} 9218 9219//(protected) this += n << w words, this >= 0 9220function bnpDAddOffset(n,w) { 9221if(n == 0) return; 9222while(this.t <= w) this.data[this.t++] = 0; 9223this.data[w] += n; 9224while(this.data[w] >= this.DV) { 9225 this.data[w] -= this.DV; 9226 if(++w >= this.t) this.data[this.t++] = 0; 9227 ++this.data[w]; 9228} 9229} 9230 9231//A "null" reducer 9232function NullExp() {} 9233function nNop(x) { return x; } 9234function nMulTo(x,y,r) { x.multiplyTo(y,r); } 9235function nSqrTo(x,r) { x.squareTo(r); } 9236 9237NullExp.prototype.convert = nNop; 9238NullExp.prototype.revert = nNop; 9239NullExp.prototype.mulTo = nMulTo; 9240NullExp.prototype.sqrTo = nSqrTo; 9241 9242//(public) this^e 9243function bnPow(e) { return this.exp(e,new NullExp()); } 9244 9245//(protected) r = lower n words of "this * a", a.t <= n 9246//"this" should be the larger one if appropriate. 9247function bnpMultiplyLowerTo(a,n,r) { 9248var i = Math.min(this.t+a.t,n); 9249r.s = 0; // assumes a,this >= 0 9250r.t = i; 9251while(i > 0) r.data[--i] = 0; 9252var j; 9253for(j = r.t-this.t; i < j; ++i) r.data[i+this.t] = this.am(0,a.data[i],r,i,0,this.t); 9254for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a.data[i],r,i,0,n-i); 9255r.clamp(); 9256} 9257 9258//(protected) r = "this * a" without lower n words, n > 0 9259//"this" should be the larger one if appropriate. 9260function bnpMultiplyUpperTo(a,n,r) { 9261--n; 9262var i = r.t = this.t+a.t-n; 9263r.s = 0; // assumes a,this >= 0
9264while(--i >= 0) r.data[i] = 0; 9265for(i = Math.max(n-this.t,0); i < a.t; ++i) 9266 r.data[this.t+i-n] = this.am(n-i,a.data[i],r,0,0,this.t+i-n); 9267r.clamp(); 9268r.drShiftTo(1,r); 9269} 9270 9271//Barrett modular reduction 9272function Barrett(m) { 9273// setup Barrett 9274this.r2 = nbi(); 9275this.q3 = nbi(); 9276BigInteger.ONE.dlShiftTo(2*m.t,this.r2); 9277this.mu = this.r2.divide(m); 9278this.m = m; 9279} 9280 9281function barrettConvert(x) { 9282if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); 9283else if(x.compareTo(this.m) < 0) return x; 9284else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } 9285} 9286 9287function barrettRevert(x) { return x; } 9288 9289//x = x mod m (HAC 14.42) 9290function barrettReduce(x) { 9291x.drShiftTo(this.m.t-1,this.r2); 9292if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } 9293this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); 9294this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); 9295while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); 9296x.subTo(this.r2,x); 9297while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 9298} 9299 9300//r = x^2 mod m; x != r 9301function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 9302 9303//r = x*y mod m; x,y != r 9304function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 9305 9306Barrett.prototype.convert = barrettConvert; 9307Barrett.prototype.revert = barrettRevert; 9308Barrett.prototype.reduce = barrettReduce; 9309Barrett.prototype.mulTo = barrettMulTo; 9310Barrett.prototype.sqrTo = barrettSqrTo; 9311 9312//(public) this^e % m (HAC 14.85) 9313function bnModPow(e,m) { 9314var i = e.bitLength(), k, r = nbv(1), z; 9315if(i <= 0) return r; 9316else if(i < 18) k = 1; 9317else if(i < 48) k = 3; 9318else if(i < 144) k = 4; 9319else if(i < 768) k = 5; 9320else k = 6; 9321if(i < 8) 9322 z = new Classic(m); 9323else if(m.isEven()) 9324 z = new Barrett(m); 9325else 9326 z = new Montgomery(m); 9327 9328// precomputation 9329var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1; 9330g[1] = z.convert(this); 9331if(k > 1) { 9332 var g2 = nbi(); 9333 z.sqrTo(g[1],g2); 9334 while(n <= km) { 9335 g[n] = nbi(); 9336 z.mulTo(g2,g[n-2],g[n]); 9337 n += 2; 9338 } 9339} 9340 9341var j = e.t-1, w, is1 = true, r2 = nbi(), t; 9342i = nbits(e.data[j])-1; 9343while(j >= 0) { 9344 if(i >= k1) w = (e.data[j]>>(i-k1))&km; 9345 else { 9346 w = (e.data[j]&((1<<(i+1))-1))<<(k1-i); 9347 if(j > 0) w |= e.data[j-1]>>(this.DB+i-k1); 9348 } 9349 9350 n = k; 9351 while((w&1) == 0) { w >>= 1; --n; } 9352 if((i -= n) < 0) { i += this.DB; --j; } 9353 if(is1) { // ret == 1, don't bother squaring or multiplying it 9354 g[w].copyTo(r); 9355 is1 = false; 9356 } else { 9357 while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } 9358 if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } 9359 z.mulTo(r2,g[w],r); 9360 } 9361 9362 while(j >= 0 && (e.data[j]&(1<<i)) == 0) { 9363 z.sqrTo(r,r2); t = r; r = r2; r2 = t; 9364 if(--i < 0) { i = this.DB-1; --j; } 9365 } 9366} 9367return z.revert(r); 9368} 9369 9370//(public) gcd(this,a) (HAC 14.54) 9371function bnGCD(a) { 9372var x = (this.s<0)?this.negate():this.clone(); 9373var y = (a.s<0)?a.negate():a.clone(); 9374if(x.compareTo(y) < 0) { var t = x; x = y; y = t; } 9375var i = x.getLowestSetBit(), g = y.getLowestSetBit(); 9376if(g < 0) return x; 9377if(i < g) g = i; 9378if(g > 0) { 9379 x.rShiftTo(g,x); 9380 y.rShiftTo(g,y); 9381} 9382while(x.signum() > 0) { 9383 if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); 9384 if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); 9385 if(x.compareTo(y) >= 0) { 9386 x.subTo(y,x); 9387 x.rShiftTo(1,x); 9388 } else { 9389 y.subTo(x,y); 9390 y.rShiftTo(1,y); 9391 } 9392} 9393if(g > 0) y.lShiftTo(g,y); 9394return y; 9395} 9396 9397//(protected) this % n, n < 2^26 9398function bnpModInt(n) { 9399if(n <= 0) return 0; 9400var d = this.DV%n, r = (this.s<0)?n-1:0; 9401if(this.t > 0) 9402 if(d == 0) r = this.data[0]%n; 9403 else for(var i = this.t-1; i >= 0; --i) r = (d*r+this.data[i])%n; 9404return r; 9405} 9406 9407//(public) 1/this % m (HAC 14.61) 9408function bnModInverse(m) { 9409var ac = m.isEven(); 9410if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; 9411var u = m.clone(), v = this.clone(); 9412var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); 9413while(u.signum() != 0) { 9414 while(u.isEven()) { 9415 u.rShiftTo(1,u); 9416 if(ac) { 9417 if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } 9418 a.rShiftTo(1,a); 9419 } else if(!b.isEven()) b.subTo(m,b); 9420 b.rShiftTo(1,b); 9421 } 9422 while(v.isEven()) { 9423 v.rShiftTo(1,v); 9424 if(ac) { 9425 if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } 9426 c.rShiftTo(1,c); 9427 } else if(!d.isEven()) d.subTo(m,d); 9428 d.rShiftTo(1,d); 9429 } 9430 if(u.compareTo(v) >= 0) { 9431 u.subTo(v,u); 9432 if(ac) a.subTo(c,a); 9433 b.subTo(d,b); 9434 } else { 9435 v.subTo(u,v); 9436 if(ac) c.subTo(a,c); 9437 d.subTo(b,d); 9438 } 9439} 9440if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; 9441if(d.compareTo(m) >= 0) return d.subtract(m); 9442if(d.signum() < 0) d.addTo(m,d); else return d; 9443if(d.signum() < 0) return d.add(m); else return d; 9444} 9445 9446var 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]; 9447var lplim = (1<<26)/lowprimes[lowprimes.length-1]; 9448 9449//(public) test primality with certainty >= 1-.5^t 9450function bnIsProbablePrime(t) { 9451var i, x = this.abs(); 9452if(x.t == 1 && x.data[0] <= lowprimes[lowprimes.length-1]) { 9453 for(i = 0; i < lowprimes.length; ++i) 9454 if(x.data[0] == lowprimes[i]) return true; 9455 return false;
9456} 9457if(x.isEven()) return false; 9458i = 1; 9459while(i < lowprimes.length) { 9460 var m = lowprimes[i], j = i+1; 9461 while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; 9462 m = x.modInt(m); 9463 while(i < j) if(m%lowprimes[i++] == 0) return false; 9464} 9465return x.millerRabin(t); 9466} 9467 9468//(protected) true if probably prime (HAC 4.24, Miller-Rabin) 9469function bnpMillerRabin(t) { 9470var n1 = this.subtract(BigInteger.ONE); 9471var k = n1.getLowestSetBit(); 9472if(k <= 0) return false; 9473var r = n1.shiftRight(k); 9474var prng = bnGetPrng(); 9475var a; 9476for(var i = 0; i < t; ++i) { 9477 // select witness 'a' at random from between 1 and n1 9478 do { 9479 a = new BigInteger(this.bitLength(), prng); 9480 } 9481 while(a.compareTo(BigInteger.ONE) <= 0 || a.compareTo(n1) >= 0); 9482 var y = a.modPow(r,this); 9483 if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { 9484 var j = 1; 9485 while(j++ < k && y.compareTo(n1) != 0) { 9486 y = y.modPowInt(2,this); 9487 if(y.compareTo(BigInteger.ONE) == 0) return false; 9488 } 9489 if(y.compareTo(n1) != 0) return false; 9490 } 9491} 9492return true; 9493} 9494 9495// get pseudo random number generator 9496function bnGetPrng() { 9497 // create prng with api that matches BigInteger secure random 9498 return { 9499 // x is an array to fill with bytes 9500 nextBytes: function(x) { 9501 for(var i = 0; i < x.length; ++i) { 9502 x[i] = Math.floor(Math.random() * 0x0100); 9503 } 9504 } 9505 }; 9506} 9507 9508//protected 9509BigInteger.prototype.chunkSize = bnpChunkSize; 9510BigInteger.prototype.toRadix = bnpToRadix; 9511BigInteger.prototype.fromRadix = bnpFromRadix; 9512BigInteger.prototype.fromNumber = bnpFromNumber; 9513BigInteger.prototype.bitwiseTo = bnpBitwiseTo; 9514BigInteger.prototype.changeBit = bnpChangeBit; 9515BigInteger.prototype.addTo = bnpAddTo; 9516BigInteger.prototype.dMultiply = bnpDMultiply; 9517BigInteger.prototype.dAddOffset = bnpDAddOffset; 9518BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; 9519BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; 9520BigInteger.prototype.modInt = bnpModInt; 9521BigInteger.prototype.millerRabin = bnpMillerRabin; 9522 9523//public 9524BigInteger.prototype.clone = bnClone; 9525BigInteger.prototype.intValue = bnIntValue; 9526BigInteger.prototype.byteValue = bnByteValue; 9527BigInteger.prototype.shortValue = bnShortValue; 9528BigInteger.prototype.signum = bnSigNum; 9529BigInteger.prototype.toByteArray = bnToByteArray; 9530BigInteger.prototype.equals = bnEquals; 9531BigInteger.prototype.min = bnMin; 9532BigInteger.prototype.max = bnMax; 9533BigInteger.prototype.and = bnAnd; 9534BigInteger.prototype.or = bnOr; 9535BigInteger.prototype.xor = bnXor; 9536BigInteger.prototype.andNot = bnAndNot; 9537BigInteger.prototype.not = bnNot; 9538BigInteger.prototype.shiftLeft = bnShiftLeft; 9539BigInteger.prototype.shiftRight = bnShiftRight; 9540BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; 9541BigInteger.prototype.bitCount = bnBitCount; 9542BigInteger.prototype.testBit = bnTestBit; 9543BigInteger.prototype.setBit = bnSetBit; 9544BigInteger.prototype.clearBit = bnClearBit; 9545BigInteger.prototype.flipBit = bnFlipBit; 9546BigInteger.prototype.add = bnAdd; 9547BigInteger.prototype.subtract = bnSubtract; 9548BigInteger.prototype.multiply = bnMultiply; 9549BigInteger.prototype.divide = bnDivide; 9550BigInteger.prototype.remainder = bnRemainder; 9551BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; 9552BigInteger.prototype.modPow = bnModPow; 9553BigInteger.prototype.modInverse = bnModInverse; 9554BigInteger.prototype.pow = bnPow; 9555BigInteger.prototype.gcd = bnGCD; 9556BigInteger.prototype.isProbablePrime = bnIsProbablePrime; 9557 9558//BigInteger interfaces not implemented in jsbn: 9559 9560//BigInteger(int signum, byte[] magnitude) 9561//double doubleValue() 9562//float floatValue() 9563//int hashCode() 9564//long longValue() 9565//static BigInteger valueOf(long val) 9566 9567forge.jsbn = forge.jsbn || {}; 9568forge.jsbn.BigInteger = BigInteger; 9569 9570} // end module implementation 9571 9572/* ########## Begin module wrapper ########## */ 9573var name = 'jsbn'; 9574if(typeof define !== 'function') { 9575 // NodeJS -> AMD 9576 if(typeof module === 'object' && module.exports) { 9577 var nodeJS = true; 9578 define = function(ids, factory) { 9579 factory(require, module); 9580 }; 9581 } else { 9582 // <script> 9583 if(typeof forge === 'undefined') { 9584 forge = {}; 9585 } 9586 return initModule(forge); 9587 } 9588} 9589// AMD 9590var deps;
9591var defineFunc = function(require, module) { 9592 module.exports = function(forge) { 9593 var mods = deps.map(function(dep) { 9594 return require(dep); 9595 }).concat(initModule); 9596 // handle circular dependencies 9597 forge = forge || {}; 9598 forge.defined = forge.defined || {}; 9599 if(forge.defined[name]) { 9600 return forge[name]; 9601 } 9602 forge.defined[name] = true; 9603 for(var i = 0; i < mods.length; ++i) { 9604 mods[i](forge); 9605 } 9606 return forge[name]; 9607 }; 9608}; 9609var tmpDefine = define; 9610define = function(ids, factory) { 9611 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 9612 if(nodeJS) { 9613 delete define; 9614 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 9615 } 9616 define = tmpDefine; 9617 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 9618}; 9619define(['require', 'module'], function() { 9620 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 9621}); 9622})(); 9623 9624/** 9625 * Javascript implementation of Abstract Syntax Notation Number One. 9626 * 9627 * @author Dave Longley 9628 * 9629 * Copyright (c) 2010-2015 Digital Bazaar, Inc. 9630 * 9631 * An API for storing data using the Abstract Syntax Notation Number One 9632 * format using DER (Distinguished Encoding Rules) encoding. This encoding is 9633 * commonly used to store data for PKI, i.e. X.509 Certificates, and this 9634 * implementation exists for that purpose. 9635 * 9636 * Abstract Syntax Notation Number One (ASN.1) is used to define the abstract 9637 * syntax of information without restricting the way the information is encoded 9638 * for transmission. It provides a standard that allows for open systems 9639 * communication. ASN.1 defines the syntax of information data and a number of 9640 * simple data types as well as a notation for describing them and specifying 9641 * values for them. 9642 * 9643 * The RSA algorithm creates public and private keys that are often stored in 9644 * X.509 or PKCS#X formats -- which use ASN.1 (encoded in DER format). This 9645 * class provides the most basic functionality required to store and load DSA 9646 * keys that are encoded according to ASN.1. 9647 * 9648 * The most common binary encodings for ASN.1 are BER (Basic Encoding Rules) 9649 * and DER (Distinguished Encoding Rules). DER is just a subset of BER that 9650 * has stricter requirements for how data must be encoded. 9651 * 9652 * Each ASN.1 structure has a tag (a byte identifying the ASN.1 structure type) 9653 * and a byte array for the value of this ASN1 structure which may be data or a 9654 * list of ASN.1 structures. 9655 * 9656 * Each ASN.1 structure using BER is (Tag-Length-Value): 9657 * 9658 * | byte 0 | bytes X | bytes Y | 9659 * |--------|---------|---------- 9660 * | tag | length | value | 9661 * 9662 * ASN.1 allows for tags to be of "High-tag-number form" which allows a tag to 9663 * be two or more octets, but that is not supported by this class. A tag is 9664 * only 1 byte. Bits 1-5 give the tag number (ie the data type within a 9665 * particular 'class'), 6 indicates whether or not the ASN.1 value is 9666 * constructed from other ASN.1 values, and bits 7 and 8 give the 'class'. If 9667 * bits 7 and 8 are both zero, the class is UNIVERSAL. If only bit 7 is set, 9668 * then the class is APPLICATION. If only bit 8 is set, then the class is 9669 * CONTEXT_SPECIFIC. If both bits 7 and 8 are set, then the class is PRIVATE. 9670 * The tag numbers for the data types for the class UNIVERSAL are listed below: 9671 * 9672 * UNIVERSAL 0 Reserved for use by the encoding rules 9673 * UNIVERSAL 1 Boolean type 9674 * UNIVERSAL 2 Integer type 9675 * UNIVERSAL 3 Bitstring type 9676 * UNIVERSAL 4 Octetstring type 9677 * UNIVERSAL 5 Null type 9678 * UNIVERSAL 6 Object identifier type 9679 * UNIVERSAL 7 Object descriptor type 9680 * UNIVERSAL 8 External type and Instance-of type 9681 * UNIVERSAL 9 Real type 9682 * UNIVERSAL 10 Enumerated type 9683 * UNIVERSAL 11 Embedded-pdv type 9684 * UNIVERSAL 12 UTF8String type 9685 * UNIVERSAL 13 Relative object identifier type 9686 * UNIVERSAL 14-15 Reserved for future editions 9687 * UNIVERSAL 16 Sequence and Sequence-of types 9688 * UNIVERSAL 17 Set and Set-of types 9689 * UNIVERSAL 18-22, 25-30 Character string types 9690 * UNIVERSAL 23-24 Time types 9691 * 9692 * The length of an ASN.1 structure is specified after the tag identifier. 9693 * There is a definite form and an indefinite form. The indefinite form may 9694 * be used if the encoding is constructed and not all immediately available. 9695 * The indefinite form is encoded using a length byte with only the 8th bit 9696 * set. The end of the constructed object is marked using end-of-contents 9697 * octets (two zero bytes). 9698 * 9699 * The definite form looks like this: 9700 * 9701 * The length may take up 1 or more bytes, it depends on the length of the 9702 * value of the ASN.1 structure. DER encoding requires that if the ASN.1 9703 * structure has a value that has a length greater than 127, more than 1 byte 9704 * will be used to store its length, otherwise just one byte will be used. 9705 * This is strict. 9706 * 9707 * In the case that the length of the ASN.1 value is less than 127, 1 octet 9708 * (byte) is used to store the "short form" length. The 8th bit has a value of
9709 * 0 indicating the length is "short form" and not "long form" and bits 7-1 9710 * give the length of the data. (The 8th bit is the left-most, most significant 9711 * bit: also known as big endian or network format). 9712 * 9713 * In the case that the length of the ASN.1 value is greater than 127, 2 to 9714 * 127 octets (bytes) are used to store the "long form" length. The first 9715 * byte's 8th bit is set to 1 to indicate the length is "long form." Bits 7-1 9716 * give the number of additional octets. All following octets are in base 256 9717 * with the most significant digit first (typical big-endian binary unsigned 9718 * integer storage). So, for instance, if the length of a value was 257, the 9719 * first byte would be set to: 9720 * 9721 * 10000010 = 130 = 0x82. 9722 * 9723 * This indicates there are 2 octets (base 256) for the length. The second and 9724 * third bytes (the octets just mentioned) would store the length in base 256: 9725 * 9726 * octet 2: 00000001 = 1 * 256^1 = 256 9727 * octet 3: 00000001 = 1 * 256^0 = 1 9728 * total = 257 9729 * 9730 * The algorithm for converting a js integer value of 257 to base-256 is: 9731 * 9732 * var value = 257; 9733 * var bytes = []; 9734 * bytes[0] = (value >>> 8) & 0xFF; // most significant byte first 9735 * bytes[1] = value & 0xFF; // least significant byte last 9736 * 9737 * On the ASN.1 UNIVERSAL Object Identifier (OID) type: 9738 * 9739 * An OID can be written like: "value1.value2.value3...valueN" 9740 * 9741 * The DER encoding rules: 9742 * 9743 * The first byte has the value 40 * value1 + value2. 9744 * The following bytes, if any, encode the remaining values. Each value is 9745 * encoded in base 128, most significant digit first (big endian), with as 9746 * few digits as possible, and the most significant bit of each byte set 9747 * to 1 except the last in each value's encoding. For example: Given the 9748 * OID "1.2.840.113549", its DER encoding is (remember each byte except the 9749 * last one in each encoding is OR'd with 0x80): 9750 * 9751 * byte 1: 40 * 1 + 2 = 42 = 0x2A. 9752 * bytes 2-3: 128 * 6 + 72 = 840 = 6 72 = 6 72 = 0x0648 = 0x8648 9753 * bytes 4-6: 16384 * 6 + 128 * 119 + 13 = 6 119 13 = 0x06770D = 0x86F70D 9754 * 9755 * The final value is: 0x2A864886F70D. 9756 * The full OID (including ASN.1 tag and length of 6 bytes) is: 9757 * 0x06062A864886F70D 9758 */ 9759(function() { 9760/* ########## Begin module implementation ########## */ 9761function initModule(forge) { 9762 9763/* ASN.1 API */ 9764var asn1 = forge.asn1 = forge.asn1 || {}; 9765 9766/** 9767 * ASN.1 classes. 9768 */ 9769asn1.Class = { 9770 UNIVERSAL: 0x00, 9771 APPLICATION: 0x40, 9772 CONTEXT_SPECIFIC: 0x80, 9773 PRIVATE: 0xC0 9774}; 9775 9776/** 9777 * ASN.1 types. Not all types are supported by this implementation, only 9778 * those necessary to implement a simple PKI are implemented. 9779 */ 9780asn1.Type = { 9781 NONE: 0, 9782 BOOLEAN: 1, 9783 INTEGER: 2, 9784 BITSTRING: 3, 9785 OCTETSTRING: 4, 9786 NULL: 5, 9787 OID: 6, 9788 ODESC: 7, 9789 EXTERNAL: 8, 9790 REAL: 9, 9791 ENUMERATED: 10, 9792 EMBEDDED: 11, 9793 UTF8: 12, 9794 ROID: 13, 9795 SEQUENCE: 16, 9796 SET: 17, 9797 PRINTABLESTRING: 19, 9798 IA5STRING: 22, 9799 UTCTIME: 23, 9800 GENERALIZEDTIME: 24, 9801 BMPSTRING: 30 9802}; 9803 9804/** 9805 * Creates a new asn1 object. 9806 * 9807 * @param tagClass the tag class for the object. 9808 * @param type the data type (tag number) for the object. 9809 * @param constructed true if the asn1 object is in constructed form. 9810 * @param value the value for the object, if it is not constructed. 9811 * 9812 * @return the asn1 object. 9813 */ 9814asn1.create = function(tagClass, type, constructed, value) { 9815 /* An asn1 object has a tagClass, a type, a constructed flag, and a 9816 value. The value's type depends on the constructed flag. If 9817 constructed, it will contain a list of other asn1 objects. If not, 9818 it will contain the ASN.1 value as an array of bytes formatted 9819 according to the ASN.1 data type. */ 9820 9821 // remove undefined values 9822 if(forge.util.isArray(value)) { 9823 var tmp = []; 9824 for(var i = 0; i < value.length; ++i) { 9825 if(value[i] !== undefined) { 9826 tmp.push(value[i]); 9827 } 9828 } 9829 value = tmp; 9830 } 9831 9832 return { 9833 tagClass: tagClass, 9834 type: type, 9835 constructed: constructed, 9836 composed: constructed || forge.util.isArray(value),
9837 value: value 9838 }; 9839}; 9840 9841/** 9842 * Gets the length of a BER-encoded ASN.1 value. 9843 * 9844 * In case the length is not specified, undefined is returned. 9845 * 9846 * @param b the BER-encoded ASN.1 byte buffer, starting with the first 9847 * length byte. 9848 * 9849 * @return the length of the BER-encoded ASN.1 value or undefined. 9850 */ 9851var _getValueLength = asn1.getBerValueLength = function(b) { 9852 // TODO: move this function and related DER/BER functions to a der.js 9853 // file; better abstract ASN.1 away from der/ber. 9854 var b2 = b.getByte(); 9855 if(b2 === 0x80) { 9856 return undefined; 9857 } 9858 9859 // see if the length is "short form" or "long form" (bit 8 set) 9860 var length; 9861 var longForm = b2 & 0x80; 9862 if(!longForm) { 9863 // length is just the first byte 9864 length = b2; 9865 } else { 9866 // the number of bytes the length is specified in bits 7 through 1 9867 // and each length byte is in big-endian base-256 9868 length = b.getInt((b2 & 0x7F) << 3); 9869 } 9870 return length; 9871}; 9872 9873/** 9874 * Parses an asn1 object from a byte buffer in DER format. 9875 * 9876 * @param bytes the byte buffer to parse from. 9877 * @param strict true to be strict when checking value lengths, false to 9878 * allow truncated values (default: true). 9879 * 9880 * @return the parsed asn1 object. 9881 */ 9882asn1.fromDer = function(bytes, strict) { 9883 if(strict === undefined) { 9884 strict = true; 9885 } 9886 9887 // wrap in buffer if needed 9888 if(typeof bytes === 'string') { 9889 bytes = forge.util.createBuffer(bytes); 9890 } 9891 9892 // minimum length for ASN.1 DER structure is 2 9893 if(bytes.length() < 2) { 9894 var error = new Error('Too few bytes to parse DER.'); 9895 error.bytes = bytes.length(); 9896 throw error; 9897 } 9898 9899 // get the first byte 9900 var b1 = bytes.getByte(); 9901 9902 // get the tag class 9903 var tagClass = (b1 & 0xC0); 9904 9905 // get the type (bits 1-5) 9906 var type = b1 & 0x1F; 9907 9908 // get the value length 9909 var length = _getValueLength(bytes); 9910 9911 // ensure there are enough bytes to get the value 9912 if(bytes.length() < length) { 9913 if(strict) { 9914 var error = new Error('Too few bytes to read ASN.1 value.'); 9915 error.detail = bytes.length() + ' < ' + length; 9916 throw error; 9917 } 9918 // Note: be lenient with truncated values 9919 length = bytes.length(); 9920 } 9921 9922 // prepare to get value 9923 var value; 9924 9925 // constructed flag is bit 6 (32 = 0x20) of the first byte 9926 var constructed = ((b1 & 0x20) === 0x20); 9927 9928 // determine if the value is composed of other ASN.1 objects (if its 9929 // constructed it will be and if its a BITSTRING it may be) 9930 var composed = constructed; 9931 if(!composed && tagClass === asn1.Class.UNIVERSAL && 9932 type === asn1.Type.BITSTRING && length > 1) { 9933 /* The first octet gives the number of bits by which the length of the 9934 bit string is less than the next multiple of eight (this is called 9935 the "number of unused bits"). 9936 9937 The second and following octets give the value of the bit string 9938 converted to an octet string. */ 9939 // if there are no unused bits, maybe the bitstring holds ASN.1 objs 9940 var read = bytes.read; 9941 var unused = bytes.getByte(); 9942 if(unused === 0) { 9943 // if the first byte indicates UNIVERSAL or CONTEXT_SPECIFIC, 9944 // and the length is valid, assume we've got an ASN.1 object 9945 b1 = bytes.getByte(); 9946 var tc = (b1 & 0xC0); 9947 if(tc === asn1.Class.UNIVERSAL || tc === asn1.Class.CONTEXT_SPECIFIC) { 9948 try { 9949 var len = _getValueLength(bytes); 9950 composed = (len === length - (bytes.read - read)); 9951 if(composed) { 9952 // adjust read/length to account for unused bits byte 9953 ++read; 9954 --length; 9955 } 9956 } catch(ex) {} 9957 } 9958 } 9959 // restore read pointer 9960 bytes.read = read; 9961 } 9962 9963 if(composed) { 9964 // parse child asn1 objects from the value 9965 value = []; 9966 if(length === undefined) { 9967 // asn1 object of indefinite length, read until end tag 9968 for(;;) { 9969 if(bytes.bytes(2) === String.fromCharCode(0, 0)) { 9970 bytes.getBytes(2); 9971 break; 9972 } 9973 value.push(asn1.fromDer(bytes, strict)); 9974 } 9975 } else { 9976 // parsing asn1 object of definite length 9977 var start = bytes.length(); 9978 while(length > 0) { 9979 value.push(asn1.fromDer(bytes, strict)); 9980 length -= start - bytes.length(); 9981 start = bytes.length(); 9982 } 9983 } 9984 } else { 9985 // asn1 not composed, get raw value 9986 // TODO: do DER to OID conversion and vice-versa in .toDer? 9987 9988 if(length === undefined) { 9989 if(strict) { 9990 throw new Error('Non-constructed ASN.1 object of indefinite length.'); 9991 } 9992 // be lenient and use remaining bytes 9993 length = bytes.length(); 9994 } 9995 9996 if(type === asn1.Type.BMPSTRING) { 9997 value = ''; 9998 for(var i = 0; i < length; i += 2) { 9999 value += String.fromCharCode(bytes.getInt16()); 10000 } 10001 } else { 10002 value = bytes.getBytes(length); 10003 } 10004 } 10005 10006 // create and return asn1 object 10007 return asn1.create(tagClass, type, constructed, value); 10008}; 10009 10010/** 10011 * Converts the given asn1 object to a buffer of bytes in DER format. 10012 * 10013 * @param asn1 the asn1 object to convert to bytes. 10014 * 10015 * @return the buffer of bytes. 10016 */ 10017asn1.toDer = function(obj) { 10018 var bytes = forge.util.createBuffer(); 10019 10020 // build the first byte 10021 var b1 = obj.tagClass | obj.type; 10022 10023 // for storing the ASN.1 value 10024 var value = forge.util.createBuffer(); 10025 10026 // if composed, use each child asn1 object's DER bytes as value 10027 if(obj.composed) { 10028 // turn on 6th bit (0x20 = 32) to indicate asn1 is constructed 10029 // from other asn1 objects 10030 if(obj.constructed) { 10031 b1 |= 0x20; 10032 } else { 10033 // type is a bit string, add unused bits of 0x00 10034 value.putByte(0x00); 10035 } 10036 10037 // add all of the child DER bytes together 10038 for(var i = 0; i < obj.value.length; ++i) { 10039 if(obj.value[i] !== undefined) { 10040 value.putBuffer(asn1.toDer(obj.value[i])); 10041 } 10042 } 10043 } else { 10044 // use asn1.value directly 10045 if(obj.type === asn1.Type.BMPSTRING) { 10046 for(var i = 0; i < obj.value.length; ++i) { 10047 value.putInt16(obj.value.charCodeAt(i)); 10048 } 10049 } else { 10050 // ensure integer is minimally-encoded 10051 if(obj.type === asn1.Type.INTEGER && 10052 obj.value.length > 1 && 10053 // leading 0x00 for positive integer 10054 ((obj.value.charCodeAt(0) === 0 && 10055 (obj.value.charCodeAt(1) & 0x80) === 0) || 10056 // leading 0xFF for negative integer 10057 (obj.value.charCodeAt(0) === 0xFF && 10058 (obj.value.charCodeAt(1) & 0x80) === 0x80))) { 10059 value.putBytes(obj.value.substr(1)); 10060 } else { 10061 value.putBytes(obj.value); 10062 } 10063 } 10064 } 10065 10066 // add tag byte 10067 bytes.putByte(b1); 10068 10069 // use "short form" encoding 10070 if(value.length() <= 127) { 10071 // one byte describes the length 10072 // bit 8 = 0 and bits 7-1 = length 10073 bytes.putByte(value.length() & 0x7F); 10074 } else { 10075 // use "long form" encoding 10076 // 2 to 127 bytes describe the length 10077 // first byte: bit 8 = 1 and bits 7-1 = # of additional bytes 10078 // other bytes: length in base 256, big-endian 10079 var len = value.length(); 10080 var lenBytes = ''; 10081 do { 10082 lenBytes += String.fromCharCode(len & 0xFF); 10083 len = len >>> 8; 10084 } while(len > 0); 10085 10086 // set first byte to # bytes used to store the length and turn on 10087 // bit 8 to indicate long-form length is used 10088 bytes.putByte(lenBytes.length | 0x80); 10089 10090 // concatenate length bytes in reverse since they were generated 10091 // little endian and we need big endian 10092 for(var i = lenBytes.length - 1; i >= 0; --i) {
10093 bytes.putByte(lenBytes.charCodeAt(i)); 10094 } 10095 } 10096 10097 // concatenate value bytes 10098 bytes.putBuffer(value); 10099 return bytes; 10100}; 10101 10102/** 10103 * Converts an OID dot-separated string to a byte buffer. The byte buffer 10104 * contains only the DER-encoded value, not any tag or length bytes. 10105 * 10106 * @param oid the OID dot-separated string. 10107 * 10108 * @return the byte buffer. 10109 */ 10110asn1.oidToDer = function(oid) { 10111 // split OID into individual values 10112 var values = oid.split('.'); 10113 var bytes = forge.util.createBuffer(); 10114 10115 // first byte is 40 * value1 + value2 10116 bytes.putByte(40 * parseInt(values[0], 10) + parseInt(values[1], 10)); 10117 // other bytes are each value in base 128 with 8th bit set except for 10118 // the last byte for each value 10119 var last, valueBytes, value, b; 10120 for(var i = 2; i < values.length; ++i) { 10121 // produce value bytes in reverse because we don't know how many 10122 // bytes it will take to store the value 10123 last = true; 10124 valueBytes = []; 10125 value = parseInt(values[i], 10); 10126 do { 10127 b = value & 0x7F; 10128 value = value >>> 7; 10129 // if value is not last, then turn on 8th bit 10130 if(!last) { 10131 b |= 0x80; 10132 } 10133 valueBytes.push(b); 10134 last = false; 10135 } while(value > 0); 10136 10137 // add value bytes in reverse (needs to be in big endian) 10138 for(var n = valueBytes.length - 1; n >= 0; --n) { 10139 bytes.putByte(valueBytes[n]); 10140 } 10141 } 10142 10143 return bytes; 10144}; 10145 10146/** 10147 * Converts a DER-encoded byte buffer to an OID dot-separated string. The 10148 * byte buffer should contain only the DER-encoded value, not any tag or 10149 * length bytes. 10150 * 10151 * @param bytes the byte buffer. 10152 * 10153 * @return the OID dot-separated string. 10154 */ 10155asn1.derToOid = function(bytes) { 10156 var oid; 10157 10158 // wrap in buffer if needed 10159 if(typeof bytes === 'string') { 10160 bytes = forge.util.createBuffer(bytes); 10161 } 10162 10163 // first byte is 40 * value1 + value2 10164 var b = bytes.getByte(); 10165 oid = Math.floor(b / 40) + '.' + (b % 40); 10166 10167 // other bytes are each value in base 128 with 8th bit set except for 10168 // the last byte for each value 10169 var value = 0; 10170 while(bytes.length() > 0) { 10171 b = bytes.getByte(); 10172 value = value << 7; 10173 // not the last byte for the value 10174 if(b & 0x80) { 10175 value += b & 0x7F; 10176 } else { 10177 // last byte 10178 oid += '.' + (value + b); 10179 value = 0; 10180 } 10181 } 10182 10183 return oid; 10184}; 10185 10186/** 10187 * Converts a UTCTime value to a date. 10188 * 10189 * Note: GeneralizedTime has 4 digits for the year and is used for X.509 10190 * dates passed 2049. Parsing that structure hasn't been implemented yet. 10191 * 10192 * @param utc the UTCTime value to convert. 10193 * 10194 * @return the date. 10195 */ 10196asn1.utcTimeToDate = function(utc) { 10197 /* The following formats can be used: 10198 10199 YYMMDDhhmmZ 10200 YYMMDDhhmm+hh'mm' 10201 YYMMDDhhmm-hh'mm' 10202 YYMMDDhhmmssZ 10203 YYMMDDhhmmss+hh'mm' 10204 YYMMDDhhmmss-hh'mm' 10205 10206 Where: 10207 10208 YY is the least significant two digits of the year 10209 MM is the month (01 to 12) 10210 DD is the day (01 to 31) 10211 hh is the hour (00 to 23) 10212 mm are the minutes (00 to 59) 10213 ss are the seconds (00 to 59) 10214 Z indicates that local time is GMT, + indicates that local time is 10215 later than GMT, and - indicates that local time is earlier than GMT 10216 hh' is the absolute value of the offset from GMT in hours 10217 mm' is the absolute value of the offset from GMT in minutes */ 10218 var date = new Date(); 10219 10220 // if YY >= 50 use 19xx, if YY < 50 use 20xx 10221 var year = parseInt(utc.substr(0, 2), 10); 10222 year = (year >= 50) ? 1900 + year : 2000 + year; 10223 var MM = parseInt(utc.substr(2, 2), 10) - 1; // use 0-11 for month 10224 var DD = parseInt(utc.substr(4, 2), 10); 10225 var hh = parseInt(utc.substr(6, 2), 10); 10226 var mm = parseInt(utc.substr(8, 2), 10); 10227 var ss = 0; 10228 10229 // not just YYMMDDhhmmZ 10230 if(utc.length > 11) { 10231 // get character after minutes 10232 var c = utc.charAt(10); 10233 var end = 10; 10234 10235 // see if seconds are present 10236 if(c !== '+' && c !== '-') { 10237 // get seconds 10238 ss = parseInt(utc.substr(10, 2), 10); 10239 end += 2; 10240 } 10241 } 10242 10243 // update date 10244 date.setUTCFullYear(year, MM, DD); 10245 date.setUTCHours(hh, mm, ss, 0); 10246 10247 if(end) { 10248 // get +/- after end of time 10249 c = utc.charAt(end); 10250 if(c === '+' || c === '-') { 10251 // get hours+minutes offset 10252 var hhoffset = parseInt(utc.substr(end + 1, 2), 10); 10253 var mmoffset = parseInt(utc.substr(end + 4, 2), 10); 10254 10255 // calculate offset in milliseconds 10256 var offset = hhoffset * 60 + mmoffset; 10257 offset *= 60000; 10258 10259 // apply offset 10260 if(c === '+') { 10261 date.setTime(+date - offset); 10262 } else { 10263 date.setTime(+date + offset); 10264 } 10265 } 10266 } 10267 10268 return date; 10269}; 10270 10271/** 10272 * Converts a GeneralizedTime value to a date. 10273 * 10274 * @param gentime the GeneralizedTime value to convert. 10275 * 10276 * @return the date. 10277 */ 10278asn1.generalizedTimeToDate = function(gentime) { 10279 /* The following formats can be used: 10280 10281 YYYYMMDDHHMMSS 10282 YYYYMMDDHHMMSS.fff 10283 YYYYMMDDHHMMSSZ 10284 YYYYMMDDHHMMSS.fffZ 10285 YYYYMMDDHHMMSS+hh'mm' 10286 YYYYMMDDHHMMSS.fff+hh'mm' 10287 YYYYMMDDHHMMSS-hh'mm' 10288 YYYYMMDDHHMMSS.fff-hh'mm' 10289 10290 Where: 10291 10292 YYYY is the year 10293 MM is the month (01 to 12) 10294 DD is the day (01 to 31) 10295 hh is the hour (00 to 23) 10296 mm are the minutes (00 to 59) 10297 ss are the seconds (00 to 59) 10298 .fff is the second fraction, accurate to three decimal places 10299 Z indicates that local time is GMT, + indicates that local time is 10300 later than GMT, and - indicates that local time is earlier than GMT 10301 hh' is the absolute value of the offset from GMT in hours 10302 mm' is the absolute value of the offset from GMT in minutes */ 10303 var date = new Date(); 10304 10305 var YYYY = parseInt(gentime.substr(0, 4), 10); 10306 var MM = parseInt(gentime.substr(4, 2), 10) - 1; // use 0-11 for month 10307 var DD = parseInt(gentime.substr(6, 2), 10); 10308 var hh = parseInt(gentime.substr(8, 2), 10); 10309 var mm = parseInt(gentime.substr(10, 2), 10); 10310 var ss = parseInt(gentime.substr(12, 2), 10); 10311 var fff = 0; 10312 var offset = 0; 10313 var isUTC = false;
10314 10315 if(gentime.charAt(gentime.length - 1) === 'Z') { 10316 isUTC = true; 10317 } 10318 10319 var end = gentime.length - 5, c = gentime.charAt(end); 10320 if(c === '+' || c === '-') { 10321 // get hours+minutes offset 10322 var hhoffset = parseInt(gentime.substr(end + 1, 2), 10); 10323 var mmoffset = parseInt(gentime.substr(end + 4, 2), 10); 10324 10325 // calculate offset in milliseconds 10326 offset = hhoffset * 60 + mmoffset; 10327 offset *= 60000; 10328 10329 // apply offset 10330 if(c === '+') { 10331 offset *= -1; 10332 } 10333 10334 isUTC = true; 10335 } 10336 10337 // check for second fraction 10338 if(gentime.charAt(14) === '.') { 10339 fff = parseFloat(gentime.substr(14), 10) * 1000; 10340 } 10341 10342 if(isUTC) { 10343 date.setUTCFullYear(YYYY, MM, DD); 10344 date.setUTCHours(hh, mm, ss, fff); 10345 10346 // apply offset 10347 date.setTime(+date + offset); 10348 } else { 10349 date.setFullYear(YYYY, MM, DD); 10350 date.setHours(hh, mm, ss, fff); 10351 } 10352 10353 return date; 10354}; 10355 10356/** 10357 * Converts a date to a UTCTime value. 10358 * 10359 * Note: GeneralizedTime has 4 digits for the year and is used for X.509 10360 * dates passed 2049. Converting to a GeneralizedTime hasn't been 10361 * implemented yet. 10362 * 10363 * @param date the date to convert. 10364 * 10365 * @return the UTCTime value. 10366 */ 10367asn1.dateToUtcTime = function(date) { 10368 // TODO: validate; currently assumes proper format 10369 if(typeof date === 'string') { 10370 return date; 10371 } 10372 10373 var rval = ''; 10374 10375 // create format YYMMDDhhmmssZ 10376 var format = []; 10377 format.push(('' + date.getUTCFullYear()).substr(2)); 10378 format.push('' + (date.getUTCMonth() + 1)); 10379 format.push('' + date.getUTCDate()); 10380 format.push('' + date.getUTCHours()); 10381 format.push('' + date.getUTCMinutes()); 10382 format.push('' + date.getUTCSeconds()); 10383 10384 // ensure 2 digits are used for each format entry 10385 for(var i = 0; i < format.length; ++i) { 10386 if(format[i].length < 2) { 10387 rval += '0'; 10388 } 10389 rval += format[i]; 10390 } 10391 rval += 'Z'; 10392 10393 return rval; 10394}; 10395 10396/** 10397 * Converts a date to a GeneralizedTime value. 10398 * 10399 * @param date the date to convert. 10400 * 10401 * @return the GeneralizedTime value as a string. 10402 */ 10403asn1.dateToGeneralizedTime = function(date) { 10404 // TODO: validate; currently assumes proper format 10405 if(typeof date === 'string') { 10406 return date; 10407 } 10408 10409 var rval = ''; 10410 10411 // create format YYYYMMDDHHMMSSZ 10412 var format = []; 10413 format.push('' + date.getUTCFullYear()); 10414 format.push('' + (date.getUTCMonth() + 1)); 10415 format.push('' + date.getUTCDate()); 10416 format.push('' + date.getUTCHours()); 10417 format.push('' + date.getUTCMinutes()); 10418 format.push('' + date.getUTCSeconds()); 10419 10420 // ensure 2 digits are used for each format entry 10421 for(var i = 0; i < format.length; ++i) { 10422 if(format[i].length < 2) { 10423 rval += '0'; 10424 } 10425 rval += format[i]; 10426 } 10427 rval += 'Z'; 10428 10429 return rval; 10430}; 10431 10432/** 10433 * Converts a javascript integer to a DER-encoded byte buffer to be used 10434 * as the value for an INTEGER type. 10435 * 10436 * @param x the integer. 10437 * 10438 * @return the byte buffer. 10439 */ 10440asn1.integerToDer = function(x) { 10441 var rval = forge.util.createBuffer(); 10442 if(x >= -0x80 && x < 0x80) { 10443 return rval.putSignedInt(x, 8); 10444 } 10445 if(x >= -0x8000 && x < 0x8000) { 10446 return rval.putSignedInt(x, 16); 10447 } 10448 if(x >= -0x800000 && x < 0x800000) { 10449 return rval.putSignedInt(x, 24); 10450 } 10451 if(x >= -0x80000000 && x < 0x80000000) { 10452 return rval.putSignedInt(x, 32); 10453 } 10454 var error = new Error('Integer too large; max is 32-bits.'); 10455 error.integer = x; 10456 throw error; 10457}; 10458 10459/** 10460 * Converts a DER-encoded byte buffer to a javascript integer. This is 10461 * typically used to decode the value of an INTEGER type. 10462 * 10463 * @param bytes the byte buffer. 10464 * 10465 * @return the integer. 10466 */ 10467asn1.derToInteger = function(bytes) { 10468 // wrap in buffer if needed 10469 if(typeof bytes === 'string') { 10470 bytes = forge.util.createBuffer(bytes); 10471 } 10472 10473 var n = bytes.length() * 8; 10474 if(n > 32) { 10475 throw new Error('Integer too large; max is 32-bits.'); 10476 } 10477 return bytes.getSignedInt(n); 10478}; 10479 10480/** 10481 * Validates the that given ASN.1 object is at least a super set of the 10482 * given ASN.1 structure. Only tag classes and types are checked. An 10483 * optional map may also be provided to capture ASN.1 values while the 10484 * structure is checked. 10485 * 10486 * To capture an ASN.1 value, set an object in the validator's 'capture' 10487 * parameter to the key to use in the capture map. To capture the full 10488 * ASN.1 object, specify 'captureAsn1'. 10489 * 10490 * Objects in the validator may set a field 'optional' to true to indicate 10491 * that it isn't necessary to pass validation. 10492 * 10493 * @param obj the ASN.1 object to validate. 10494 * @param v the ASN.1 structure validator. 10495 * @param capture an optional map to capture values in. 10496 * @param errors an optional array for storing validation errors. 10497 * 10498 * @return true on success, false on failure. 10499 */ 10500asn1.validate = function(obj, v, capture, errors) { 10501 var rval = false;
10502 10503 // ensure tag class and type are the same if specified 10504 if((obj.tagClass === v.tagClass || typeof(v.tagClass) === 'undefined') && 10505 (obj.type === v.type || typeof(v.type) === 'undefined')) { 10506 // ensure constructed flag is the same if specified 10507 if(obj.constructed === v.constructed || 10508 typeof(v.constructed) === 'undefined') { 10509 rval = true; 10510 10511 // handle sub values 10512 if(v.value && forge.util.isArray(v.value)) { 10513 var j = 0; 10514 for(var i = 0; rval && i < v.value.length; ++i) { 10515 rval = v.value[i].optional || false; 10516 if(obj.value[j]) { 10517 rval = asn1.validate(obj.value[j], v.value[i], capture, errors); 10518 if(rval) { 10519 ++j; 10520 } else if(v.value[i].optional) { 10521 rval = true; 10522 } 10523 } 10524 if(!rval && errors) { 10525 errors.push( 10526 '[' + v.name + '] ' + 10527 'Tag class "' + v.tagClass + '", type "' + 10528 v.type + '" expected value length "' + 10529 v.value.length + '", got "' + 10530 obj.value.length + '"'); 10531 } 10532 } 10533 } 10534 10535 if(rval && capture) { 10536 if(v.capture) { 10537 capture[v.capture] = obj.value; 10538 } 10539 if(v.captureAsn1) { 10540 capture[v.captureAsn1] = obj; 10541 } 10542 } 10543 } else if(errors) { 10544 errors.push( 10545 '[' + v.name + '] ' + 10546 'Expected constructed "' + v.constructed + '", got "' + 10547 obj.constructed + '"'); 10548 } 10549 } else if(errors) { 10550 if(obj.tagClass !== v.tagClass) { 10551 errors.push( 10552 '[' + v.name + '] ' + 10553 'Expected tag class "' + v.tagClass + '", got "' + 10554 obj.tagClass + '"'); 10555 } 10556 if(obj.type !== v.type) { 10557 errors.push( 10558 '[' + v.name + '] ' + 10559 'Expected type "' + v.type + '", got "' + obj.type + '"'); 10560 } 10561 } 10562 return rval; 10563}; 10564 10565// regex for testing for non-latin characters 10566var _nonLatinRegex = /[^\\u0000-\\u00ff]/; 10567 10568/** 10569 * Pretty prints an ASN.1 object to a string. 10570 * 10571 * @param obj the object to write out. 10572 * @param level the level in the tree. 10573 * @param indentation the indentation to use. 10574 * 10575 * @return the string. 10576 */ 10577asn1.prettyPrint = function(obj, level, indentation) { 10578 var rval = ''; 10579 10580 // set default level and indentation 10581 level = level || 0; 10582 indentation = indentation || 2; 10583 10584 // start new line for deep levels 10585 if(level > 0) { 10586 rval += '\n'; 10587 } 10588 10589 // create indent 10590 var indent = ''; 10591 for(var i = 0; i < level * indentation; ++i) { 10592 indent += ' '; 10593 } 10594 10595 // print class:type 10596 rval += indent + 'Tag: '; 10597 switch(obj.tagClass) { 10598 case asn1.Class.UNIVERSAL: 10599 rval += 'Universal:'; 10600 break; 10601 case asn1.Class.APPLICATION: 10602 rval += 'Application:'; 10603 break; 10604 case asn1.Class.CONTEXT_SPECIFIC: 10605 rval += 'Context-Specific:'; 10606 break; 10607 case asn1.Class.PRIVATE: 10608 rval += 'Private:'; 10609 break; 10610 } 10611 10612 if(obj.tagClass === asn1.Class.UNIVERSAL) { 10613 rval += obj.type; 10614 10615 // known types 10616 switch(obj.type) { 10617 case asn1.Type.NONE: 10618 rval += ' (None)'; 10619 break; 10620 case asn1.Type.BOOLEAN: 10621 rval += ' (Boolean)'; 10622 break; 10623 case asn1.Type.BITSTRING: 10624 rval += ' (Bit string)'; 10625 break; 10626 case asn1.Type.INTEGER: 10627 rval += ' (Integer)'; 10628 break; 10629 case asn1.Type.OCTETSTRING: 10630 rval += ' (Octet string)'; 10631 break; 10632 case asn1.Type.NULL: 10633 rval += ' (Null)'; 10634 break; 10635 case asn1.Type.OID: 10636 rval += ' (Object Identifier)'; 10637 break; 10638 case asn1.Type.ODESC: 10639 rval += ' (Object Descriptor)'; 10640 break; 10641 case asn1.Type.EXTERNAL: 10642 rval += ' (External or Instance of)'; 10643 break; 10644 case asn1.Type.REAL: 10645 rval += ' (Real)'; 10646 break; 10647 case asn1.Type.ENUMERATED: 10648 rval += ' (Enumerated)'; 10649 break; 10650 case asn1.Type.EMBEDDED: 10651 rval += ' (Embedded PDV)'; 10652 break; 10653 case asn1.Type.UTF8: 10654 rval += ' (UTF8)'; 10655 break; 10656 case asn1.Type.ROID: 10657 rval += ' (Relative Object Identifier)'; 10658 break; 10659 case asn1.Type.SEQUENCE: 10660 rval += ' (Sequence)'; 10661 break; 10662 case asn1.Type.SET: 10663 rval += ' (Set)'; 10664 break; 10665 case asn1.Type.PRINTABLESTRING: 10666 rval += ' (Printable String)'; 10667 break; 10668 case asn1.Type.IA5String: 10669 rval += ' (IA5String (ASCII))'; 10670 break; 10671 case asn1.Type.UTCTIME: 10672 rval += ' (UTC time)'; 10673 break; 10674 case asn1.Type.GENERALIZEDTIME: 10675 rval += ' (Generalized time)'; 10676 break; 10677 case asn1.Type.BMPSTRING: 10678 rval += ' (BMP String)'; 10679 break; 10680 } 10681 } else { 10682 rval += obj.type; 10683 } 10684 10685 rval += '\n'; 10686 rval += indent + 'Constructed: ' + obj.constructed + '\n'; 10687 10688 if(obj.composed) { 10689 var subvalues = 0; 10690 var sub = ''; 10691 for(var i = 0; i < obj.value.length; ++i) { 10692 if(obj.value[i] !== undefined) { 10693 subvalues += 1;
10694 sub += asn1.prettyPrint(obj.value[i], level + 1, indentation); 10695 if((i + 1) < obj.value.length) { 10696 sub += ','; 10697 } 10698 } 10699 } 10700 rval += indent + 'Sub values: ' + subvalues + sub; 10701 } else { 10702 rval += indent + 'Value: '; 10703 if(obj.type === asn1.Type.OID) { 10704 var oid = asn1.derToOid(obj.value); 10705 rval += oid; 10706 if(forge.pki && forge.pki.oids) { 10707 if(oid in forge.pki.oids) { 10708 rval += ' (' + forge.pki.oids[oid] + ') '; 10709 } 10710 } 10711 } 10712 if(obj.type === asn1.Type.INTEGER) { 10713 try { 10714 rval += asn1.derToInteger(obj.value); 10715 } catch(ex) { 10716 rval += '0x' + forge.util.bytesToHex(obj.value); 10717 } 10718 } else if(obj.type === asn1.Type.OCTETSTRING) { 10719 if(!_nonLatinRegex.test(obj.value)) { 10720 rval += '(' + obj.value + ') '; 10721 } 10722 rval += '0x' + forge.util.bytesToHex(obj.value); 10723 } else if(obj.type === asn1.Type.UTF8) { 10724 rval += forge.util.decodeUtf8(obj.value); 10725 } else if(obj.type === asn1.Type.PRINTABLESTRING || 10726 obj.type === asn1.Type.IA5String) { 10727 rval += obj.value; 10728 } else if(_nonLatinRegex.test(obj.value)) { 10729 rval += '0x' + forge.util.bytesToHex(obj.value); 10730 } else if(obj.value.length === 0) { 10731 rval += '[null]'; 10732 } else { 10733 rval += obj.value; 10734 } 10735 } 10736 10737 return rval; 10738}; 10739 10740} // end module implementation 10741 10742/* ########## Begin module wrapper ########## */ 10743var name = 'asn1'; 10744if(typeof define !== 'function') { 10745 // NodeJS -> AMD 10746 if(typeof module === 'object' && module.exports) { 10747 var nodeJS = true; 10748 define = function(ids, factory) { 10749 factory(require, module); 10750 }; 10751 } else { 10752 // <script> 10753 if(typeof forge === 'undefined') { 10754 forge = {}; 10755 } 10756 return initModule(forge); 10757 } 10758} 10759// AMD 10760var deps; 10761var defineFunc = function(require, module) { 10762 module.exports = function(forge) { 10763 var mods = deps.map(function(dep) { 10764 return require(dep); 10765 }).concat(initModule); 10766 // handle circular dependencies 10767 forge = forge || {}; 10768 forge.defined = forge.defined || {}; 10769 if(forge.defined[name]) { 10770 return forge[name]; 10771 } 10772 forge.defined[name] = true; 10773 for(var i = 0; i < mods.length; ++i) { 10774 mods[i](forge); 10775 } 10776 return forge[name]; 10777 }; 10778}; 10779var tmpDefine = define; 10780define = function(ids, factory) { 10781 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 10782 if(nodeJS) { 10783 delete define; 10784 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 10785 } 10786 define = tmpDefine; 10787 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 10788}; 10789define(['require', 'module', './util', './oids'], function() { 10790 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 10791}); 10792})(); 10793 10794/** 10795 * Javascript implementation of basic PEM (Privacy Enhanced Mail) algorithms. 10796 * 10797 * See: RFC 1421. 10798 * 10799 * @author Dave Longley 10800 * 10801 * Copyright (c) 2013-2014 Digital Bazaar, Inc. 10802 * 10803 * A Forge PEM object has the following fields: 10804 * 10805 * type: identifies the type of message (eg: "RSA PRIVATE KEY"). 10806 * 10807 * procType: identifies the type of processing performed on the message, 10808 * it has two subfields: version and type, eg: 4,ENCRYPTED. 10809 * 10810 * contentDomain: identifies the type of content in the message, typically 10811 * only uses the value: "RFC822". 10812 * 10813 * dekInfo: identifies the message encryption algorithm and mode and includes 10814 * any parameters for the algorithm, it has two subfields: algorithm and 10815 * parameters, eg: DES-CBC,F8143EDE5960C597. 10816 * 10817 * headers: contains all other PEM encapsulated headers -- where order is 10818 * significant (for pairing data like recipient ID + key info). 10819 * 10820 * body: the binary-encoded body. 10821 */ 10822(function() { 10823/* ########## Begin module implementation ########## */ 10824function initModule(forge) { 10825 10826// shortcut for pem API 10827var pem = forge.pem = forge.pem || {}; 10828 10829/** 10830 * Encodes (serializes) the given PEM object. 10831 * 10832 * @param msg the PEM message object to encode. 10833 * @param options the options to use: 10834 * maxline the maximum characters per line for the body, (default: 64). 10835 * 10836 * @return the PEM-formatted string. 10837 */ 10838pem.encode = function(msg, options) { 10839 options = options || {}; 10840 var rval = '-----BEGIN ' + msg.type + '-----\r\n'; 10841 10842 // encode special headers 10843 var header; 10844 if(msg.procType) { 10845 header = { 10846 name: 'Proc-Type', 10847 values: [String(msg.procType.version), msg.procType.type] 10848 }; 10849 rval += foldHeader(header); 10850 } 10851 if(msg.contentDomain) { 10852 header = {name: 'Content-Domain', values: [msg.contentDomain]}; 10853 rval += foldHeader(header); 10854 } 10855 if(msg.dekInfo) { 10856 header = {name: 'DEK-Info', values: [msg.dekInfo.algorithm]}; 10857 if(msg.dekInfo.parameters) { 10858 header.values.push(msg.dekInfo.parameters); 10859 } 10860 rval += foldHeader(header); 10861 } 10862 10863 if(msg.headers) { 10864 // encode all other headers 10865 for(var i = 0; i < msg.headers.length; ++i) { 10866 rval += foldHeader(msg.headers[i]); 10867 } 10868 } 10869 10870 // terminate header 10871 if(msg.procType) { 10872 rval += '\r\n'; 10873 } 10874 10875 // add body 10876 rval += forge.util.encode64(msg.body, options.maxline || 64) + '\r\n'; 10877 10878 rval += '-----END ' + msg.type + '-----\r\n'; 10879 return rval; 10880}; 10881 10882/** 10883 * Decodes (deserializes) all PEM messages found in the given string. 10884 * 10885 * @param str the PEM-formatted string to decode. 10886 * 10887 * @return the PEM message objects in an array.
10888 */ 10889pem.decode = function(str) { 10890 var rval = []; 10891 10892 // split string into PEM messages (be lenient w/EOF on BEGIN line) 10893 var rMessage = /\s*-----BEGIN ([A-Z0-9- ]+)-----\r?\n?([\x21-\x7e\s]+?(?:\r?\n\r?\n))?([:A-Za-z0-9+\/=\s]+?)-----END \1-----/g; 10894 var rHeader = /([\x21-\x7e]+):\s*([\x21-\x7e\s^:]+)/; 10895 var rCRLF = /\r?\n/; 10896 var match; 10897 while(true) { 10898 match = rMessage.exec(str); 10899 if(!match) { 10900 break; 10901 } 10902 10903 var msg = { 10904 type: match[1], 10905 procType: null, 10906 contentDomain: null, 10907 dekInfo: null, 10908 headers: [], 10909 body: forge.util.decode64(match[3]) 10910 }; 10911 rval.push(msg); 10912 10913 // no headers 10914 if(!match[2]) { 10915 continue; 10916 } 10917 10918 // parse headers 10919 var lines = match[2].split(rCRLF); 10920 var li = 0; 10921 while(match && li < lines.length) { 10922 // get line, trim any rhs whitespace 10923 var line = lines[li].replace(/\s+$/, ''); 10924 10925 // RFC2822 unfold any following folded lines 10926 for(var nl = li + 1; nl < lines.length; ++nl) { 10927 var next = lines[nl]; 10928 if(!/\s/.test(next[0])) { 10929 break; 10930 } 10931 line += next; 10932 li = nl; 10933 } 10934 10935 // parse header 10936 match = line.match(rHeader); 10937 if(match) { 10938 var header = {name: match[1], values: []}; 10939 var values = match[2].split(','); 10940 for(var vi = 0; vi < values.length; ++vi) { 10941 header.values.push(ltrim(values[vi])); 10942 } 10943 10944 // Proc-Type must be the first header 10945 if(!msg.procType) { 10946 if(header.name !== 'Proc-Type') { 10947 throw new Error('Invalid PEM formatted message. The first ' + 10948 'encapsulated header must be "Proc-Type".'); 10949 } else if(header.values.length !== 2) { 10950 throw new Error('Invalid PEM formatted message. The "Proc-Type" ' + 10951 'header must have two subfields.'); 10952 } 10953 msg.procType = {version: values[0], type: values[1]}; 10954 } else if(!msg.contentDomain && header.name === 'Content-Domain') { 10955 // special-case Content-Domain 10956 msg.contentDomain = values[0] || ''; 10957 } else if(!msg.dekInfo && header.name === 'DEK-Info') { 10958 // special-case DEK-Info 10959 if(header.values.length === 0) { 10960 throw new Error('Invalid PEM formatted message. The "DEK-Info" ' + 10961 'header must have at least one subfield.'); 10962 } 10963 msg.dekInfo = {algorithm: values[0], parameters: values[1] || null}; 10964 } else { 10965 msg.headers.push(header); 10966 } 10967 } 10968 10969 ++li; 10970 } 10971 10972 if(msg.procType === 'ENCRYPTED' && !msg.dekInfo) { 10973 throw new Error('Invalid PEM formatted message. The "DEK-Info" ' + 10974 'header must be present if "Proc-Type" is "ENCRYPTED".'); 10975 } 10976 } 10977 10978 if(rval.length === 0) { 10979 throw new Error('Invalid PEM formatted message.'); 10980 } 10981 10982 return rval; 10983}; 10984 10985function foldHeader(header) { 10986 var rval = header.name + ': '; 10987 10988 // ensure values with CRLF are folded 10989 var values = []; 10990 var insertSpace = function(match, $1) { 10991 return ' ' + $1; 10992 }; 10993 for(var i = 0; i < header.values.length; ++i) { 10994 values.push(header.values[i].replace(/^(\S+\r\n)/, insertSpace)); 10995 } 10996 rval += values.join(',') + '\r\n'; 10997 10998 // do folding 10999 var length = 0; 11000 var candidate = -1; 11001 for(var i = 0; i < rval.length; ++i, ++length) { 11002 if(length > 65 && candidate !== -1) { 11003 var insert = rval[candidate]; 11004 if(insert === ',') { 11005 ++candidate; 11006 rval = rval.substr(0, candidate) + '\r\n ' + rval.substr(candidate); 11007 } else { 11008 rval = rval.substr(0, candidate) + 11009 '\r\n' + insert + rval.substr(candidate + 1); 11010 } 11011 length = (i - candidate - 1); 11012 candidate = -1; 11013 ++i; 11014 } else if(rval[i] === ' ' || rval[i] === '\t' || rval[i] === ',') { 11015 candidate = i; 11016 } 11017 } 11018 11019 return rval; 11020} 11021 11022function ltrim(str) { 11023 return str.replace(/^\s+/, ''); 11024} 11025 11026} // end module implementation 11027 11028/* ########## Begin module wrapper ########## */ 11029var name = 'pem'; 11030if(typeof define !== 'function') { 11031 // NodeJS -> AMD 11032 if(typeof module === 'object' && module.exports) { 11033 var nodeJS = true; 11034 define = function(ids, factory) { 11035 factory(require, module); 11036 }; 11037 } else { 11038 // <script> 11039 if(typeof forge === 'undefined') { 11040 forge = {}; 11041 } 11042 return initModule(forge); 11043 } 11044} 11045// AMD 11046var deps;
11047var defineFunc = function(require, module) { 11048 module.exports = function(forge) { 11049 var mods = deps.map(function(dep) { 11050 return require(dep); 11051 }).concat(initModule); 11052 // handle circular dependencies 11053 forge = forge || {}; 11054 forge.defined = forge.defined || {}; 11055 if(forge.defined[name]) { 11056 return forge[name]; 11057 } 11058 forge.defined[name] = true; 11059 for(var i = 0; i < mods.length; ++i) { 11060 mods[i](forge); 11061 } 11062 return forge[name]; 11063 }; 11064}; 11065var tmpDefine = define; 11066define = function(ids, factory) { 11067 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 11068 if(nodeJS) { 11069 delete define; 11070 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 11071 } 11072 define = tmpDefine; 11073 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 11074}; 11075define(['require', 'module', './util'], function() { 11076 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 11077}); 11078})(); 11079 11080/** 11081 * Javascript implementation of basic RSA algorithms. 11082 * 11083 * @author Dave Longley 11084 * 11085 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 11086 * 11087 * The only algorithm currently supported for PKI is RSA. 11088 * 11089 * An RSA key is often stored in ASN.1 DER format. The SubjectPublicKeyInfo 11090 * ASN.1 structure is composed of an algorithm of type AlgorithmIdentifier 11091 * and a subjectPublicKey of type bit string. 11092 * 11093 * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters 11094 * for the algorithm, if any. In the case of RSA, there aren't any. 11095 * 11096 * SubjectPublicKeyInfo ::= SEQUENCE { 11097 * algorithm AlgorithmIdentifier, 11098 * subjectPublicKey BIT STRING 11099 * } 11100 * 11101 * AlgorithmIdentifer ::= SEQUENCE { 11102 * algorithm OBJECT IDENTIFIER, 11103 * parameters ANY DEFINED BY algorithm OPTIONAL 11104 * } 11105 * 11106 * For an RSA public key, the subjectPublicKey is: 11107 * 11108 * RSAPublicKey ::= SEQUENCE { 11109 * modulus INTEGER, -- n 11110 * publicExponent INTEGER -- e 11111 * } 11112 * 11113 * PrivateKeyInfo ::= SEQUENCE { 11114 * version Version, 11115 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, 11116 * privateKey PrivateKey, 11117 * attributes [0] IMPLICIT Attributes OPTIONAL 11118 * } 11119 * 11120 * Version ::= INTEGER 11121 * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier 11122 * PrivateKey ::= OCTET STRING 11123 * Attributes ::= SET OF Attribute 11124 * 11125 * An RSA private key as the following structure: 11126 * 11127 * RSAPrivateKey ::= SEQUENCE { 11128 * version Version, 11129 * modulus INTEGER, -- n 11130 * publicExponent INTEGER, -- e 11131 * privateExponent INTEGER, -- d 11132 * prime1 INTEGER, -- p 11133 * prime2 INTEGER, -- q 11134 * exponent1 INTEGER, -- d mod (p-1) 11135 * exponent2 INTEGER, -- d mod (q-1) 11136 * coefficient INTEGER -- (inverse of q) mod p 11137 * } 11138 * 11139 * Version ::= INTEGER 11140 * 11141 * The OID for the RSA key algorithm is: 1.2.840.113549.1.1.1 11142 */ 11143(function() { 11144function initModule(forge) { 11145/* ########## Begin module implementation ########## */ 11146 11147if(typeof BigInteger === 'undefined') { 11148 var BigInteger = forge.jsbn.BigInteger; 11149} 11150 11151// shortcut for asn.1 API 11152var asn1 = forge.asn1; 11153 11154/* 11155 * RSA encryption and decryption, see RFC 2313. 11156 */ 11157forge.pki = forge.pki || {}; 11158forge.pki.rsa = forge.rsa = forge.rsa || {}; 11159var pki = forge.pki; 11160 11161// for finding primes, which are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29 11162var GCD_30_DELTA = [6, 4, 2, 4, 2, 4, 6, 2]; 11163 11164// validator for a PrivateKeyInfo structure 11165var privateKeyValidator = { 11166 // PrivateKeyInfo 11167 name: 'PrivateKeyInfo', 11168 tagClass: asn1.Class.UNIVERSAL, 11169 type: asn1.Type.SEQUENCE, 11170 constructed: true, 11171 value: [{ 11172 // Version (INTEGER) 11173 name: 'PrivateKeyInfo.version', 11174 tagClass: asn1.Class.UNIVERSAL, 11175 type: asn1.Type.INTEGER, 11176 constructed: false, 11177 capture: 'privateKeyVersion' 11178 }, { 11179 // privateKeyAlgorithm 11180 name: 'PrivateKeyInfo.privateKeyAlgorithm', 11181 tagClass: asn1.Class.UNIVERSAL, 11182 type: asn1.Type.SEQUENCE, 11183 constructed: true, 11184 value: [{ 11185 name: 'AlgorithmIdentifier.algorithm', 11186 tagClass: asn1.Class.UNIVERSAL, 11187 type: asn1.Type.OID, 11188 constructed: false, 11189 capture: 'privateKeyOid' 11190 }] 11191 }, { 11192 // PrivateKey 11193 name: 'PrivateKeyInfo', 11194 tagClass: asn1.Class.UNIVERSAL, 11195 type: asn1.Type.OCTETSTRING, 11196 constructed: false, 11197 capture: 'privateKey' 11198 }] 11199}; 11200 11201// validator for an RSA private key 11202var rsaPrivateKeyValidator = { 11203 // RSAPrivateKey 11204 name: 'RSAPrivateKey', 11205 tagClass: asn1.Class.UNIVERSAL, 11206 type: asn1.Type.SEQUENCE, 11207 constructed: true, 11208 value: [{ 11209 // Version (INTEGER) 11210 name: 'RSAPrivateKey.version', 11211 tagClass: asn1.Class.UNIVERSAL, 11212 type: asn1.Type.INTEGER, 11213 constructed: false, 11214 capture: 'privateKeyVersion' 11215 }, { 11216 // modulus (n) 11217 name: 'RSAPrivateKey.modulus', 11218 tagClass: asn1.Class.UNIVERSAL, 11219 type: asn1.Type.INTEGER, 11220 constructed: false, 11221 capture: 'privateKeyModulus' 11222 }, { 11223 // publicExponent (e) 11224 name: 'RSAPrivateKey.publicExponent', 11225 tagClass: asn1.Class.UNIVERSAL, 11226 type: asn1.Type.INTEGER, 11227 constructed: false, 11228 capture: 'privateKeyPublicExponent' 11229 }, { 11230 // privateExponent (d) 11231 name: 'RSAPrivateKey.privateExponent', 11232 tagClass: asn1.Class.UNIVERSAL, 11233 type: asn1.Type.INTEGER, 11234 constructed: false, 11235 capture: 'privateKeyPrivateExponent' 11236 }, { 11237 // prime1 (p) 11238 name: 'RSAPrivateKey.prime1', 11239 tagClass: asn1.Class.UNIVERSAL, 11240 type: asn1.Type.INTEGER, 11241 constructed: false, 11242 capture: 'privateKeyPrime1' 11243 }, { 11244 // prime2 (q) 11245 name: 'RSAPrivateKey.prime2', 11246 tagClass: asn1.Class.UNIVERSAL, 11247 type: asn1.Type.INTEGER, 11248 constructed: false, 11249 capture: 'privateKeyPrime2' 11250 }, { 11251 // exponent1 (d mod (p-1)) 11252 name: 'RSAPrivateKey.exponent1', 11253 tagClass: asn1.Class.UNIVERSAL, 11254 type: asn1.Type.INTEGER, 11255 constructed: false, 11256 capture: 'privateKeyExponent1' 11257 }, { 11258 // exponent2 (d mod (q-1)) 11259 name: 'RSAPrivateKey.exponent2', 11260 tagClass: asn1.Class.UNIVERSAL, 11261 type: asn1.Type.INTEGER, 11262 constructed: false, 11263 capture: 'privateKeyExponent2' 11264 }, { 11265 // coefficient ((inverse of q) mod p) 11266 name: 'RSAPrivateKey.coefficient', 11267 tagClass: asn1.Class.UNIVERSAL, 11268 type: asn1.Type.INTEGER, 11269 constructed: false, 11270 capture: 'privateKeyCoefficient' 11271 }] 11272}; 11273 11274// validator for an RSA public key 11275var rsaPublicKeyValidator = { 11276 // RSAPublicKey 11277 name: 'RSAPublicKey', 11278 tagClass: asn1.Class.UNIVERSAL, 11279 type: asn1.Type.SEQUENCE, 11280 constructed: true, 11281 value: [{ 11282 // modulus (n) 11283 name: 'RSAPublicKey.modulus', 11284 tagClass: asn1.Class.UNIVERSAL, 11285 type: asn1.Type.INTEGER, 11286 constructed: false, 11287 capture: 'publicKeyModulus' 11288 }, { 11289 // publicExponent (e) 11290 name: 'RSAPublicKey.exponent', 11291 tagClass: asn1.Class.UNIVERSAL, 11292 type: asn1.Type.INTEGER, 11293 constructed: false, 11294 capture: 'publicKeyExponent' 11295 }] 11296}; 11297 11298// validator for an SubjectPublicKeyInfo structure
11299// Note: Currently only works with an RSA public key 11300var publicKeyValidator = forge.pki.rsa.publicKeyValidator = { 11301 name: 'SubjectPublicKeyInfo', 11302 tagClass: asn1.Class.UNIVERSAL, 11303 type: asn1.Type.SEQUENCE, 11304 constructed: true, 11305 captureAsn1: 'subjectPublicKeyInfo', 11306 value: [{ 11307 name: 'SubjectPublicKeyInfo.AlgorithmIdentifier', 11308 tagClass: asn1.Class.UNIVERSAL, 11309 type: asn1.Type.SEQUENCE, 11310 constructed: true, 11311 value: [{ 11312 name: 'AlgorithmIdentifier.algorithm', 11313 tagClass: asn1.Class.UNIVERSAL, 11314 type: asn1.Type.OID, 11315 constructed: false, 11316 capture: 'publicKeyOid' 11317 }] 11318 }, { 11319 // subjectPublicKey 11320 name: 'SubjectPublicKeyInfo.subjectPublicKey', 11321 tagClass: asn1.Class.UNIVERSAL, 11322 type: asn1.Type.BITSTRING, 11323 constructed: false, 11324 value: [{ 11325 // RSAPublicKey 11326 name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey', 11327 tagClass: asn1.Class.UNIVERSAL, 11328 type: asn1.Type.SEQUENCE, 11329 constructed: true, 11330 optional: true, 11331 captureAsn1: 'rsaPublicKey' 11332 }] 11333 }] 11334}; 11335 11336/** 11337 * Wrap digest in DigestInfo object. 11338 * 11339 * This function implements EMSA-PKCS1-v1_5-ENCODE as per RFC 3447. 11340 * 11341 * DigestInfo ::= SEQUENCE { 11342 * digestAlgorithm DigestAlgorithmIdentifier, 11343 * digest Digest 11344 * } 11345 * 11346 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 11347 * Digest ::= OCTET STRING 11348 * 11349 * @param md the message digest object with the hash to sign. 11350 * 11351 * @return the encoded message (ready for RSA encrytion) 11352 */ 11353var emsaPkcs1v15encode = function(md) { 11354 // get the oid for the algorithm 11355 var oid; 11356 if(md.algorithm in pki.oids) { 11357 oid = pki.oids[md.algorithm]; 11358 } else { 11359 var error = new Error('Unknown message digest algorithm.'); 11360 error.algorithm = md.algorithm; 11361 throw error; 11362 } 11363 var oidBytes = asn1.oidToDer(oid).getBytes(); 11364 11365 // create the digest info 11366 var digestInfo = asn1.create( 11367 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 11368 var digestAlgorithm = asn1.create( 11369 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 11370 digestAlgorithm.value.push(asn1.create( 11371 asn1.Class.UNIVERSAL, asn1.Type.OID, false, oidBytes)); 11372 digestAlgorithm.value.push(asn1.create( 11373 asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '')); 11374 var digest = asn1.create( 11375 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, 11376 false, md.digest().getBytes()); 11377 digestInfo.value.push(digestAlgorithm); 11378 digestInfo.value.push(digest); 11379 11380 // encode digest info 11381 return asn1.toDer(digestInfo).getBytes(); 11382}; 11383 11384/** 11385 * Performs x^c mod n (RSA encryption or decryption operation). 11386 * 11387 * @param x the number to raise and mod. 11388 * @param key the key to use. 11389 * @param pub true if the key is public, false if private. 11390 * 11391 * @return the result of x^c mod n. 11392 */ 11393var _modPow = function(x, key, pub) { 11394 if(pub) { 11395 return x.modPow(key.e, key.n); 11396 } 11397 11398 if(!key.p || !key.q) { 11399 // allow calculation without CRT params (slow) 11400 return x.modPow(key.d, key.n); 11401 } 11402 11403 // pre-compute dP, dQ, and qInv if necessary 11404 if(!key.dP) { 11405 key.dP = key.d.mod(key.p.subtract(BigInteger.ONE)); 11406 } 11407 if(!key.dQ) { 11408 key.dQ = key.d.mod(key.q.subtract(BigInteger.ONE)); 11409 } 11410 if(!key.qInv) { 11411 key.qInv = key.q.modInverse(key.p); 11412 } 11413 11414 /* Chinese remainder theorem (CRT) states: 11415 11416 Suppose n1, n2, ..., nk are positive integers which are pairwise 11417 coprime (n1 and n2 have no common factors other than 1). For any 11418 integers x1, x2, ..., xk there exists an integer x solving the 11419 system of simultaneous congruences (where ~= means modularly 11420 congruent so a ~= b mod n means a mod n = b mod n): 11421 11422 x ~= x1 mod n1 11423 x ~= x2 mod n2 11424 ... 11425 x ~= xk mod nk 11426 11427 This system of congruences has a single simultaneous solution x 11428 between 0 and n - 1. Furthermore, each xk solution and x itself 11429 is congruent modulo the product n = n1*n2*...*nk. 11430 So x1 mod n = x2 mod n = xk mod n = x mod n. 11431 11432 The single simultaneous solution x can be solved with the following 11433 equation: 11434 11435 x = sum(xi*ri*si) mod n where ri = n/ni and si = ri^-1 mod ni. 11436 11437 Where x is less than n, xi = x mod ni. 11438 11439 For RSA we are only concerned with k = 2. The modulus n = pq, where 11440 p and q are coprime. The RSA decryption algorithm is: 11441 11442 y = x^d mod n 11443 11444 Given the above: 11445 11446 x1 = x^d mod p 11447 r1 = n/p = q 11448 s1 = q^-1 mod p 11449 x2 = x^d mod q 11450 r2 = n/q = p 11451 s2 = p^-1 mod q 11452 11453 So y = (x1r1s1 + x2r2s2) mod n 11454 = ((x^d mod p)q(q^-1 mod p) + (x^d mod q)p(p^-1 mod q)) mod n 11455 11456 According to Fermat's Little Theorem, if the modulus P is prime, 11457 for any integer A not evenly divisible by P, A^(P-1) ~= 1 mod P. 11458 Since A is not divisible by P it follows that if: 11459 N ~= M mod (P - 1), then A^N mod P = A^M mod P. Therefore: 11460 11461 A^N mod P = A^(M mod (P - 1)) mod P. (The latter takes less effort 11462 to calculate). In order to calculate x^d mod p more quickly the 11463 exponent d mod (p - 1) is stored in the RSA private key (the same 11464 is done for x^d mod q). These values are referred to as dP and dQ 11465 respectively. Therefore we now have: 11466 11467 y = ((x^dP mod p)q(q^-1 mod p) + (x^dQ mod q)p(p^-1 mod q)) mod n 11468 11469 Since we'll be reducing x^dP by modulo p (same for q) we can also 11470 reduce x by p (and q respectively) before hand. Therefore, let 11471 11472 xp = ((x mod p)^dP mod p), and 11473 xq = ((x mod q)^dQ mod q), yielding: 11474 11475 y = (xp*q*(q^-1 mod p) + xq*p*(p^-1 mod q)) mod n 11476 11477 This can be further reduced to a simple algorithm that only 11478 requires 1 inverse (the q inverse is used) to be used and stored. 11479 The algorithm is called Garner's algorithm. If qInv is the 11480 inverse of q, we simply calculate: 11481 11482 y = (qInv*(xp - xq) mod p) * q + xq 11483 11484 However, there are two further complications. First, we need to 11485 ensure that xp > xq to prevent signed BigIntegers from being used 11486 so we add p until this is true (since we will be mod'ing with 11487 p anyway). Then, there is a known timing attack on algorithms 11488 using the CRT. To mitigate this risk, "cryptographic blinding" 11489 should be used. This requires simply generating a random number r 11490 between 0 and n-1 and its inverse and multiplying x by r^e before 11491 calculating y and then multiplying y by r^-1 afterwards. Note that 11492 r must be coprime with n (gcd(r, n) === 1) in order to have an 11493 inverse. 11494 */ 11495 11496 // cryptographic blinding 11497 var r; 11498 do { 11499 r = new BigInteger( 11500 forge.util.bytesToHex(forge.random.getBytes(key.n.bitLength() / 8)), 11501 16); 11502 } while(r.compareTo(key.n) >= 0 || !r.gcd(key.n).equals(BigInteger.ONE)); 11503 x = x.multiply(r.modPow(key.e, key.n)).mod(key.n); 11504 11505 // calculate xp and xq 11506 var xp = x.mod(key.p).modPow(key.dP, key.p);
11507 var xq = x.mod(key.q).modPow(key.dQ, key.q); 11508 11509 // xp must be larger than xq to avoid signed bit usage 11510 while(xp.compareTo(xq) < 0) { 11511 xp = xp.add(key.p); 11512 } 11513 11514 // do last step 11515 var y = xp.subtract(xq) 11516 .multiply(key.qInv).mod(key.p) 11517 .multiply(key.q).add(xq); 11518 11519 // remove effect of random for cryptographic blinding 11520 y = y.multiply(r.modInverse(key.n)).mod(key.n); 11521 11522 return y; 11523}; 11524 11525/** 11526 * NOTE: THIS METHOD IS DEPRECATED, use 'sign' on a private key object or 11527 * 'encrypt' on a public key object instead. 11528 * 11529 * Performs RSA encryption. 11530 * 11531 * The parameter bt controls whether to put padding bytes before the 11532 * message passed in. Set bt to either true or false to disable padding 11533 * completely (in order to handle e.g. EMSA-PSS encoding seperately before), 11534 * signaling whether the encryption operation is a public key operation 11535 * (i.e. encrypting data) or not, i.e. private key operation (data signing). 11536 * 11537 * For PKCS#1 v1.5 padding pass in the block type to use, i.e. either 0x01 11538 * (for signing) or 0x02 (for encryption). The key operation mode (private 11539 * or public) is derived from this flag in that case). 11540 * 11541 * @param m the message to encrypt as a byte string. 11542 * @param key the RSA key to use. 11543 * @param bt for PKCS#1 v1.5 padding, the block type to use 11544 * (0x01 for private key, 0x02 for public), 11545 * to disable padding: true = public key, false = private key. 11546 * 11547 * @return the encrypted bytes as a string. 11548 */ 11549pki.rsa.encrypt = function(m, key, bt) { 11550 var pub = bt; 11551 var eb; 11552 11553 // get the length of the modulus in bytes 11554 var k = Math.ceil(key.n.bitLength() / 8); 11555 11556 if(bt !== false && bt !== true) { 11557 // legacy, default to PKCS#1 v1.5 padding 11558 pub = (bt === 0x02); 11559 eb = _encodePkcs1_v1_5(m, key, bt); 11560 } else { 11561 eb = forge.util.createBuffer(); 11562 eb.putBytes(m); 11563 } 11564 11565 // load encryption block as big integer 'x' 11566 // FIXME: hex conversion inefficient, get BigInteger w/byte strings 11567 var x = new BigInteger(eb.toHex(), 16); 11568 11569 // do RSA encryption 11570 var y = _modPow(x, key, pub); 11571 11572 // convert y into the encrypted data byte string, if y is shorter in 11573 // bytes than k, then prepend zero bytes to fill up ed 11574 // FIXME: hex conversion inefficient, get BigInteger w/byte strings 11575 var yhex = y.toString(16); 11576 var ed = forge.util.createBuffer(); 11577 var zeros = k - Math.ceil(yhex.length / 2); 11578 while(zeros > 0) { 11579 ed.putByte(0x00); 11580 --zeros; 11581 } 11582 ed.putBytes(forge.util.hexToBytes(yhex)); 11583 return ed.getBytes(); 11584}; 11585 11586/** 11587 * NOTE: THIS METHOD IS DEPRECATED, use 'decrypt' on a private key object or 11588 * 'verify' on a public key object instead. 11589 * 11590 * Performs RSA decryption. 11591 * 11592 * The parameter ml controls whether to apply PKCS#1 v1.5 padding 11593 * or not. Set ml = false to disable padding removal completely 11594 * (in order to handle e.g. EMSA-PSS later on) and simply pass back 11595 * the RSA encryption block. 11596 * 11597 * @param ed the encrypted data to decrypt in as a byte string. 11598 * @param key the RSA key to use. 11599 * @param pub true for a public key operation, false for private. 11600 * @param ml the message length, if known, false to disable padding. 11601 * 11602 * @return the decrypted message as a byte string. 11603 */ 11604pki.rsa.decrypt = function(ed, key, pub, ml) { 11605 // get the length of the modulus in bytes 11606 var k = Math.ceil(key.n.bitLength() / 8); 11607 11608 // error if the length of the encrypted data ED is not k 11609 if(ed.length !== k) { 11610 var error = new Error('Encrypted message length is invalid.'); 11611 error.length = ed.length; 11612 error.expected = k; 11613 throw error; 11614 } 11615 11616 // convert encrypted data into a big integer 11617 // FIXME: hex conversion inefficient, get BigInteger w/byte strings 11618 var y = new BigInteger(forge.util.createBuffer(ed).toHex(), 16); 11619 11620 // y must be less than the modulus or it wasn't the result of 11621 // a previous mod operation (encryption) using that modulus 11622 if(y.compareTo(key.n) >= 0) { 11623 throw new Error('Encrypted message is invalid.'); 11624 } 11625 11626 // do RSA decryption 11627 var x = _modPow(y, key, pub); 11628 11629 // create the encryption block, if x is shorter in bytes than k, then 11630 // prepend zero bytes to fill up eb 11631 // FIXME: hex conversion inefficient, get BigInteger w/byte strings 11632 var xhex = x.toString(16); 11633 var eb = forge.util.createBuffer(); 11634 var zeros = k - Math.ceil(xhex.length / 2); 11635 while(zeros > 0) { 11636 eb.putByte(0x00); 11637 --zeros; 11638 } 11639 eb.putBytes(forge.util.hexToBytes(xhex)); 11640 11641 if(ml !== false) { 11642 // legacy, default to PKCS#1 v1.5 padding 11643 return _decodePkcs1_v1_5(eb.getBytes(), key, pub); 11644 } 11645 11646 // return message 11647 return eb.getBytes(); 11648}; 11649 11650/** 11651 * Creates an RSA key-pair generation state object. It is used to allow 11652 * key-generation to be performed in steps. It also allows for a UI to 11653 * display progress updates. 11654 * 11655 * @param bits the size for the private key in bits, defaults to 2048. 11656 * @param e the public exponent to use, defaults to 65537 (0x10001). 11657 * @param [options] the options to use. 11658 * prng a custom crypto-secure pseudo-random number generator to use, 11659 * that must define "getBytesSync". 11660 * algorithm the algorithm to use (default: 'PRIMEINC'). 11661 * 11662 * @return the state object to use to generate the key-pair. 11663 */ 11664pki.rsa.createKeyPairGenerationState = function(bits, e, options) { 11665 // TODO: migrate step-based prime generation code to forge.prime 11666 11667 // set default bits 11668 if(typeof(bits) === 'string') { 11669 bits = parseInt(bits, 10); 11670 } 11671 bits = bits || 2048; 11672 11673 // create prng with api that matches BigInteger secure random 11674 options = options || {}; 11675 var prng = options.prng || forge.random; 11676 var rng = { 11677 // x is an array to fill with bytes 11678 nextBytes: function(x) { 11679 var b = prng.getBytesSync(x.length); 11680 for(var i = 0; i < x.length; ++i) { 11681 x[i] = b.charCodeAt(i); 11682 } 11683 } 11684 }; 11685 11686 var algorithm = options.algorithm || 'PRIMEINC'; 11687 11688 // create PRIMEINC algorithm state 11689 var rval; 11690 if(algorithm === 'PRIMEINC') { 11691 rval = { 11692 algorithm: algorithm, 11693 state: 0, 11694 bits: bits, 11695 rng: rng, 11696 eInt: e || 65537, 11697 e: new BigInteger(null), 11698 p: null, 11699 q: null, 11700 qBits: bits >> 1, 11701 pBits: bits - (bits >> 1), 11702 pqState: 0, 11703 num: null, 11704 keys: null 11705 }; 11706 rval.e.fromInt(rval.eInt); 11707 } else { 11708 throw new Error('Invalid key generation algorithm: ' + algorithm); 11709 } 11710 11711 return rval; 11712}; 11713 11714/** 11715 * Attempts to runs the key-generation algorithm for at most n seconds 11716 * (approximately) using the given state. When key-generation has completed, 11717 * the keys will be stored in state.keys. 11718 * 11719 * To use this function to update a UI while generating a key or to prevent 11720 * causing browser lockups/warnings, set "n" to a value other than 0. A 11721 * simple pattern for generating a key and showing a progress indicator is: 11722 * 11723 * var state = pki.rsa.createKeyPairGenerationState(2048); 11724 * var step = function() { 11725 * // step key-generation, run algorithm for 100 ms, repeat 11726 * if(!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) { 11727 * setTimeout(step, 1); 11728 * } else { 11729 * // key-generation complete 11730 * // TODO: turn off progress indicator here 11731 * // TODO: use the generated key-pair in "state.keys" 11732 * } 11733 * }; 11734 * // TODO: turn on progress indicator here 11735 * setTimeout(step, 0); 11736 * 11737 * @param state the state to use. 11738 * @param n the maximum number of milliseconds to run the algorithm for, 0 11739 * to run the algorithm to completion. 11740 * 11741 * @return true if the key-generation completed, false if not. 11742 */ 11743pki.rsa.stepKeyPairGenerationState = function(state, n) { 11744 // set default algorithm if not set 11745 if(!('algorithm' in state)) { 11746 state.algorithm = 'PRIMEINC'; 11747 } 11748 11749 // TODO: migrate step-based prime generation code to forge.prime 11750 // TODO: abstract as PRIMEINC algorithm 11751
11752 // do key generation (based on Tom Wu's rsa.js, see jsbn.js license) 11753 // with some minor optimizations and designed to run in steps 11754 11755 // local state vars 11756 var THIRTY = new BigInteger(null); 11757 THIRTY.fromInt(30); 11758 var deltaIdx = 0; 11759 var op_or = function(x,y) { return x|y; }; 11760 11761 // keep stepping until time limit is reached or done 11762 var t1 = +new Date(); 11763 var t2; 11764 var total = 0; 11765 while(state.keys === null && (n <= 0 || total < n)) { 11766 // generate p or q 11767 if(state.state === 0) { 11768 /* Note: All primes are of the form: 11769 11770 30k+i, for i < 30 and gcd(30, i)=1, where there are 8 values for i 11771 11772 When we generate a random number, we always align it at 30k + 1. Each 11773 time the number is determined not to be prime we add to get to the 11774 next 'i', eg: if the number was at 30k + 1 we add 6. */ 11775 var bits = (state.p === null) ? state.pBits : state.qBits; 11776 var bits1 = bits - 1; 11777 11778 // get a random number 11779 if(state.pqState === 0) { 11780 state.num = new BigInteger(bits, state.rng); 11781 // force MSB set 11782 if(!state.num.testBit(bits1)) { 11783 state.num.bitwiseTo( 11784 BigInteger.ONE.shiftLeft(bits1), op_or, state.num); 11785 } 11786 // align number on 30k+1 boundary 11787 state.num.dAddOffset(31 - state.num.mod(THIRTY).byteValue(), 0); 11788 deltaIdx = 0; 11789 11790 ++state.pqState; 11791 } else if(state.pqState === 1) { 11792 // try to make the number a prime 11793 if(state.num.bitLength() > bits) { 11794 // overflow, try again 11795 state.pqState = 0; 11796 // do primality test 11797 } else if(state.num.isProbablePrime( 11798 _getMillerRabinTests(state.num.bitLength()))) { 11799 ++state.pqState; 11800 } else { 11801 // get next potential prime 11802 state.num.dAddOffset(GCD_30_DELTA[deltaIdx++ % 8], 0); 11803 } 11804 } else if(state.pqState === 2) { 11805 // ensure number is coprime with e 11806 state.pqState = 11807 (state.num.subtract(BigInteger.ONE).gcd(state.e) 11808 .compareTo(BigInteger.ONE) === 0) ? 3 : 0; 11809 } else if(state.pqState === 3) { 11810 // store p or q 11811 state.pqState = 0; 11812 if(state.p === null) { 11813 state.p = state.num; 11814 } else { 11815 state.q = state.num; 11816 } 11817 11818 // advance state if both p and q are ready 11819 if(state.p !== null && state.q !== null) { 11820 ++state.state; 11821 } 11822 state.num = null; 11823 } 11824 } else if(state.state === 1) { 11825 // ensure p is larger than q (swap them if not) 11826 if(state.p.compareTo(state.q) < 0) { 11827 state.num = state.p; 11828 state.p = state.q; 11829 state.q = state.num; 11830 } 11831 ++state.state; 11832 } else if(state.state === 2) { 11833 // compute phi: (p - 1)(q - 1) (Euler's totient function) 11834 state.p1 = state.p.subtract(BigInteger.ONE); 11835 state.q1 = state.q.subtract(BigInteger.ONE); 11836 state.phi = state.p1.multiply(state.q1); 11837 ++state.state; 11838 } else if(state.state === 3) { 11839 // ensure e and phi are coprime 11840 if(state.phi.gcd(state.e).compareTo(BigInteger.ONE) === 0) { 11841 // phi and e are coprime, advance 11842 ++state.state; 11843 } else { 11844 // phi and e aren't coprime, so generate a new p and q 11845 state.p = null; 11846 state.q = null; 11847 state.state = 0; 11848 } 11849 } else if(state.state === 4) { 11850 // create n, ensure n is has the right number of bits 11851 state.n = state.p.multiply(state.q); 11852 11853 // ensure n is right number of bits 11854 if(state.n.bitLength() === state.bits) { 11855 // success, advance 11856 ++state.state; 11857 } else { 11858 // failed, get new q 11859 state.q = null; 11860 state.state = 0; 11861 } 11862 } else if(state.state === 5) { 11863 // set keys 11864 var d = state.e.modInverse(state.phi); 11865 state.keys = { 11866 privateKey: pki.rsa.setPrivateKey( 11867 state.n, state.e, d, state.p, state.q, 11868 d.mod(state.p1), d.mod(state.q1), 11869 state.q.modInverse(state.p)), 11870 publicKey: pki.rsa.setPublicKey(state.n, state.e) 11871 }; 11872 } 11873 11874 // update timing 11875 t2 = +new Date(); 11876 total += t2 - t1; 11877 t1 = t2; 11878 } 11879 11880 return state.keys !== null; 11881}; 11882 11883/** 11884 * Generates an RSA public-private key pair in a single call. 11885 * 11886 * To generate a key-pair in steps (to allow for progress updates and to 11887 * prevent blocking or warnings in slow browsers) then use the key-pair 11888 * generation state functions. 11889 * 11890 * To generate a key-pair asynchronously (either through web-workers, if 11891 * available, or by breaking up the work on the main thread), pass a 11892 * callback function. 11893 * 11894 * @param [bits] the size for the private key in bits, defaults to 2048. 11895 * @param [e] the public exponent to use, defaults to 65537. 11896 * @param [options] options for key-pair generation, if given then 'bits' 11897 * and 'e' must *not* be given: 11898 * bits the size for the private key in bits, (default: 2048). 11899 * e the public exponent to use, (default: 65537 (0x10001)). 11900 * workerScript the worker script URL. 11901 * workers the number of web workers (if supported) to use, 11902 * (default: 2). 11903 * workLoad the size of the work load, ie: number of possible prime 11904 * numbers for each web worker to check per work assignment, 11905 * (default: 100). 11906 * prng a custom crypto-secure pseudo-random number generator to use, 11907 * that must define "getBytesSync". 11908 * algorithm the algorithm to use (default: 'PRIMEINC'). 11909 * @param [callback(err, keypair)] called once the operation completes. 11910 * 11911 * @return an object with privateKey and publicKey properties. 11912 */ 11913pki.rsa.generateKeyPair = function(bits, e, options, callback) { 11914 // (bits), (options), (callback) 11915 if(arguments.length === 1) { 11916 if(typeof bits === 'object') { 11917 options = bits; 11918 bits = undefined; 11919 } else if(typeof bits === 'function') { 11920 callback = bits; 11921 bits = undefined; 11922 } 11923 } else if(arguments.length === 2) { 11924 // (bits, e), (bits, options), (bits, callback), (options, callback) 11925 if(typeof bits === 'number') { 11926 if(typeof e === 'function') { 11927 callback = e; 11928 e = undefined; 11929 } else if(typeof e !== 'number') { 11930 options = e; 11931 e = undefined; 11932 } 11933 } else { 11934 options = bits; 11935 callback = e; 11936 bits = undefined; 11937 e = undefined; 11938 } 11939 } else if(arguments.length === 3) { 11940 // (bits, e, options), (bits, e, callback), (bits, options, callback) 11941 if(typeof e === 'number') { 11942 if(typeof options === 'function') { 11943 callback = options; 11944 options = undefined; 11945 } 11946 } else { 11947 callback = options; 11948 options = e; 11949 e = undefined; 11950 } 11951 } 11952 options = options || {}; 11953 if(bits === undefined) { 11954 bits = options.bits || 2048; 11955 } 11956 if(e === undefined) { 11957 e = options.e || 0x10001; 11958 } 11959 11960 // if native code is permitted and a callback is given, use native 11961 // key generation code if available and if parameters are acceptable 11962 if(!forge.disableNativeCode && callback && 11963 bits >= 256 && bits <= 16384 && (e === 0x10001 || e === 3)) { 11964 if(_detectSubtleCrypto('generateKey') && _detectSubtleCrypto('export
11964Key')) { 11965 // use standard native generateKey 11966 return window.crypto.subtle.generateKey({ 11967 name: 'RSASSA-PKCS1-v1_5', 11968 modulusLength: bits, 11969 publicExponent: _intToUint8Array(e), 11970 hash: {name: 'SHA-256'} 11971 }, true /* key can be exported*/, ['sign', 'verify']) 11972 .then(function(pair) { 11973 return window.crypto.subtle.exportKey('pkcs8', pair.privateKey); 11974 }).catch(function(err) { 11975 callback(err); 11976 }).then(function(pkcs8) { 11977 if(pkcs8) { 11978 var privateKey = pki.privateKeyFromAsn1( 11979 asn1.fromDer(forge.util.createBuffer(pkcs8))); 11980 callback(null, { 11981 privateKey: privateKey, 11982 publicKey: pki.setRsaPublicKey(privateKey.n, privateKey.e) 11983 }); 11984 } 11985 }); 11986 } 11987 if(_detectSubtleMsCrypto('generateKey') && 11988 _detectSubtleMsCrypto('exportKey')) { 11989 var genOp = window.msCrypto.subtle.generateKey({ 11990 name: 'RSASSA-PKCS1-v1_5', 11991 modulusLength: bits, 11992 publicExponent: _intToUint8Array(e), 11993 hash: {name: 'SHA-256'} 11994 }, true /* key can be exported*/, ['sign', 'verify']); 11995 genOp.oncomplete = function(e) { 11996 var pair = e.target.result; 11997 var exportOp = window.msCrypto.subtle.exportKey( 11998 'pkcs8', pair.privateKey); 11999 exportOp.oncomplete = function(e) { 12000 var pkcs8 = e.target.result; 12001 var privateKey = pki.privateKeyFromAsn1( 12002 asn1.fromDer(forge.util.createBuffer(pkcs8))); 12003 callback(null, { 12004 privateKey: privateKey, 12005 publicKey: pki.setRsaPublicKey(privateKey.n, privateKey.e) 12006 }); 12007 }; 12008 exportOp.onerror = function(err) { 12009 callback(err); 12010 }; 12011 }; 12012 genOp.onerror = function(err) { 12013 callback(err); 12014 }; 12015 return; 12016 } 12017 } 12018 12019 // use JavaScript implementation 12020 var state = pki.rsa.createKeyPairGenerationState(bits, e, options); 12021 if(!callback) { 12022 pki.rsa.stepKeyPairGenerationState(state, 0); 12023 return state.keys; 12024 } 12025 _generateKeyPair(state, options, callback); 12026}; 12027 12028/** 12029 * Sets an RSA public key from BigIntegers modulus and exponent. 12030 * 12031 * @param n the modulus. 12032 * @param e the exponent. 12033 * 12034 * @return the public key. 12035 */ 12036pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) { 12037 var key = { 12038 n: n, 12039 e: e 12040 }; 12041 12042 /** 12043 * Encrypts the given data with this public key. Newer applications 12044 * should use the 'RSA-OAEP' decryption scheme, 'RSAES-PKCS1-V1_5' is for 12045 * legacy applications. 12046 * 12047 * @param data the byte string to encrypt. 12048 * @param scheme the encryption scheme to use: 12049 * 'RSAES-PKCS1-V1_5' (default), 12050 * 'RSA-OAEP', 12051 * 'RAW', 'NONE', or null to perform raw RSA encryption, 12052 * an object with an 'encode' property set to a function 12053 * with the signature 'function(data, key)' that returns 12054 * a binary-encoded string representing the encoded data. 12055 * @param schemeOptions any scheme-specific options. 12056 * 12057 * @return the encrypted byte string. 12058 */ 12059 key.encrypt = function(data, scheme, schemeOptions) { 12060 if(typeof scheme === 'string') { 12061 scheme = scheme.toUpperCase(); 12062 } else if(scheme === undefined) { 12063 scheme = 'RSAES-PKCS1-V1_5'; 12064 } 12065 12066 if(scheme === 'RSAES-PKCS1-V1_5') { 12067 scheme = { 12068 encode: function(m, key, pub) { 12069 return _encodePkcs1_v1_5(m, key, 0x02).getBytes(); 12070 } 12071 }; 12072 } else if(scheme === 'RSA-OAEP' || scheme === 'RSAES-OAEP') { 12073 scheme = { 12074 encode: function(m, key) { 12075 return forge.pkcs1.encode_rsa_oaep(key, m, schemeOptions); 12076 } 12077 }; 12078 } else if(['RAW', 'NONE', 'NULL', null].indexOf(scheme) !== -1) { 12079 scheme = { encode: function(e) { return e; } }; 12080 } else if(typeof scheme === 'string') { 12081 throw new Error('Unsupported encryption scheme: "' + scheme + '".'); 12082 } 12083 12084 // do scheme-based encoding then rsa encryption 12085 var e = scheme.encode(data, key, true); 12086 return pki.rsa.encrypt(e, key, true); 12087 }; 12088 12089 /** 12090 * Verifies the given signature against the given digest. 12091 * 12092 * PKCS#1 supports multiple (currently two) signature schemes: 12093 * RSASSA-PKCS1-V1_5 and RSASSA-PSS. 12094 * 12095 * By default this implementation uses the "old scheme", i.e. 12096 * RSASSA-PKCS1-V1_5, in which case once RSA-decrypted, the 12097 * signature is an OCTET STRING that holds a DigestInfo. 12098 * 12099 * DigestInfo ::= SEQUENCE { 12100 * digestAlgorithm DigestAlgorithmIdentifier, 12101 * digest Digest 12102 * } 12103 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 12104 * Digest ::= OCTET STRING 12105 * 12106 * To perform PSS signature verification, provide an instance 12107 * of Forge PSS object as the scheme parameter. 12108 * 12109 * @param digest the message digest hash to compare against the signature, 12110 * as a binary-encoded string. 12111 * @param signature the signature to verify, as a binary-encoded string. 12112 * @param scheme signature verification scheme to use: 12113 * 'RSASSA-PKCS1-V1_5' or undefined for RSASSA PKCS#1 v1.5, 12114 * a Forge PSS object for RSASSA-PSS,
12115 * 'NONE' or null for none, DigestInfo will not be expected, but 12116 * PKCS#1 v1.5 padding will still be used. 12117 * 12118 * @return true if the signature was verified, false if not. 12119 */ 12120 key.verify = function(digest, signature, scheme) { 12121 if(typeof scheme === 'string') { 12122 scheme = scheme.toUpperCase(); 12123 } else if(scheme === undefined) { 12124 scheme = 'RSASSA-PKCS1-V1_5'; 12125 } 12126 12127 if(scheme === 'RSASSA-PKCS1-V1_5') { 12128 scheme = { 12129 verify: function(digest, d) { 12130 // remove padding 12131 d = _decodePkcs1_v1_5(d, key, true); 12132 // d is ASN.1 BER-encoded DigestInfo 12133 var obj = asn1.fromDer(d); 12134 // compare the given digest to the decrypted one 12135 return digest === obj.value[1].value; 12136 } 12137 }; 12138 } else if(scheme === 'NONE' || scheme === 'NULL' || scheme === null) { 12139 scheme = { 12140 verify: function(digest, d) { 12141 // remove padding 12142 d = _decodePkcs1_v1_5(d, key, true); 12143 return digest === d; 12144 } 12145 }; 12146 } 12147 12148 // do rsa decryption w/o any decoding, then verify -- which does decoding 12149 var d = pki.rsa.decrypt(signature, key, true, false); 12150 return scheme.verify(digest, d, key.n.bitLength()); 12151 }; 12152 12153 return key; 12154}; 12155 12156/** 12157 * Sets an RSA private key from BigIntegers modulus, exponent, primes, 12158 * prime exponents, and modular multiplicative inverse. 12159 * 12160 * @param n the modulus. 12161 * @param e the public exponent. 12162 * @param d the private exponent ((inverse of e) mod n). 12163 * @param p the first prime. 12164 * @param q the second prime. 12165 * @param dP exponent1 (d mod (p-1)). 12166 * @param dQ exponent2 (d mod (q-1)). 12167 * @param qInv ((inverse of q) mod p) 12168 * 12169 * @return the private key. 12170 */ 12171pki.setRsaPrivateKey = pki.rsa.setPrivateKey = function( 12172 n, e, d, p, q, dP, dQ, qInv) { 12173 var key = { 12174 n: n, 12175 e: e, 12176 d: d, 12177 p: p, 12178 q: q, 12179 dP: dP, 12180 dQ: dQ, 12181 qInv: qInv 12182 }; 12183 12184 /** 12185 * Decrypts the given data with this private key. The decryption scheme 12186 * must match the one used to encrypt the data. 12187 * 12188 * @param data the byte string to decrypt. 12189 * @param scheme the decryption scheme to use: 12190 * 'RSAES-PKCS1-V1_5' (default), 12191 * 'RSA-OAEP', 12192 * 'RAW', 'NONE', or null to perform raw RSA decryption. 12193 * @param schemeOptions any scheme-specific options. 12194 * 12195 * @return the decrypted byte string. 12196 */ 12197 key.decrypt = function(data, scheme, schemeOptions) { 12198 if(typeof scheme === 'string') { 12199 scheme = scheme.toUpperCase(); 12200 } else if(scheme === undefined) { 12201 scheme = 'RSAES-PKCS1-V1_5'; 12202 } 12203 12204 // do rsa decryption w/o any decoding 12205 var d = pki.rsa.decrypt(data, key, false, false); 12206 12207 if(scheme === 'RSAES-PKCS1-V1_5') { 12208 scheme = { decode: _decodePkcs1_v1_5 }; 12209 } else if(scheme === 'RSA-OAEP' || scheme === 'RSAES-OAEP') { 12210 scheme = { 12211 decode: function(d, key) { 12212 return forge.pkcs1.decode_rsa_oaep(key, d, schemeOptions); 12213 } 12214 }; 12215 } else if(['RAW', 'NONE', 'NULL', null].indexOf(scheme) !== -1) { 12216 scheme = { decode: function(d) { return d; } }; 12217 } else { 12218 throw new Error('Unsupported encryption scheme: "' + scheme + '".'); 12219 } 12220 12221 // decode according to scheme 12222 return scheme.decode(d, key, false); 12223 }; 12224 12225 /** 12226 * Signs the given digest, producing a signature. 12227 * 12228 * PKCS#1 supports multiple (currently two) signature schemes: 12229 * RSASSA-PKCS1-V1_5 and RSASSA-PSS. 12230 * 12231 * By default this implementation uses the "old scheme", i.e. 12232 * RSASSA-PKCS1-V1_5. In order to generate a PSS signature, provide 12233 * an instance of Forge PSS object as the scheme parameter. 12234 * 12235 * @param md the message digest object with the hash to sign. 12236 * @param scheme the signature scheme to use: 12237 * 'RSASSA-PKCS1-V1_5' or undefined for RSASSA PKCS#1 v1.5, 12238 * a Forge PSS object for RSASSA-PSS, 12239 * 'NONE' or null for none, DigestInfo will not be used but 12240 * PKCS#1 v1.5 padding will still be used. 12241 * 12242 * @return the signature as a byte string. 12243 */ 12244 key.sign = function(md, scheme) { 12245 /* Note: The internal implementation of RSA operations is being 12246 transitioned away from a PKCS#1 v1.5 hard-coded scheme. Some legacy 12247 code like the use of an encoding block identifier 'bt' will eventually 12248 be removed. */ 12249 12250 // private key operation 12251 var bt = false;
12252 12253 if(typeof scheme === 'string') { 12254 scheme = scheme.toUpperCase(); 12255 } 12256 12257 if(scheme === undefined || scheme === 'RSASSA-PKCS1-V1_5') { 12258 scheme = { encode: emsaPkcs1v15encode }; 12259 bt = 0x01; 12260 } else if(scheme === 'NONE' || scheme === 'NULL' || scheme === null) { 12261 scheme = { encode: function() { return md; } }; 12262 bt = 0x01; 12263 } 12264 12265 // encode and then encrypt 12266 var d = scheme.encode(md, key.n.bitLength()); 12267 return pki.rsa.encrypt(d, key, bt); 12268 }; 12269 12270 return key; 12271}; 12272 12273/** 12274 * Wraps an RSAPrivateKey ASN.1 object in an ASN.1 PrivateKeyInfo object. 12275 * 12276 * @param rsaKey the ASN.1 RSAPrivateKey. 12277 * 12278 * @return the ASN.1 PrivateKeyInfo. 12279 */ 12280pki.wrapRsaPrivateKey = function(rsaKey) { 12281 // PrivateKeyInfo 12282 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 12283 // version (0) 12284 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12285 asn1.integerToDer(0).getBytes()), 12286 // privateKeyAlgorithm 12287 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 12288 asn1.create( 12289 asn1.Class.UNIVERSAL, asn1.Type.OID, false, 12290 asn1.oidToDer(pki.oids.rsaEncryption).getBytes()), 12291 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 12292 ]), 12293 // PrivateKey 12294 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 12295 asn1.toDer(rsaKey).getBytes()) 12296 ]); 12297}; 12298 12299/** 12300 * Converts a private key from an ASN.1 object. 12301 * 12302 * @param obj the ASN.1 representation of a PrivateKeyInfo containing an 12303 * RSAPrivateKey or an RSAPrivateKey. 12304 * 12305 * @return the private key. 12306 */ 12307pki.privateKeyFromAsn1 = function(obj) { 12308 // get PrivateKeyInfo 12309 var capture = {}; 12310 var errors = []; 12311 if(asn1.validate(obj, privateKeyValidator, capture, errors)) { 12312 obj = asn1.fromDer(forge.util.createBuffer(capture.privateKey)); 12313 } 12314 12315 // get RSAPrivateKey 12316 capture = {}; 12317 errors = []; 12318 if(!asn1.validate(obj, rsaPrivateKeyValidator, capture, errors)) { 12319 var error = new Error('Cannot read private key. ' + 12320 'ASN.1 object does not contain an RSAPrivateKey.'); 12321 error.errors = errors; 12322 throw error; 12323 } 12324 12325 // Note: Version is currently ignored. 12326 // capture.privateKeyVersion 12327 // FIXME: inefficient, get a BigInteger that uses byte strings 12328 var n, e, d, p, q, dP, dQ, qInv; 12329 n = forge.util.createBuffer(capture.privateKeyModulus).toHex(); 12330 e = forge.util.createBuffer(capture.privateKeyPublicExponent).toHex(); 12331 d = forge.util.createBuffer(capture.privateKeyPrivateExponent).toHex(); 12332 p = forge.util.createBuffer(capture.privateKeyPrime1).toHex(); 12333 q = forge.util.createBuffer(capture.privateKeyPrime2).toHex(); 12334 dP = forge.util.createBuffer(capture.privateKeyExponent1).toHex(); 12335 dQ = forge.util.createBuffer(capture.privateKeyExponent2).toHex(); 12336 qInv = forge.util.createBuffer(capture.privateKeyCoefficient).toHex(); 12337 12338 // set private key 12339 return pki.setRsaPrivateKey( 12340 new BigInteger(n, 16), 12341 new BigInteger(e, 16), 12342 new BigInteger(d, 16), 12343 new BigInteger(p, 16), 12344 new BigInteger(q, 16), 12345 new BigInteger(dP, 16), 12346 new BigInteger(dQ, 16), 12347 new BigInteger(qInv, 16)); 12348}; 12349 12350/** 12351 * Converts a private key to an ASN.1 RSAPrivateKey. 12352 * 12353 * @param key the private key. 12354 * 12355 * @return the ASN.1 representation of an RSAPrivateKey. 12356 */ 12357pki.privateKeyToAsn1 = pki.privateKeyToRSAPrivateKey = function(key) { 12358 // RSAPrivateKey 12359 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 12360 // version (0 = only 2 primes, 1 multiple primes) 12361 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12362 asn1.integerToDer(0).getBytes()), 12363 // modulus (n) 12364 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12365 _bnToBytes(key.n)), 12366 // publicExponent (e) 12367 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12368 _bnToBytes(key.e)), 12369 // privateExponent (d) 12370 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12371 _bnToBytes(key.d)), 12372 // privateKeyPrime1 (p) 12373 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12374 _bnToBytes(key.p)), 12375 // privateKeyPrime2 (q) 12376 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12377 _bnToBytes(key.q)), 12378 // privateKeyExponent1 (dP) 12379 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12380 _bnToBytes(key.dP)), 12381 // privateKeyExponent2 (dQ) 12382 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12383 _bnToBytes(key.dQ)), 12384 // coefficient (qInv) 12385 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12386 _bnToBytes(key.qInv)) 12387 ]); 12388}; 12389 12390/** 12391 * Converts a public key from an ASN.1 SubjectPublicKeyInfo or RSAPublicKey. 12392 * 12393 * @param obj the asn1 representation of a SubjectPublicKeyInfo or RSAPublicKey. 12394 * 12395 * @return the public key. 12396 */ 12397pki.publicKeyFromAsn1 = function(obj) { 12398 // get SubjectPublicKeyInfo 12399 var capture = {}; 12400 var errors = []; 12401 if(asn1.validate(obj, publicKeyValidator, capture, errors)) { 12402 // get oid 12403 var oid = asn1.derToOid(capture.publicKeyOid); 12404 if(oid !== pki.oids.rsaEncryption) { 12405 var error = new Error('Cannot read public key. Unknown OID.'); 12406 error.oid = oid; 12407 throw error; 12408 } 12409 obj = capture.rsaPublicKey; 12410 } 12411 12412 // get RSA params 12413 errors = []; 12414 if(!asn1.validate(obj, rsaPublicKeyValidator, capture, errors)) { 12415 var error = new Error('Cannot read public key. ' + 12416 'ASN.1 object does not contain an RSAPublicKey.'); 12417 error.errors = errors; 12418 throw error; 12419 } 12420 12421 // FIXME: inefficient, get a BigInteger that uses byte strings 12422 var n = forge.util.createBuffer(capture.publicKeyModulus).toHex(); 12423 var e = forge.util.createBuffer(capture.publicKeyExponent).toHex(); 12424 12425 // set public key 12426 return pki.setRsaPublicKey( 12427 new BigInteger(n, 16), 12428 new BigInteger(e, 16)); 12429}; 12430 12431/** 12432 * Converts a public key to an ASN.1 SubjectPublicKeyInfo. 12433 * 12434 * @param key the public key. 12435 * 12436 * @return the asn1 representation of a SubjectPublicKeyInfo. 12437 */ 12438pki.publicKeyToAsn1 = pki.publicKeyToSubjectPublicKeyInfo = function(key) { 12439 // SubjectPublicKeyInfo 12440 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 12441 // AlgorithmIdentifier 12442 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 12443 // algorithm 12444 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 12445 asn1.oidToDer(pki.oids.rsaEncryption).getBytes()), 12446 // parameters (null) 12447 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 12448 ]), 12449 // subjectPublicKey 12450 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, [ 12451 pki.publicKeyToRSAPublicKey(key) 12452 ]) 12453 ]); 12454}; 12455 12456/** 12457 * Converts a public key to an ASN.1 RSAPublicKey. 12458 * 12459 * @param key the public key. 12460 * 12461 * @return the asn1 representation of a RSAPublicKey. 12462 */ 12463pki.publicKeyToRSAPublicKey = function(key) { 12464 // RSAPublicKey 12465 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 12466 // modulus (n) 12467 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false,
12468 _bnToBytes(key.n)), 12469 // publicExponent (e) 12470 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 12471 _bnToBytes(key.e)) 12472 ]); 12473}; 12474 12475/** 12476 * Encodes a message using PKCS#1 v1.5 padding. 12477 * 12478 * @param m the message to encode. 12479 * @param key the RSA key to use. 12480 * @param bt the block type to use, i.e. either 0x01 (for signing) or 0x02 12481 * (for encryption). 12482 * 12483 * @return the padded byte buffer. 12484 */ 12485function _encodePkcs1_v1_5(m, key, bt) { 12486 var eb = forge.util.createBuffer(); 12487 12488 // get the length of the modulus in bytes 12489 var k = Math.ceil(key.n.bitLength() / 8); 12490 12491 /* use PKCS#1 v1.5 padding */ 12492 if(m.length > (k - 11)) { 12493 var error = new Error('Message is too long for PKCS#1 v1.5 padding.'); 12494 error.length = m.length; 12495 error.max = k - 11; 12496 throw error; 12497 } 12498 12499 /* A block type BT, a padding string PS, and the data D shall be 12500 formatted into an octet string EB, the encryption block: 12501 12502 EB = 00 || BT || PS || 00 || D 12503 12504 The block type BT shall be a single octet indicating the structure of 12505 the encryption block. For this version of the document it shall have 12506 value 00, 01, or 02. For a private-key operation, the block type 12507 shall be 00 or 01. For a public-key operation, it shall be 02. 12508 12509 The padding string PS shall consist of k-3-||D|| octets. For block 12510 type 00, the octets shall have value 00; for block type 01, they 12511 shall have value FF; and for block type 02, they shall be 12512 pseudorandomly generated and nonzero. This makes the length of the 12513 encryption block EB equal to k. */ 12514 12515 // build the encryption block 12516 eb.putByte(0x00); 12517 eb.putByte(bt); 12518 12519 // create the padding 12520 var padNum = k - 3 - m.length; 12521 var padByte; 12522 // private key op 12523 if(bt === 0x00 || bt === 0x01) { 12524 padByte = (bt === 0x00) ? 0x00 : 0xFF; 12525 for(var i = 0; i < padNum; ++i) { 12526 eb.putByte(padByte); 12527 } 12528 } else { 12529 // public key op 12530 // pad with random non-zero values 12531 while(padNum > 0) { 12532 var numZeros = 0; 12533 var padBytes = forge.random.getBytes(padNum); 12534 for(var i = 0; i < padNum; ++i) { 12535 padByte = padBytes.charCodeAt(i); 12536 if(padByte === 0) { 12537 ++numZeros; 12538 } else { 12539 eb.putByte(padByte); 12540 } 12541 } 12542 padNum = numZeros; 12543 } 12544 } 12545 12546 // zero followed by message 12547 eb.putByte(0x00); 12548 eb.putBytes(m); 12549 12550 return eb; 12551} 12552 12553/** 12554 * Decodes a message using PKCS#1 v1.5 padding. 12555 * 12556 * @param em the message to decode. 12557 * @param key the RSA key to use. 12558 * @param pub true if the key is a public key, false if it is private. 12559 * @param ml the message length, if specified. 12560 * 12561 * @return the decoded bytes. 12562 */ 12563function _decodePkcs1_v1_5(em, key, pub, ml) { 12564 // get the length of the modulus in bytes 12565 var k = Math.ceil(key.n.bitLength() / 8); 12566 12567 /* It is an error if any of the following conditions occurs: 12568 12569 1. The encryption block EB cannot be parsed unambiguously. 12570 2. The padding string PS consists of fewer than eight octets 12571 or is inconsisent with the block type BT. 12572 3. The decryption process is a public-key operation and the block 12573 type BT is not 00 or 01, or the decryption process is a 12574 private-key operation and the block type is not 02. 12575 */ 12576 12577 // parse the encryption block 12578 var eb = forge.util.createBuffer(em); 12579 var first = eb.getByte(); 12580 var bt = eb.getByte(); 12581 if(first !== 0x00 || 12582 (pub && bt !== 0x00 && bt !== 0x01) || 12583 (!pub && bt != 0x02) || 12584 (pub && bt === 0x00 && typeof(ml) === 'undefined')) { 12585 throw new Error('Encryption block is invalid.'); 12586 } 12587 12588 var padNum = 0; 12589 if(bt === 0x00) { 12590 // check all padding bytes for 0x00 12591 padNum = k - 3 - ml; 12592 for(var i = 0; i < padNum; ++i) { 12593 if(eb.getByte() !== 0x00) { 12594 throw new Error('Encryption block is invalid.'); 12595 } 12596 } 12597 } else if(bt === 0x01) { 12598 // find the first byte that isn't 0xFF, should be after all padding 12599 padNum = 0; 12600 while(eb.length() > 1) { 12601 if(eb.getByte() !== 0xFF) { 12602 --eb.read; 12603 break; 12604 } 12605 ++padNum; 12606 } 12607 } else if(bt === 0x02) { 12608 // look for 0x00 byte 12609 padNum = 0; 12610 while(eb.length() > 1) { 12611 if(eb.getByte() === 0x00) { 12612 --eb.read; 12613 break; 12614 } 12615 ++padNum; 12616 } 12617 } 12618 12619 // zero must be 0x00 and padNum must be (k - 3 - message length) 12620 var zero = eb.getByte(); 12621 if(zero !== 0x00 || padNum !== (k - 3 - eb.length())) {
12622 throw new Error('Encryption block is invalid.'); 12623 } 12624 12625 return eb.getBytes(); 12626} 12627 12628/** 12629 * Runs the key-generation algorithm asynchronously, either in the background 12630 * via Web Workers, or using the main thread and setImmediate. 12631 * 12632 * @param state the key-pair generation state. 12633 * @param [options] options for key-pair generation: 12634 * workerScript the worker script URL. 12635 * workers the number of web workers (if supported) to use, 12636 * (default: 2, -1 to use estimated cores minus one). 12637 * workLoad the size of the work load, ie: number of possible prime 12638 * numbers for each web worker to check per work assignment, 12639 * (default: 100). 12640 * @param callback(err, keypair) called once the operation completes. 12641 */ 12642function _generateKeyPair(state, options, callback) { 12643 if(typeof options === 'function') { 12644 callback = options; 12645 options = {}; 12646 } 12647 options = options || {}; 12648 12649 var opts = { 12650 algorithm: { 12651 name: options.algorithm || 'PRIMEINC', 12652 options: { 12653 workers: options.workers || 2, 12654 workLoad: options.workLoad || 100, 12655 workerScript: options.workerScript 12656 } 12657 } 12658 }; 12659 if('prng' in options) { 12660 opts.prng = options.prng; 12661 } 12662 12663 generate(); 12664 12665 function generate() { 12666 // find p and then q (done in series to simplify) 12667 getPrime(state.pBits, function(err, num) { 12668 if(err) { 12669 return callback(err); 12670 } 12671 state.p = num; 12672 if(state.q !== null) { 12673 return finish(err, state.q); 12674 } 12675 getPrime(state.qBits, finish); 12676 }); 12677 } 12678 12679 function getPrime(bits, callback) { 12680 forge.prime.generateProbablePrime(bits, opts, callback); 12681 } 12682 12683 function finish(err, num) { 12684 if(err) { 12685 return callback(err); 12686 } 12687 12688 // set q 12689 state.q = num; 12690 12691 // ensure p is larger than q (swap them if not) 12692 if(state.p.compareTo(state.q) < 0) { 12693 var tmp = state.p; 12694 state.p = state.q; 12695 state.q = tmp; 12696 } 12697 12698 // ensure p is coprime with e 12699 if(state.p.subtract(BigInteger.ONE).gcd(state.e) 12700 .compareTo(BigInteger.ONE) !== 0) { 12701 state.p = null; 12702 generate(); 12703 return; 12704 } 12705 12706 // ensure q is coprime with e 12707 if(state.q.subtract(BigInteger.ONE).gcd(state.e) 12708 .compareTo(BigInteger.ONE) !== 0) { 12709 state.q = null; 12710 getPrime(state.qBits, finish); 12711 return; 12712 } 12713 12714 // compute phi: (p - 1)(q - 1) (Euler's totient function) 12715 state.p1 = state.p.subtract(BigInteger.ONE); 12716 state.q1 = state.q.subtract(BigInteger.ONE); 12717 state.phi = state.p1.multiply(state.q1); 12718 12719 // ensure e and phi are coprime 12720 if(state.phi.gcd(state.e).compareTo(BigInteger.ONE) !== 0) { 12721 // phi and e aren't coprime, so generate a new p and q 12722 state.p = state.q = null; 12723 generate(); 12724 return; 12725 } 12726 12727 // create n, ensure n is has the right number of bits 12728 state.n = state.p.multiply(state.q); 12729 if(state.n.bitLength() !== state.bits) { 12730 // failed, get new q 12731 state.q = null; 12732 getPrime(state.qBits, finish); 12733 return; 12734 } 12735 12736 // set keys 12737 var d = state.e.modInverse(state.phi); 12738 state.keys = { 12739 privateKey: pki.rsa.setPrivateKey( 12740 state.n, state.e, d, state.p, state.q, 12741 d.mod(state.p1), d.mod(state.q1), 12742 state.q.modInverse(state.p)), 12743 publicKey: pki.rsa.setPublicKey(state.n, state.e) 12744 }; 12745 12746 callback(null, state.keys); 12747 } 12748} 12749 12750/** 12751 * Converts a positive BigInteger into 2's-complement big-endian bytes. 12752 * 12753 * @param b the big integer to convert. 12754 * 12755 * @return the bytes. 12756 */ 12757function _bnToBytes(b) { 12758 // prepend 0x00 if first byte >= 0x80 12759 var hex = b.toString(16); 12760 if(hex[0] >= '8') { 12761 hex = '00' + hex; 12762 } 12763 var bytes = forge.util.hexToBytes(hex); 12764 12765 // ensure integer is minimally-encoded 12766 if(bytes.length > 1 && 12767 // leading 0x00 for positive integer 12768 ((bytes.charCodeAt(0) === 0 && 12769 (bytes.charCodeAt(1) & 0x80) === 0) || 12770 // leading 0xFF for negative integer 12771 (bytes.charCodeAt(0) === 0xFF && 12772 (bytes.charCodeAt(1) & 0x80) === 0x80))) { 12773 return bytes.substr(1); 12774 } 12775 return bytes; 12776} 12777 12778/** 12779 * Returns the required number of Miller-Rabin tests to generate a 12780 * prime with an error probability of (1/2)^80. 12781 * 12782 * See Handbook of Applied Cryptography Chapter 4, Table 4.4. 12783 * 12784 * @param bits the bit size. 12785 * 12786 * @return the required number of iterations. 12787 */ 12788function _getMillerRabinTests(bits) { 12789 if(bits <= 100) return 27; 12790 if(bits <= 150) return 18; 12791 if(bits <= 200) return 15; 12792 if(bits <= 250) return 12; 12793 if(bits <= 300) return 9; 12794 if(bits <= 350) return 8; 12795 if(bits <= 400) return 7; 12796 if(bits <= 500) return 6; 12797 if(bits <= 600) return 5; 12798 if(bits <= 800) return 4; 12799 if(bits <= 1250) return 3; 12800 return 2; 12801} 12802 12803/** 12804 * Performs feature detection on the SubtleCrypto interface. 12805 * 12806 * @param fn the feature (function) to detect. 12807 * 12808 * @return true if detected, false if not. 12809 */ 12810function _detectSubtleCrypto(fn) { 12811 return (typeof window !== 'undefined' && 12812 typeof window.crypto === 'object' && 12813 typeof window.crypto.subtle === 'object' && 12814 typeof window.crypto.subtle[fn] === 'function'); 12815} 12816 12817/** 12818 * Performs feature detection on the deprecated Microsoft Internet Explorer 12819 * outdated SubtleCrypto interface. This function should only be used after 12820 * checking for the modern, standard SubtleCrypto interface. 12821 * 12822 * @param fn the feature (function) to detect. 12823 * 12824 * @return true if detected, false if not. 12825 */ 12826function _detectSubtleMsCrypto(fn) { 12827 return (typeof window !== 'undefined' && 12828 typeof window.msCrypto === 'object' && 12829 typeof window.msCrypto.subtle === 'object' && 12830 typeof window.msCrypto.subtle[fn] === 'function'); 12831} 12832 12833function _intToUint8Array(x) { 12834 var bytes = forge.util.hexToBytes(x.toString(16)); 12835 var buffer = new Uint8Array(bytes.length); 12836 for(var i = 0; i < bytes.length; ++i) {
12837 buffer[i] = bytes.charCodeAt(i); 12838 } 12839 return buffer; 12840} 12841 12842function _privateKeyFromJwk(jwk) { 12843 if(jwk.kty !== 'RSA') { 12844 throw new Error( 12845 'Unsupported key algorithm "' + jwk.kty + '"; algorithm must be "RSA".'); 12846 } 12847 return pki.setRsaPrivateKey( 12848 _base64ToBigInt(jwk.n), 12849 _base64ToBigInt(jwk.e), 12850 _base64ToBigInt(jwk.d), 12851 _base64ToBigInt(jwk.p), 12852 _base64ToBigInt(jwk.q), 12853 _base64ToBigInt(jwk.dp), 12854 _base64ToBigInt(jwk.dq), 12855 _base64ToBigInt(jwk.qi)); 12856} 12857 12858function _publicKeyFromJwk(jwk) { 12859 if(jwk.kty !== 'RSA') { 12860 throw new Error('Key algorithm must be "RSA".'); 12861 } 12862 return pki.setRsaPublicKey( 12863 _base64ToBigInt(jwk.n), 12864 _base64ToBigInt(jwk.e)); 12865} 12866 12867function _base64ToBigInt(b64) { 12868 return new BigInteger(forge.util.bytesToHex(forge.util.decode64(b64)), 16); 12869} 12870 12871} // end module implementation 12872 12873/* ########## Begin module wrapper ########## */ 12874var name = 'rsa'; 12875if(typeof define !== 'function') { 12876 // NodeJS -> AMD 12877 if(typeof module === 'object' && module.exports) { 12878 var nodeJS = true; 12879 define = function(ids, factory) { 12880 factory(require, module); 12881 }; 12882 } else { 12883 // <script> 12884 if(typeof forge === 'undefined') { 12885 forge = {}; 12886 } 12887 return initModule(forge); 12888 } 12889} 12890// AMD 12891var deps; 12892var defineFunc = function(require, module) { 12893 module.exports = function(forge) { 12894 var mods = deps.map(function(dep) { 12895 return require(dep); 12896 }).concat(initModule); 12897 // handle circular dependencies 12898 forge = forge || {}; 12899 forge.defined = forge.defined || {}; 12900 if(forge.defined[name]) { 12901 return forge[name]; 12902 } 12903 forge.defined[name] = true; 12904 for(var i = 0; i < mods.length; ++i) { 12905 mods[i](forge); 12906 } 12907 return forge[name]; 12908 }; 12909}; 12910var tmpDefine = define; 12911define = function(ids, factory) { 12912 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 12913 if(nodeJS) { 12914 delete define; 12915 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 12916 } 12917 define = tmpDefine; 12918 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 12919}; 12920define([ 12921 'require', 12922 'module', 12923 './asn1', 12924 './jsbn', 12925 './oids', 12926 './pkcs1', 12927 './prime', 12928 './random', 12929 './util' 12930], function() { 12931 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 12932}); 12933})(); 12934 12935/** 12936 * Javascript implementation of a basic Public Key Infrastructure, including 12937 * support for RSA public and private keys. 12938 * 12939 * @author Dave Longley 12940 * 12941 * Copyright (c) 2010-2013 Digital Bazaar, Inc. 12942 */ 12943(function() { 12944/* ########## Begin module implementation ########## */ 12945function initModule(forge) { 12946 12947// shortcut for asn.1 API 12948var asn1 = forge.asn1; 12949 12950/* Public Key Infrastructure (PKI) implementation. */ 12951var pki = forge.pki = forge.pki || {}; 12952 12953/** 12954 * NOTE: THIS METHOD IS DEPRECATED. Use pem.decode() instead. 12955 * 12956 * Converts PEM-formatted data to DER. 12957 * 12958 * @param pem the PEM-formatted data. 12959 * 12960 * @return the DER-formatted data. 12961 */ 12962pki.pemToDer = function(pem) { 12963 var msg = forge.pem.decode(pem)[0]; 12964 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 12965 throw new Error('Could not convert PEM to DER; PEM is encrypted.'); 12966 } 12967 return forge.util.createBuffer(msg.body); 12968}; 12969 12970/** 12971 * Converts an RSA private key from PEM format. 12972 * 12973 * @param pem the PEM-formatted private key. 12974 * 12975 * @return the private key. 12976 */ 12977pki.privateKeyFromPem = function(pem) { 12978 var msg = forge.pem.decode(pem)[0]; 12979 12980 if(msg.type !== 'PRIVATE KEY' && msg.type !== 'RSA PRIVATE KEY') { 12981 var error = new Error('Could not convert private key from PEM; PEM ' + 12982 'header type is not "PRIVATE KEY" or "RSA PRIVATE KEY".'); 12983 error.headerType = msg.type; 12984 throw error; 12985 } 12986 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 12987 throw new Error('Could not convert private key from PEM; PEM is encrypted.'); 12988 } 12989 12990 // convert DER to ASN.1 object 12991 var obj = asn1.fromDer(msg.body); 12992 12993 return pki.privateKeyFromAsn1(obj); 12994}; 12995 12996/** 12997 * Converts an RSA private key to PEM format. 12998 * 12999 * @param key the private key. 13000 * @param maxline the maximum characters per line, defaults to 64. 13001 * 13002 * @return the PEM-formatted private key. 13003 */ 13004pki.privateKeyToPem = function(key, maxline) { 13005 // convert to ASN.1, then DER, then PEM-encode 13006 var msg = { 13007 type: 'RSA PRIVATE KEY', 13008 body: asn1.toDer(pki.privateKeyToAsn1(key)).getBytes() 13009 }; 13010 return forge.pem.encode(msg, {maxline: maxline}); 13011}; 13012 13013/** 13014 * Converts a PrivateKeyInfo to PEM format. 13015 * 13016 * @param pki the PrivateKeyInfo. 13017 * @param maxline the maximum characters per line, defaults to 64. 13018 * 13019 * @return the PEM-formatted private key. 13020 */ 13021pki.privateKeyInfoToPem = function(pki, maxline) { 13022 // convert to DER, then PEM-encode 13023 var msg = { 13024 type: 'PRIVATE KEY', 13025 body: asn1.toDer(pki).getBytes() 13026 }; 13027 return forge.pem.encode(msg, {maxline: maxline}); 13028}; 13029 13030} // end module implementation 13031 13032/* ########## Begin module wrapper ########## */ 13033var name = 'pki'; 13034if(typeof define !== 'function') { 13035 // NodeJS -> AMD 13036 if(typeof module === 'object' && module.exports) { 13037 var nodeJS = true; 13038 define = function(ids, factory) { 13039 factory(require, module); 13040 }; 13041 } else { 13042 // <script> 13043 if(typeof forge === 'undefined') { 13044 forge = {}; 13045 } 13046 return initModule(forge); 13047 } 13048} 13049// AMD 13050var deps;
13051var defineFunc = function(require, module) { 13052 module.exports = function(forge) { 13053 var mods = deps.map(function(dep) { 13054 return require(dep); 13055 }).concat(initModule); 13056 // handle circular dependencies 13057 forge = forge || {}; 13058 forge.defined = forge.defined || {}; 13059 if(forge.defined[name]) { 13060 return forge[name]; 13061 } 13062 forge.defined[name] = true; 13063 for(var i = 0; i < mods.length; ++i) { 13064 mods[i](forge); 13065 } 13066 return forge[name]; 13067 }; 13068}; 13069var tmpDefine = define; 13070define = function(ids, factory) { 13071 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 13072 if(nodeJS) { 13073 delete define; 13074 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 13075 } 13076 define = tmpDefine; 13077 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 13078}; 13079define([ 13080 'require', 13081 'module', 13082 './asn1', 13083 './oids', 13084 './pbe', 13085 './pem', 13086 './pbkdf2', 13087 './pkcs12', 13088 './pss', 13089 './rsa', 13090 './util', 13091 './x509' 13092], function() { 13093 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 13094}); 13095})(); 13096 13097/** 13098 * Object IDs for ASN.1. 13099 * 13100 * @author Dave Longley 13101 * 13102 * Copyright (c) 2010-2013 Digital Bazaar, Inc. 13103 */ 13104(function() { 13105/* ########## Begin module implementation ########## */ 13106function initModule(forge) { 13107 13108forge.pki = forge.pki || {}; 13109var oids = forge.pki.oids = forge.oids = forge.oids || {}; 13110 13111// algorithm OIDs 13112oids['1.2.840.113549.1.1.1'] = 'rsaEncryption'; 13113oids['rsaEncryption'] = '1.2.840.113549.1.1.1'; 13114// Note: md2 & md4 not implemented 13115//oids['1.2.840.113549.1.1.2'] = 'md2WithRSAEncryption'; 13116//oids['md2WithRSAEncryption'] = '1.2.840.113549.1.1.2'; 13117//oids['1.2.840.113549.1.1.3'] = 'md4WithRSAEncryption'; 13118//oids['md4WithRSAEncryption'] = '1.2.840.113549.1.1.3'; 13119oids['1.2.840.113549.1.1.4'] = 'md5WithRSAEncryption'; 13120oids['md5WithRSAEncryption'] = '1.2.840.113549.1.1.4'; 13121oids['1.2.840.113549.1.1.5'] = 'sha1WithRSAEncryption'; 13122oids['sha1WithRSAEncryption'] = '1.2.840.113549.1.1.5'; 13123oids['1.2.840.113549.1.1.7'] = 'RSAES-OAEP'; 13124oids['RSAES-OAEP'] = '1.2.840.113549.1.1.7'; 13125oids['1.2.840.113549.1.1.8'] = 'mgf1'; 13126oids['mgf1'] = '1.2.840.113549.1.1.8'; 13127oids['1.2.840.113549.1.1.9'] = 'pSpecified'; 13128oids['pSpecified'] = '1.2.840.113549.1.1.9'; 13129oids['1.2.840.113549.1.1.10'] = 'RSASSA-PSS'; 13130oids['RSASSA-PSS'] = '1.2.840.113549.1.1.10'; 13131oids['1.2.840.113549.1.1.11'] = 'sha256WithRSAEncryption'; 13132oids['sha256WithRSAEncryption'] = '1.2.840.113549.1.1.11'; 13133oids['1.2.840.113549.1.1.12'] = 'sha384WithRSAEncryption'; 13134oids['sha384WithRSAEncryption'] = '1.2.840.113549.1.1.12'; 13135oids['1.2.840.113549.1.1.13'] = 'sha512WithRSAEncryption'; 13136oids['sha512WithRSAEncryption'] = '1.2.840.113549.1.1.13'; 13137 13138oids['1.3.14.3.2.7'] = 'desCBC'; 13139oids['desCBC'] = '1.3.14.3.2.7'; 13140 13141oids['1.3.14.3.2.26'] = 'sha1'; 13142oids['sha1'] = '1.3.14.3.2.26'; 13143oids['2.16.840.1.101.3.4.2.1'] = 'sha256'; 13144oids['sha256'] = '2.16.840.1.101.3.4.2.1'; 13145oids['2.16.840.1.101.3.4.2.2'] = 'sha384'; 13146oids['sha384'] = '2.16.840.1.101.3.4.2.2'; 13147oids['2.16.840.1.101.3.4.2.3'] = 'sha512'; 13148oids['sha512'] = '2.16.840.1.101.3.4.2.3'; 13149oids['1.2.840.113549.2.5'] = 'md5'; 13150oids['md5'] = '1.2.840.113549.2.5'; 13151 13152// pkcs#7 content types 13153oids['1.2.840.113549.1.7.1'] = 'data'; 13154oids['data'] = '1.2.840.113549.1.7.1'; 13155oids['1.2.840.113549.1.7.2'] = 'signedData'; 13156oids['signedData'] = '1.2.840.113549.1.7.2'; 13157oids['1.2.840.113549.1.7.3'] = 'envelopedData'; 13158oids['envelopedData'] = '1.2.840.113549.1.7.3'; 13159oids['1.2.840.113549.1.7.4'] = 'signedAndEnvelopedData'; 13160oids['signedAndEnvelopedData'] = '1.2.840.113549.1.7.4'; 13161oids['1.2.840.113549.1.7.5'] = 'digestedData'; 13162oids['digestedData'] = '1.2.840.113549.1.7.5'; 13163oids['1.2.840.113549.1.7.6'] = 'encryptedData'; 13164oids['encryptedData'] = '1.2.840.113549.1.7.6'; 13165 13166// pkcs#9 oids 13167oids['1.2.840.113549.1.9.1'] = 'emailAddress'; 13168oids['emailAddress'] = '1.2.840.113549.1.9.1'; 13169oids['1.2.840.113549.1.9.2'] = 'unstructuredName'; 13170oids['unstructuredName'] = '1.2.840.113549.1.9.2'; 13171oids['1.2.840.113549.1.9.3'] = 'contentType'; 13172oids['contentType'] = '1.2.840.113549.1.9.3'; 13173oids['1.2.840.113549.1.9.4'] = 'messageDigest'; 13174oids['messageDigest'] = '1.2.840.113549.1.9.4'; 13175oids['1.2.840.113549.1.9.5'] = 'signingTime'; 13176oids['signingTime'] = '1.2.840.113549.1.9.5'; 13177oids['1.2.840.113549.1.9.6'] = 'counterSignature'; 13178oids['counterSignature'] = '1.2.840.113549.1.9.6'; 13179oids['1.2.840.113549.1.9.7'] = 'challengePassword';
13180oids['challengePassword'] = '1.2.840.113549.1.9.7'; 13181oids['1.2.840.113549.1.9.8'] = 'unstructuredAddress'; 13182oids['unstructuredAddress'] = '1.2.840.113549.1.9.8'; 13183oids['1.2.840.113549.1.9.14'] = 'extensionRequest'; 13184oids['extensionRequest'] = '1.2.840.113549.1.9.14'; 13185 13186oids['1.2.840.113549.1.9.20'] = 'friendlyName'; 13187oids['friendlyName'] = '1.2.840.113549.1.9.20'; 13188oids['1.2.840.113549.1.9.21'] = 'localKeyId'; 13189oids['localKeyId'] = '1.2.840.113549.1.9.21'; 13190oids['1.2.840.113549.1.9.22.1'] = 'x509Certificate'; 13191oids['x509Certificate'] = '1.2.840.113549.1.9.22.1'; 13192 13193// pkcs#12 safe bags 13194oids['1.2.840.113549.1.12.10.1.1'] = 'keyBag'; 13195oids['keyBag'] = '1.2.840.113549.1.12.10.1.1'; 13196oids['1.2.840.113549.1.12.10.1.2'] = 'pkcs8ShroudedKeyBag'; 13197oids['pkcs8ShroudedKeyBag'] = '1.2.840.113549.1.12.10.1.2'; 13198oids['1.2.840.113549.1.12.10.1.3'] = 'certBag'; 13199oids['certBag'] = '1.2.840.113549.1.12.10.1.3'; 13200oids['1.2.840.113549.1.12.10.1.4'] = 'crlBag'; 13201oids['crlBag'] = '1.2.840.113549.1.12.10.1.4'; 13202oids['1.2.840.113549.1.12.10.1.5'] = 'secretBag'; 13203oids['secretBag'] = '1.2.840.113549.1.12.10.1.5'; 13204oids['1.2.840.113549.1.12.10.1.6'] = 'safeContentsBag'; 13205oids['safeContentsBag'] = '1.2.840.113549.1.12.10.1.6'; 13206 13207// password-based-encryption for pkcs#12 13208oids['1.2.840.113549.1.5.13'] = 'pkcs5PBES2'; 13209oids['pkcs5PBES2'] = '1.2.840.113549.1.5.13'; 13210oids['1.2.840.113549.1.5.12'] = 'pkcs5PBKDF2'; 13211oids['pkcs5PBKDF2'] = '1.2.840.113549.1.5.12'; 13212 13213oids['1.2.840.113549.1.12.1.1'] = 'pbeWithSHAAnd128BitRC4'; 13214oids['pbeWithSHAAnd128BitRC4'] = '1.2.840.113549.1.12.1.1'; 13215oids['1.2.840.113549.1.12.1.2'] = 'pbeWithSHAAnd40BitRC4'; 13216oids['pbeWithSHAAnd40BitRC4'] = '1.2.840.113549.1.12.1.2'; 13217oids['1.2.840.113549.1.12.1.3'] = 'pbeWithSHAAnd3-KeyTripleDES-CBC'; 13218oids['pbeWithSHAAnd3-KeyTripleDES-CBC'] = '1.2.840.113549.1.12.1.3'; 13219oids['1.2.840.113549.1.12.1.4'] = 'pbeWithSHAAnd2-KeyTripleDES-CBC'; 13220oids['pbeWithSHAAnd2-KeyTripleDES-CBC'] = '1.2.840.113549.1.12.1.4'; 13221oids['1.2.840.113549.1.12.1.5'] = 'pbeWithSHAAnd128BitRC2-CBC'; 13222oids['pbeWithSHAAnd128BitRC2-CBC'] = '1.2.840.113549.1.12.1.5'; 13223oids['1.2.840.113549.1.12.1.6'] = 'pbewithSHAAnd40BitRC2-CBC'; 13224oids['pbewithSHAAnd40BitRC2-CBC'] = '1.2.840.113549.1.12.1.6'; 13225 13226// hmac OIDs 13227oids['1.2.840.113549.2.7'] = 'hmacWithSHA1'; 13228oids['hmacWithSHA1'] = '1.2.840.113549.2.7'; 13229oids['1.2.840.113549.2.8'] = 'hmacWithSHA224'; 13230oids['hmacWithSHA224'] = '1.2.840.113549.2.8'; 13231oids['1.2.840.113549.2.9'] = 'hmacWithSHA256'; 13232oids['hmacWithSHA256'] = '1.2.840.113549.2.9'; 13233oids['1.2.840.113549.2.10'] = 'hmacWithSHA384'; 13234oids['hmacWithSHA384'] = '1.2.840.113549.2.10'; 13235oids['1.2.840.113549.2.11'] = 'hmacWithSHA512'; 13236oids['hmacWithSHA512'] = '1.2.840.113549.2.11'; 13237 13238// symmetric key algorithm oids 13239oids['1.2.840.113549.3.7'] = 'des-EDE3-CBC'; 13240oids['des-EDE3-CBC'] = '1.2.840.113549.3.7'; 13241oids['2.16.840.1.101.3.4.1.2'] = 'aes128-CBC'; 13242oids['aes128-CBC'] = '2.16.840.1.101.3.4.1.2'; 13243oids['2.16.840.1.101.3.4.1.22'] = 'aes192-CBC'; 13244oids['aes192-CBC'] = '2.16.840.1.101.3.4.1.22'; 13245oids['2.16.840.1.101.3.4.1.42'] = 'aes256-CBC'; 13246oids['aes256-CBC'] = '2.16.840.1.101.3.4.1.42'; 13247 13248// certificate issuer/subject OIDs 13249oids['2.5.4.3'] = 'commonName'; 13250oids['commonName'] = '2.5.4.3'; 13251oids['2.5.4.5'] = 'serialName'; 13252oids['serialName'] = '2.5.4.5'; 13253oids['2.5.4.6'] = 'countryName'; 13254oids['countryName'] = '2.5.4.6';
13255oids['2.5.4.7'] = 'localityName'; 13256oids['localityName'] = '2.5.4.7'; 13257oids['2.5.4.8'] = 'stateOrProvinceName'; 13258oids['stateOrProvinceName'] = '2.5.4.8'; 13259oids['2.5.4.10'] = 'organizationName'; 13260oids['organizationName'] = '2.5.4.10'; 13261oids['2.5.4.11'] = 'organizationalUnitName'; 13262oids['organizationalUnitName'] = '2.5.4.11'; 13263 13264// X.509 extension OIDs 13265oids['2.16.840.1.113730.1.1'] = 'nsCertType'; 13266oids['nsCertType'] = '2.16.840.1.113730.1.1'; 13267oids['2.5.29.1'] = 'authorityKeyIdentifier'; // deprecated, use .35 13268oids['2.5.29.2'] = 'keyAttributes'; // obsolete use .37 or .15 13269oids['2.5.29.3'] = 'certificatePolicies'; // deprecated, use .32 13270oids['2.5.29.4'] = 'keyUsageRestriction'; // obsolete use .37 or .15 13271oids['2.5.29.5'] = 'policyMapping'; // deprecated use .33 13272oids['2.5.29.6'] = 'subtreesConstraint'; // obsolete use .30 13273oids['2.5.29.7'] = 'subjectAltName'; // deprecated use .17 13274oids['2.5.29.8'] = 'issuerAltName'; // deprecated use .18 13275oids['2.5.29.9'] = 'subjectDirectoryAttributes'; 13276oids['2.5.29.10'] = 'basicConstraints'; // deprecated use .19 13277oids['2.5.29.11'] = 'nameConstraints'; // deprecated use .30 13278oids['2.5.29.12'] = 'policyConstraints'; // deprecated use .36 13279oids['2.5.29.13'] = 'basicConstraints'; // deprecated use .19 13280oids['2.5.29.14'] = 'subjectKeyIdentifier'; 13281oids['subjectKeyIdentifier'] = '2.5.29.14'; 13282oids['2.5.29.15'] = 'keyUsage'; 13283oids['keyUsage'] = '2.5.29.15'; 13284oids['2.5.29.16'] = 'privateKeyUsagePeriod'; 13285oids['2.5.29.17'] = 'subjectAltName'; 13286oids['subjectAltName'] = '2.5.29.17'; 13287oids['2.5.29.18'] = 'issuerAltName'; 13288oids['issuerAltName'] = '2.5.29.18'; 13289oids['2.5.29.19'] = 'basicConstraints'; 13290oids['basicConstraints'] = '2.5.29.19'; 13291oids['2.5.29.20'] = 'cRLNumber'; 13292oids['2.5.29.21'] = 'cRLReason'; 13293oids['2.5.29.22'] = 'expirationDate'; 13294oids['2.5.29.23'] = 'instructionCode'; 13295oids['2.5.29.24'] = 'invalidityDate'; 13296oids['2.5.29.25'] = 'cRLDistributionPoints'; // deprecated use .31 13297oids['2.5.29.26'] = 'issuingDistributionPoint'; // deprecated use .28 13298oids['2.5.29.27'] = 'deltaCRLIndicator'; 13299oids['2.5.29.28'] = 'issuingDistributionPoint'; 13300oids['2.5.29.29'] = 'certificateIssuer'; 13301oids['2.5.29.30'] = 'nameConstraints'; 13302oids['2.5.29.31'] = 'cRLDistributionPoints'; 13303oids['cRLDistributionPoints'] = '2.5.29.31'; 13304oids['2.5.29.32'] = 'certificatePolicies'; 13305oids['certificatePolicies'] = '2.5.29.32'; 13306oids['2.5.29.33'] = 'policyMappings'; 13307oids['2.5.29.34'] = 'policyConstraints'; // deprecated use .36 13308oids['2.5.29.35'] = 'authorityKeyIdentifier'; 13309oids['authorityKeyIdentifier'] = '2.5.29.35'; 13310oids['2.5.29.36'] = 'policyConstraints'; 13311oids['2.5.29.37'] = 'extKeyUsage'; 13312oids['extKeyUsage'] = '2.5.29.37'; 13313oids['2.5.29.46'] = 'freshestCRL'; 13314oids['2.5.29.54'] = 'inhibitAnyPolicy'; 13315 13316// extKeyUsage purposes 13317oids['1.3.6.1.4.1.11129.2.4.2'] = 'timestampList'; 13318oids['timestampList'] = '1.3.6.1.4.1.11129.2.4.2'; 13319oids['1.3.6.1.5.5.7.1.1'] = 'authorityInfoAccess'; 13320oids['authorityInfoAccess'] = '1.3.6.1.5.5.7.1.1'; 13321oids['1.3.6.1.5.5.7.3.1'] = 'serverAuth'; 13322oids['serverAuth'] = '1.3.6.1.5.5.7.3.1'; 13323oids['1.3.6.1.5.5.7.3.2'] = 'clientAuth'; 13324oids['clientAuth'] = '1.3.6.1.5.5.7.3.2'; 13325oids['1.3.6.1.5.5.7.3.3'] = 'codeSigning'; 13326oids['codeSigning'] = '1.3.6.1.5.5.7.3.3'; 13327oids['1.3.6.1.5.5.7.3.4'] = 'emailProtection'; 13328oids['emailProtection'] = '1.3.6.1.5.5.7.3.4'; 13329oids['1.3.6.1.5.5.7.3.8'] = 'timeStamping'; 13330oids['timeStamping'] = '1.3.6.1.5.5.7.3.8'; 13331 13332} // end module implementation 13333 13334/* ########## Begin module wrapper ########## */ 13335var name = 'oids'; 13336if(typeof define !== 'function') { 13337 // NodeJS -> AMD 13338 if(typeof module === 'object' && module.exports) { 13339 var nodeJS = true; 13340 define = function(ids, factory) { 13341 factory(require, module); 13342 }; 13343 } else { 13344 // <script> 13345 if(typeof forge === 'undefined') { 13346 forge = {}; 13347 } 13348 return initModule(forge); 13349 } 13350} 13351// AMD 13352var deps; 13353var defineFunc = function(require, module) { 13354 module.exports = function(forge) { 13355 var mods = deps.map(function(dep) { 13356 return require(dep); 13357 }).concat(initModule); 13358 // handle circular dependencies 13359 forge = forge || {}; 13360 forge.defined = forge.defined || {}; 13361 if(forge.defined[name]) { 13362 return forge[name]; 13363 } 13364 forge.defined[name] = true; 13365 for(var i = 0; i < mods.length; ++i) { 13366 mods[i](forge); 13367 } 13368 return forge[name]; 13369 }; 13370}; 13371var tmpDefine = define; 13372define = function(ids, factory) { 13373 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 13374 if(nodeJS) { 13375 delete define; 13376 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 13377 } 13378 define = tmpDefine; 13379 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 13380}; 13381define(['require', 'module'], function() { 13382 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 13383}); 13384})(); 13385 13386/** 13387 * Javascript implementation of X.509 and related components (such as
13388 * Certification Signing Requests) of a Public Key Infrastructure. 13389 * 13390 * @author Dave Longley 13391 * 13392 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 13393 * 13394 * The ASN.1 representation of an X.509v3 certificate is as follows 13395 * (see RFC 2459): 13396 * 13397 * Certificate ::= SEQUENCE { 13398 * tbsCertificate TBSCertificate, 13399 * signatureAlgorithm AlgorithmIdentifier, 13400 * signatureValue BIT STRING 13401 * } 13402 * 13403 * TBSCertificate ::= SEQUENCE { 13404 * version [0] EXPLICIT Version DEFAULT v1, 13405 * serialNumber CertificateSerialNumber, 13406 * signature AlgorithmIdentifier, 13407 * issuer Name, 13408 * validity Validity, 13409 * subject Name, 13410 * subjectPublicKeyInfo SubjectPublicKeyInfo, 13411 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, 13412 * -- If present, version shall be v2 or v3 13413 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, 13414 * -- If present, version shall be v2 or v3 13415 * extensions [3] EXPLICIT Extensions OPTIONAL 13416 * -- If present, version shall be v3 13417 * } 13418 * 13419 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 13420 * 13421 * CertificateSerialNumber ::= INTEGER 13422 * 13423 * Name ::= CHOICE { 13424 * // only one possible choice for now 13425 * RDNSequence 13426 * } 13427 * 13428 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 13429 * 13430 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue 13431 * 13432 * AttributeTypeAndValue ::= SEQUENCE { 13433 * type AttributeType, 13434 * value AttributeValue 13435 * } 13436 * AttributeType ::= OBJECT IDENTIFIER 13437 * AttributeValue ::= ANY DEFINED BY AttributeType 13438 * 13439 * Validity ::= SEQUENCE { 13440 * notBefore Time, 13441 * notAfter Time 13442 * } 13443 * 13444 * Time ::= CHOICE { 13445 * utcTime UTCTime, 13446 * generalTime GeneralizedTime 13447 * } 13448 * 13449 * UniqueIdentifier ::= BIT STRING 13450 * 13451 * SubjectPublicKeyInfo ::= SEQUENCE { 13452 * algorithm AlgorithmIdentifier, 13453 * subjectPublicKey BIT STRING 13454 * } 13455 * 13456 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 13457 * 13458 * Extension ::= SEQUENCE { 13459 * extnID OBJECT IDENTIFIER, 13460 * critical BOOLEAN DEFAULT FALSE, 13461 * extnValue OCTET STRING 13462 * } 13463 * 13464 * The only key algorithm currently supported for PKI is RSA. 13465 * 13466 * RSASSA-PSS signatures are described in RFC 3447 and RFC 4055. 13467 * 13468 * PKCS#10 v1.7 describes certificate signing requests: 13469 * 13470 * CertificationRequestInfo: 13471 * 13472 * CertificationRequestInfo ::= SEQUENCE { 13473 * version INTEGER { v1(0) } (v1,...), 13474 * subject Name, 13475 * subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, 13476 * attributes [0] Attributes{{ CRIAttributes }} 13477 * } 13478 * 13479 * Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }} 13480 * 13481 * CRIAttributes ATTRIBUTE ::= { 13482 * ... -- add any locally defined attributes here -- } 13483 * 13484 * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE { 13485 * type ATTRIBUTE.&id({IOSet}), 13486 * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) 13487 * } 13488 * 13489 * CertificationRequest ::= SEQUENCE { 13490 * certificationRequestInfo CertificationRequestInfo, 13491 * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, 13492 * signature BIT STRING 13493 * } 13494 */ 13495(function() { 13496/* ########## Begin module implementation ########## */ 13497function initModule(forge) { 13498 13499// shortcut for asn.1 API 13500var asn1 = forge.asn1; 13501 13502/* Public Key Infrastructure (PKI) implementation. */ 13503var pki = forge.pki = forge.pki || {}; 13504var oids = pki.oids; 13505 13506// short name OID mappings 13507var _shortNames = {}; 13508_shortNames['CN'] = oids['commonName']; 13509_shortNames['commonName'] = 'CN'; 13510_shortNames['C'] = oids['countryName']; 13511_shortNames['countryName'] = 'C'; 13512_shortNames['L'] = oids['localityName']; 13513_shortNames['localityName'] = 'L'; 13514_shortNames['ST'] = oids['stateOrProvinceName']; 13515_shortNames['stateOrProvinceName'] = 'ST'; 13516_shortNames['O'] = oids['organizationName']; 13517_shortNames['organizationName'] = 'O'; 13518_shortNames['OU'] = oids['organizationalUnitName']; 13519_shortNames['organizationalUnitName'] = 'OU'; 13520_shortNames['E'] = oids['emailAddress']; 13521_shortNames['emailAddress'] = 'E'; 13522 13523// validator for an SubjectPublicKeyInfo structure
13524// Note: Currently only works with an RSA public key 13525var publicKeyValidator = forge.pki.rsa.publicKeyValidator; 13526 13527// validator for an X.509v3 certificate 13528var x509CertificateValidator = { 13529 name: 'Certificate', 13530 tagClass: asn1.Class.UNIVERSAL, 13531 type: asn1.Type.SEQUENCE, 13532 constructed: true, 13533 value: [{ 13534 name: 'Certificate.TBSCertificate', 13535 tagClass: asn1.Class.UNIVERSAL, 13536 type: asn1.Type.SEQUENCE, 13537 constructed: true, 13538 captureAsn1: 'tbsCertificate', 13539 value: [{ 13540 name: 'Certificate.TBSCertificate.version', 13541 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13542 type: 0, 13543 constructed: true, 13544 optional: true, 13545 value: [{ 13546 name: 'Certificate.TBSCertificate.version.integer', 13547 tagClass: asn1.Class.UNIVERSAL, 13548 type: asn1.Type.INTEGER, 13549 constructed: false, 13550 capture: 'certVersion' 13551 }] 13552 }, { 13553 name: 'Certificate.TBSCertificate.serialNumber', 13554 tagClass: asn1.Class.UNIVERSAL, 13555 type: asn1.Type.INTEGER, 13556 constructed: false, 13557 capture: 'certSerialNumber' 13558 }, { 13559 name: 'Certificate.TBSCertificate.signature', 13560 tagClass: asn1.Class.UNIVERSAL, 13561 type: asn1.Type.SEQUENCE, 13562 constructed: true, 13563 value: [{ 13564 name: 'Certificate.TBSCertificate.signature.algorithm', 13565 tagClass: asn1.Class.UNIVERSAL, 13566 type: asn1.Type.OID, 13567 constructed: false, 13568 capture: 'certinfoSignatureOid' 13569 }, { 13570 name: 'Certificate.TBSCertificate.signature.parameters', 13571 tagClass: asn1.Class.UNIVERSAL, 13572 optional: true, 13573 captureAsn1: 'certinfoSignatureParams' 13574 }] 13575 }, { 13576 name: 'Certificate.TBSCertificate.issuer', 13577 tagClass: asn1.Class.UNIVERSAL, 13578 type: asn1.Type.SEQUENCE, 13579 constructed: true, 13580 captureAsn1: 'certIssuer' 13581 }, { 13582 name: 'Certificate.TBSCertificate.validity', 13583 tagClass: asn1.Class.UNIVERSAL, 13584 type: asn1.Type.SEQUENCE, 13585 constructed: true, 13586 // Note: UTC and generalized times may both appear so the capture 13587 // names are based on their detected order, the names used below 13588 // are only for the common case, which validity time really means 13589 // "notBefore" and which means "notAfter" will be determined by order 13590 value: [{ 13591 // notBefore (Time) (UTC time case) 13592 name: 'Certificate.TBSCertificate.validity.notBefore (utc)', 13593 tagClass: asn1.Class.UNIVERSAL, 13594 type: asn1.Type.UTCTIME, 13595 constructed: false, 13596 optional: true, 13597 capture: 'certValidity1UTCTime' 13598 }, { 13599 // notBefore (Time) (generalized time case) 13600 name: 'Certificate.TBSCertificate.validity.notBefore (generalized)', 13601 tagClass: asn1.Class.UNIVERSAL, 13602 type: asn1.Type.GENERALIZEDTIME, 13603 constructed: false, 13604 optional: true, 13605 capture: 'certValidity2GeneralizedTime' 13606 }, { 13607 // notAfter (Time) (only UTC time is supported) 13608 name: 'Certificate.TBSCertificate.validity.notAfter (utc)', 13609 tagClass: asn1.Class.UNIVERSAL, 13610 type: asn1.Type.UTCTIME, 13611 constructed: false, 13612 optional: true, 13613 capture: 'certValidity3UTCTime' 13614 }, { 13615 // notAfter (Time) (only UTC time is supported) 13616 name: 'Certificate.TBSCertificate.validity.notAfter (generalized)', 13617 tagClass: asn1.Class.UNIVERSAL, 13618 type: asn1.Type.GENERALIZEDTIME, 13619 constructed: false, 13620 optional: true, 13621 capture: 'certValidity4GeneralizedTime' 13622 }] 13623 }, { 13624 // Name (subject) (RDNSequence) 13625 name: 'Certificate.TBSCertificate.subject', 13626 tagClass: asn1.Class.UNIVERSAL, 13627 type: asn1.Type.SEQUENCE, 13628 constructed: true, 13629 captureAsn1: 'certSubject' 13630 }, 13631 // SubjectPublicKeyInfo 13632 publicKeyValidator, 13633 { 13634 // issuerUniqueID (optional) 13635 name: 'Certificate.TBSCertificate.issuerUniqueID', 13636 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13637 type: 1, 13638 constructed: true, 13639 optional: true, 13640 value: [{ 13641 name: 'Certificate.TBSCertificate.issuerUniqueID.id', 13642 tagClass: asn1.Class.UNIVERSAL, 13643 type: asn1.Type.BITSTRING, 13644 constructed: false, 13645 capture: 'certIssuerUniqueId' 13646 }] 13647 }, {
13648 // subjectUniqueID (optional) 13649 name: 'Certificate.TBSCertificate.subjectUniqueID', 13650 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13651 type: 2, 13652 constructed: true, 13653 optional: true, 13654 value: [{ 13655 name: 'Certificate.TBSCertificate.subjectUniqueID.id', 13656 tagClass: asn1.Class.UNIVERSAL, 13657 type: asn1.Type.BITSTRING, 13658 constructed: false, 13659 capture: 'certSubjectUniqueId' 13660 }] 13661 }, { 13662 // Extensions (optional) 13663 name: 'Certificate.TBSCertificate.extensions', 13664 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13665 type: 3, 13666 constructed: true, 13667 captureAsn1: 'certExtensions', 13668 optional: true 13669 }] 13670 }, { 13671 // AlgorithmIdentifier (signature algorithm) 13672 name: 'Certificate.signatureAlgorithm', 13673 tagClass: asn1.Class.UNIVERSAL, 13674 type: asn1.Type.SEQUENCE, 13675 constructed: true, 13676 value: [{ 13677 // algorithm 13678 name: 'Certificate.signatureAlgorithm.algorithm', 13679 tagClass: asn1.Class.UNIVERSAL, 13680 type: asn1.Type.OID, 13681 constructed: false, 13682 capture: 'certSignatureOid' 13683 }, { 13684 name: 'Certificate.TBSCertificate.signature.parameters', 13685 tagClass: asn1.Class.UNIVERSAL, 13686 optional: true, 13687 captureAsn1: 'certSignatureParams' 13688 }] 13689 }, { 13690 // SignatureValue 13691 name: 'Certificate.signatureValue', 13692 tagClass: asn1.Class.UNIVERSAL, 13693 type: asn1.Type.BITSTRING, 13694 constructed: false, 13695 capture: 'certSignature' 13696 }] 13697}; 13698 13699var rsassaPssParameterValidator = { 13700 name: 'rsapss', 13701 tagClass: asn1.Class.UNIVERSAL, 13702 type: asn1.Type.SEQUENCE, 13703 constructed: true, 13704 value: [{ 13705 name: 'rsapss.hashAlgorithm', 13706 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13707 type: 0, 13708 constructed: true, 13709 value: [{ 13710 name: 'rsapss.hashAlgorithm.AlgorithmIdentifier', 13711 tagClass: asn1.Class.UNIVERSAL, 13712 type: asn1.Class.SEQUENCE, 13713 constructed: true, 13714 optional: true, 13715 value: [{ 13716 name: 'rsapss.hashAlgorithm.AlgorithmIdentifier.algorithm', 13717 tagClass: asn1.Class.UNIVERSAL, 13718 type: asn1.Type.OID, 13719 constructed: false, 13720 capture: 'hashOid' 13721 /* parameter block omitted, for SHA1 NULL anyhow. */ 13722 }] 13723 }] 13724 }, { 13725 name: 'rsapss.maskGenAlgorithm', 13726 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13727 type: 1, 13728 constructed: true, 13729 value: [{ 13730 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier', 13731 tagClass: asn1.Class.UNIVERSAL, 13732 type: asn1.Class.SEQUENCE, 13733 constructed: true, 13734 optional: true, 13735 value: [{ 13736 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.algorithm', 13737 tagClass: asn1.Class.UNIVERSAL, 13738 type: asn1.Type.OID, 13739 constructed: false, 13740 capture: 'maskGenOid' 13741 }, { 13742 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params', 13743 tagClass: asn1.Class.UNIVERSAL, 13744 type: asn1.Type.SEQUENCE, 13745 constructed: true, 13746 value: [{ 13747 name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params.algorithm', 13748 tagClass: asn1.Class.UNIVERSAL, 13749 type: asn1.Type.OID, 13750 constructed: false, 13751 capture: 'maskGenHashOid' 13752 /* parameter block omitted, for SHA1 NULL anyhow. */ 13753 }] 13754 }] 13755 }] 13756 }, { 13757 name: 'rsapss.saltLength', 13758 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13759 type: 2, 13760 optional: true, 13761 value: [{ 13762 name: 'rsapss.saltLength.saltLength', 13763 tagClass: asn1.Class.UNIVERSAL, 13764 type: asn1.Class.INTEGER, 13765 constructed: false, 13766 capture: 'saltLength' 13767 }] 13768 }, { 13769 name: 'rsapss.trailerField', 13770 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13771 type: 3, 13772 optional: true, 13773 value: [{ 13774 name: 'rsapss.trailer.trailer', 13775 tagClass: asn1.Class.UNIVERSAL, 13776 type: asn1.Class.INTEGER, 13777 constructed: false, 13778 capture: 'trailer' 13779 }] 13780 }] 13781}; 13782 13783// validator for a CertificationRequestInfo structure 13784var certificationRequestInfoValidator = { 13785 name: 'CertificationRequestInfo', 13786 tagClass: asn1.Class.UNIVERSAL, 13787 type: asn1.Type.SEQUENCE, 13788 constructed: true, 13789 captureAsn1: 'certificationRequestInfo', 13790 value: [{ 13791 name: 'CertificationRequestInfo.integer', 13792 tagClass: asn1.Class.UNIVERSAL, 13793 type: asn1.Type.INTEGER, 13794 constructed: false, 13795 capture: 'certificationRequestInfoVersion' 13796 }, { 13797 // Name (subject) (RDNSequence) 13798 name: 'CertificationRequestInfo.subject', 13799 tagClass: asn1.Class.UNIVERSAL, 13800 type: asn1.Type.SEQUENCE, 13801 constructed: true, 13802 captureAsn1: 'certificationRequestInfoSubject' 13803 }, 13804 // SubjectPublicKeyInfo 13805 publicKeyValidator, 13806 { 13807 name: 'CertificationRequestInfo.attributes', 13808 tagClass: asn1.Class.CONTEXT_SPECIFIC, 13809 type: 0, 13810 constructed: true, 13811 optional: true, 13812 capture: 'certificationRequestInfoAttributes', 13813 value: [{ 13814 name: 'CertificationRequestInfo.attributes', 13815 tagClass: asn1.Class.UNIVERSAL, 13816 type: asn1.Type.SEQUENCE, 13817 constructed: true, 13818 value: [{ 13819 name: 'CertificationRequestInfo.attributes.type', 13820 tagClass: asn1.Class.UNIVERSAL, 13821 type: asn1.Type.OID, 13822 constructed: false 13823 }, { 13824 name: 'CertificationRequestInfo.attributes.value', 13825 tagClass: asn1.Class.UNIVERSAL, 13826 type: asn1.Type.SET, 13827 constructed: true 13828 }] 13829 }] 13830 }] 13831}; 13832 13833// validator for a CertificationRequest structure 13834var certificationRequestValidator = { 13835 name: 'CertificationRequest', 13836 tagClass: asn1.Class.UNIVERSAL, 13837 type: asn1.Type.SEQUENCE, 13838 constructed: true, 13839 captureAsn1: 'csr', 13840 value: [ 13841 certificationRequestInfoValidator, { 13842 // AlgorithmIdentifier (signature algorithm) 13843 name: 'CertificationRequest.signatureAlgorithm', 13844 tagClass: asn1.Class.UNIVERSAL, 13845 type: asn1.Type.SEQUENCE, 13846 constructed: true, 13847 value: [{ 13848 // algorithm 13849 name: 'CertificationRequest.signatureAlgorithm.algorithm', 13850 tagClass: asn1.Class.UNIVERSAL, 13851 type: asn1.Type.OID, 13852 constructed: false, 13853 capture: 'csrSignatureOid' 13854 }, {
13855 name: 'CertificationRequest.signatureAlgorithm.parameters', 13856 tagClass: asn1.Class.UNIVERSAL, 13857 optional: true, 13858 captureAsn1: 'csrSignatureParams' 13859 }] 13860 }, { 13861 // signature 13862 name: 'CertificationRequest.signature', 13863 tagClass: asn1.Class.UNIVERSAL, 13864 type: asn1.Type.BITSTRING, 13865 constructed: false, 13866 capture: 'csrSignature' 13867 }] 13868}; 13869 13870/** 13871 * Converts an RDNSequence of ASN.1 DER-encoded RelativeDistinguishedName 13872 * sets into an array with objects that have type and value properties. 13873 * 13874 * @param rdn the RDNSequence to convert. 13875 * @param md a message digest to append type and value to if provided. 13876 */ 13877pki.RDNAttributesAsArray = function(rdn, md) { 13878 var rval = []; 13879 13880 // each value in 'rdn' in is a SET of RelativeDistinguishedName 13881 var set, attr, obj; 13882 for(var si = 0; si < rdn.value.length; ++si) { 13883 // get the RelativeDistinguishedName set 13884 set = rdn.value[si]; 13885 13886 // each value in the SET is an AttributeTypeAndValue sequence 13887 // containing first a type (an OID) and second a value (defined by 13888 // the OID) 13889 for(var i = 0; i < set.value.length; ++i) { 13890 obj = {}; 13891 attr = set.value[i]; 13892 obj.type = asn1.derToOid(attr.value[0].value); 13893 obj.value = attr.value[1].value; 13894 obj.valueTagClass = attr.value[1].type; 13895 // if the OID is known, get its name and short name 13896 if(obj.type in oids) { 13897 obj.name = oids[obj.type]; 13898 if(obj.name in _shortNames) { 13899 obj.shortName = _shortNames[obj.name]; 13900 } 13901 } 13902 if(md) { 13903 md.update(obj.type); 13904 md.update(obj.value); 13905 } 13906 rval.push(obj); 13907 } 13908 } 13909 13910 return rval; 13911}; 13912 13913/** 13914 * Converts ASN.1 CRIAttributes into an array with objects that have type and 13915 * value properties. 13916 * 13917 * @param attributes the CRIAttributes to convert. 13918 */ 13919pki.CRIAttributesAsArray = function(attributes) { 13920 var rval = []; 13921 13922 // each value in 'attributes' in is a SEQUENCE with an OID and a SET 13923 for(var si = 0; si < attributes.length; ++si) { 13924 // get the attribute sequence 13925 var seq = attributes[si]; 13926 13927 // each value in the SEQUENCE containing first a type (an OID) and 13928 // second a set of values (defined by the OID) 13929 var type = asn1.derToOid(seq.value[0].value); 13930 var values = seq.value[1].value; 13931 for(var vi = 0; vi < values.length; ++vi) { 13932 var obj = {}; 13933 obj.type = type; 13934 obj.value = values[vi].value; 13935 obj.valueTagClass = values[vi].type; 13936 // if the OID is known, get its name and short name 13937 if(obj.type in oids) { 13938 obj.name = oids[obj.type]; 13939 if(obj.name in _shortNames) { 13940 obj.shortName = _shortNames[obj.name]; 13941 } 13942 } 13943 // parse extensions 13944 if(obj.type === oids.extensionRequest) { 13945 obj.extensions = []; 13946 for(var ei = 0; ei < obj.value.length; ++ei) { 13947 obj.extensions.push(pki.certificateExtensionFromAsn1(obj.value[ei])); 13948 } 13949 } 13950 rval.push(obj); 13951 } 13952 } 13953 13954 return rval; 13955}; 13956 13957/** 13958 * Gets an issuer or subject attribute from its name, type, or short name. 13959 * 13960 * @param obj the issuer or subject object. 13961 * @param options a short name string or an object with: 13962 * shortName the short name for the attribute. 13963 * name the name for the attribute. 13964 * type the type for the attribute. 13965 * 13966 * @return the attribute. 13967 */ 13968function _getAttribute(obj, options) { 13969 if(typeof options === 'string') { 13970 options = {shortName: options}; 13971 } 13972 13973 var rval = null; 13974 var attr; 13975 for(var i = 0; rval === null && i < obj.attributes.length; ++i) { 13976 attr = obj.attributes[i]; 13977 if(options.type && options.type === attr.type) { 13978 rval = attr; 13979 } else if(options.name && options.name === attr.name) { 13980 rval = attr; 13981 } else if(options.shortName && options.shortName === attr.shortName) { 13982 rval = attr; 13983 } 13984 } 13985 return rval; 13986} 13987 13988/** 13989 * Converts signature parameters from ASN.1 structure. 13990 * 13991 * Currently only RSASSA-PSS supported. The PKCS#1 v1.5 signature scheme had 13992 * no parameters. 13993 * 13994 * RSASSA-PSS-params ::= SEQUENCE { 13995 * hashAlgorithm [0] HashAlgorithm DEFAULT 13996 * sha1Identifier, 13997 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT 13998 * mgf1SHA1Identifier, 13999 * saltLength [2] INTEGER DEFAULT 20, 14000 * trailerField [3] INTEGER DEFAULT 1 14001 * } 14002 * 14003 * HashAlgorithm ::= AlgorithmIdentifier 14004 * 14005 * MaskGenAlgorithm ::= AlgorithmIdentifier 14006 * 14007 * AlgorithmIdentifer ::= SEQUENCE { 14008 * algorithm OBJECT IDENTIFIER, 14009 * parameters ANY DEFINED BY algorithm OPTIONAL 14010 * } 14011 * 14012 * @param oid The OID specifying the signature algorithm 14013 * @param obj The ASN.1 structure holding the parameters 14014 * @param fillDefaults Whether to use return default values where omitted 14015 * @return signature parameter object 14016 */ 14017var _readSignatureParameters = function(oid, obj, fillDefaults) { 14018 var params = {}; 14019 14020 if(oid !== oids['RSASSA-PSS']) { 14021 return params; 14022 } 14023 14024 if(fillDefaults) { 14025 params = { 14026 hash: { 14027 algorithmOid: oids['sha1'] 14028 }, 14029 mgf: { 14030 algorithmOid: oids['mgf1'], 14031 hash: { 14032 algorithmOid: oids['sha1'] 14033 } 14034 }, 14035 saltLength: 20 14036 }; 14037 } 14038 14039 var capture = {}; 14040 var errors = []; 14041 if(!asn1.validate(obj, rsassaPssParameterValidator, capture, errors)) { 14042 var error = new Error('Cannot read RSASSA-PSS parameter block.'); 14043 error.errors = errors; 14044 throw error; 14045 } 14046 14047 if(capture.hashOid !== undefined) { 14048 params.hash = params.hash || {}; 14049 params.hash.algorithmOid = asn1.derToOid(capture.hashOid); 14050 } 14051 14052 if(capture.maskGenOid !== undefined) { 14053 params.mgf = params.mgf || {}; 14054 params.mgf.algorithmOid = asn1.derToOid(capture.maskGenOid); 14055 params.mgf.hash = params.mgf.hash || {}; 14056 params.mgf.hash.algorithmOid = asn1.derToOid(capture.maskGenHashOid); 14057 } 14058 14059 if(capture.saltLength !== undefined) { 14060 params.saltLength = capture.saltLength.charCodeAt(0); 14061 } 14062 14063 return params; 14064}; 14065 14066/** 14067 * Converts an X.509 certificate from PEM format. 14068 *
14069 * Note: If the certificate is to be verified then compute hash should 14070 * be set to true. This will scan the TBSCertificate part of the ASN.1 14071 * object while it is converted so it doesn't need to be converted back 14072 * to ASN.1-DER-encoding later. 14073 * 14074 * @param pem the PEM-formatted certificate. 14075 * @param computeHash true to compute the hash for verification. 14076 * @param strict true to be strict when checking ASN.1 value lengths, false to 14077 * allow truncated values (default: true). 14078 * 14079 * @return the certificate. 14080 */ 14081pki.certificateFromPem = function(pem, computeHash, strict) { 14082 var msg = forge.pem.decode(pem)[0]; 14083 14084 if(msg.type !== 'CERTIFICATE' && 14085 msg.type !== 'X509 CERTIFICATE' && 14086 msg.type !== 'TRUSTED CERTIFICATE') { 14087 var error = new Error('Could not convert certificate from PEM; PEM header type ' + 14088 'is not "CERTIFICATE", "X509 CERTIFICATE", or "TRUSTED CERTIFICATE".'); 14089 error.headerType = msg.type; 14090 throw error; 14091 } 14092 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 14093 throw new Error('Could not convert certificate from PEM; PEM is encrypted.'); 14094 } 14095 14096 // convert DER to ASN.1 object 14097 var obj = asn1.fromDer(msg.body, strict); 14098 14099 return pki.certificateFromAsn1(obj, computeHash); 14100}; 14101 14102/** 14103 * Converts an X.509 certificate to PEM format. 14104 * 14105 * @param cert the certificate. 14106 * @param maxline the maximum characters per line, defaults to 64. 14107 * 14108 * @return the PEM-formatted certificate. 14109 */ 14110pki.certificateToPem = function(cert, maxline) { 14111 // convert to ASN.1, then DER, then PEM-encode 14112 var msg = { 14113 type: 'CERTIFICATE', 14114 body: asn1.toDer(pki.certificateToAsn1(cert)).getBytes() 14115 }; 14116 return forge.pem.encode(msg, {maxline: maxline}); 14117}; 14118 14119/** 14120 * Converts an RSA public key from PEM format. 14121 * 14122 * @param pem the PEM-formatted public key. 14123 * 14124 * @return the public key. 14125 */ 14126pki.publicKeyFromPem = function(pem) { 14127 var msg = forge.pem.decode(pem)[0]; 14128 14129 if(msg.type !== 'PUBLIC KEY' && msg.type !== 'RSA PUBLIC KEY') { 14130 var error = new Error('Could not convert public key from PEM; PEM header ' + 14131 'type is not "PUBLIC KEY" or "RSA PUBLIC KEY".'); 14132 error.headerType = msg.type; 14133 throw error; 14134 } 14135 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 14136 throw new Error('Could not convert public key from PEM; PEM is encrypted.'); 14137 } 14138 14139 // convert DER to ASN.1 object 14140 var obj = asn1.fromDer(msg.body); 14141 14142 return pki.publicKeyFromAsn1(obj); 14143}; 14144 14145/** 14146 * Converts an RSA public key to PEM format (using a SubjectPublicKeyInfo). 14147 * 14148 * @param key the public key. 14149 * @param maxline the maximum characters per line, defaults to 64. 14150 * 14151 * @return the PEM-formatted public key. 14152 */ 14153pki.publicKeyToPem = function(key, maxline) { 14154 // convert to ASN.1, then DER, then PEM-encode 14155 var msg = { 14156 type: 'PUBLIC KEY', 14157 body: asn1.toDer(pki.publicKeyToAsn1(key)).getBytes() 14158 }; 14159 return forge.pem.encode(msg, {maxline: maxline}); 14160}; 14161 14162/** 14163 * Converts an RSA public key to PEM format (using an RSAPublicKey). 14164 * 14165 * @param key the public key. 14166 * @param maxline the maximum characters per line, defaults to 64. 14167 * 14168 * @return the PEM-formatted public key. 14169 */ 14170pki.publicKeyToRSAPublicKeyPem = function(key, maxline) { 14171 // convert to ASN.1, then DER, then PEM-encode 14172 var msg = { 14173 type: 'RSA PUBLIC KEY', 14174 body: asn1.toDer(pki.publicKeyToRSAPublicKey(key)).getBytes() 14175 }; 14176 return forge.pem.encode(msg, {maxline: maxline}); 14177}; 14178 14179/** 14180 * Gets a fingerprint for the given public key. 14181 * 14182 * @param options the options to use. 14183 * [md] the message digest object to use (defaults to forge.md.sha1). 14184 * [type] the type of fingerprint, such as 'RSAPublicKey', 14185 * 'SubjectPublicKeyInfo' (defaults to 'RSAPublicKey'). 14186 * [encoding] an alternative output encoding, such as 'hex' 14187 * (defaults to none, outputs a byte buffer). 14188 * [delimiter] the delimiter to use between bytes for 'hex' encoded 14189 * output, eg: ':' (defaults to none). 14190 * 14191 * @return the fingerprint as a byte buffer or other encoding based on options. 14192 */ 14193pki.getPublicKeyFingerprint = function(key, options) { 14194 options = options || {}; 14195 var md = options.md || forge.md.sha1.create(); 14196 var type = options.type || 'RSAPublicKey'; 14197 14198 var bytes; 14199 switch(type) { 14200 case 'RSAPublicKey': 14201 bytes = asn1.toDer(pki.publicKeyToRSAPublicKey(key)).getBytes(); 14202 break; 14203 case 'SubjectPublicKeyInfo': 14204 bytes = asn1.toDer(pki.publicKeyToAsn1(key)).getBytes(); 14205 break; 14206 default: 14207 throw new Error('Unknown fingerprint type "' + options.type + '".'); 14208 } 14209 14210 // hash public key bytes 14211 md.start(); 14212 md.update(bytes); 14213 var digest = md.digest(); 14214 if(options.encoding === 'hex') { 14215 var hex = digest.toHex(); 14216 if(options.delimiter) { 14217 return hex.match(/.{2}/g).join(options.delimiter); 14218 } 14219 return hex; 14220 } else if(options.encoding === 'binary') { 14221 return digest.getBytes(); 14222 } else if(options.encoding) { 14223 throw new Error('Unknown encoding "' + options.encoding + '".'); 14224 } 14225 return digest; 14226}; 14227 14228/** 14229 * Converts a PKCS#10 certification request (CSR) from PEM format. 14230 *
14231 * Note: If the certification request is to be verified then compute hash 14232 * should be set to true. This will scan the CertificationRequestInfo part of 14233 * the ASN.1 object while it is converted so it doesn't need to be converted 14234 * back to ASN.1-DER-encoding later. 14235 * 14236 * @param pem the PEM-formatted certificate. 14237 * @param computeHash true to compute the hash for verification. 14238 * @param strict true to be strict when checking ASN.1 value lengths, false to 14239 * allow truncated values (default: true). 14240 * 14241 * @return the certification request (CSR). 14242 */ 14243pki.certificationRequestFromPem = function(pem, computeHash, strict) { 14244 var msg = forge.pem.decode(pem)[0]; 14245 14246 if(msg.type !== 'CERTIFICATE REQUEST') { 14247 var error = new Error('Could not convert certification request from PEM; ' + 14248 'PEM header type is not "CERTIFICATE REQUEST".'); 14249 error.headerType = msg.type; 14250 throw error; 14251 } 14252 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 14253 throw new Error('Could not convert certification request from PEM; ' + 14254 'PEM is encrypted.'); 14255 } 14256 14257 // convert DER to ASN.1 object 14258 var obj = asn1.fromDer(msg.body, strict); 14259 14260 return pki.certificationRequestFromAsn1(obj, computeHash); 14261}; 14262 14263/** 14264 * Converts a PKCS#10 certification request (CSR) to PEM format. 14265 * 14266 * @param csr the certification request. 14267 * @param maxline the maximum characters per line, defaults to 64. 14268 * 14269 * @return the PEM-formatted certification request. 14270 */ 14271pki.certificationRequestToPem = function(csr, maxline) { 14272 // convert to ASN.1, then DER, then PEM-encode 14273 var msg = { 14274 type: 'CERTIFICATE REQUEST', 14275 body: asn1.toDer(pki.certificationRequestToAsn1(csr)).getBytes() 14276 }; 14277 return forge.pem.encode(msg, {maxline: maxline}); 14278}; 14279 14280/** 14281 * Creates an empty X.509v3 RSA certificate. 14282 * 14283 * @return the certificate. 14284 */ 14285pki.createCertificate = function() { 14286 var cert = {}; 14287 cert.version = 0x02; 14288 cert.serialNumber = '00'; 14289 cert.signatureOid = null; 14290 cert.signature = null; 14291 cert.siginfo = {}; 14292 cert.siginfo.algorithmOid = null; 14293 cert.validity = {}; 14294 cert.validity.notBefore = new Date(); 14295 cert.validity.notAfter = new Date(); 14296 14297 cert.issuer = {}; 14298 cert.issuer.getField = function(sn) { 14299 return _getAttribute(cert.issuer, sn); 14300 }; 14301 cert.issuer.addField = function(attr) { 14302 _fillMissingFields([attr]); 14303 cert.issuer.attributes.push(attr); 14304 }; 14305 cert.issuer.attributes = []; 14306 cert.issuer.hash = null; 14307 14308 cert.subject = {}; 14309 cert.subject.getField = function(sn) { 14310 return _getAttribute(cert.subject, sn); 14311 }; 14312 cert.subject.addField = function(attr) { 14313 _fillMissingFields([attr]); 14314 cert.subject.attributes.push(attr); 14315 }; 14316 cert.subject.attributes = []; 14317 cert.subject.hash = null; 14318 14319 cert.extensions = []; 14320 cert.publicKey = null; 14321 cert.md = null; 14322 14323 /** 14324 * Sets the subject of this certificate. 14325 * 14326 * @param attrs the array of subject attributes to use. 14327 * @param uniqueId an optional a unique ID to use. 14328 */ 14329 cert.setSubject = function(attrs, uniqueId) { 14330 // set new attributes, clear hash 14331 _fillMissingFields(attrs); 14332 cert.subject.attributes = attrs; 14333 delete cert.subject.uniqueId; 14334 if(uniqueId) { 14335 cert.subject.uniqueId = uniqueId; 14336 } 14337 cert.subject.hash = null; 14338 }; 14339 14340 /** 14341 * Sets the issuer of this certificate. 14342 * 14343 * @param attrs the array of issuer attributes to use. 14344 * @param uniqueId an optional a unique ID to use. 14345 */ 14346 cert.setIssuer = function(attrs, uniqueId) { 14347 // set new attributes, clear hash 14348 _fillMissingFields(attrs); 14349 cert.issuer.attributes = attrs; 14350 delete cert.issuer.uniqueId; 14351 if(uniqueId) { 14352 cert.issuer.uniqueId = uniqueId; 14353 } 14354 cert.issuer.hash = null; 14355 }; 14356 14357 /** 14358 * Sets the extensions of this certificate. 14359 * 14360 * @param exts the array of extensions to use. 14361 */ 14362 cert.setExtensions = function(exts) { 14363 for(var i = 0; i < exts.length; ++i) { 14364 _fillMissingExtensionFields(exts[i], {cert: cert}); 14365 } 14366 // set new extensions 14367 cert.extensions = exts; 14368 }; 14369 14370 /** 14371 * Gets an extension by its name or id. 14372 * 14373 * @param options the name to use or an object with: 14374 * name the name to use. 14375 * id the id to use. 14376 * 14377 * @return the extension or null if not found. 14378 */ 14379 cert.getExtension = function(options) { 14380 if(typeof options === 'string') { 14381 options = {name: options}; 14382 } 14383 14384 var rval = null; 14385 var ext; 14386 for(var i = 0; rval === null && i < cert.extensions.length; ++i) { 14387 ext = cert.extensions[i]; 14388 if(options.id && ext.id === options.id) { 14389 rval = ext; 14390 } else if(options.name && ext.name === options.name) { 14391 rval = ext; 14392 } 14393 } 14394 return rval; 14395 }; 14396 14397 /** 14398 * Signs this certificate using the given private key. 14399 *
14400 * @param key the private key to sign with. 14401 * @param md the message digest object to use (defaults to forge.md.sha1). 14402 */ 14403 cert.sign = function(key, md) { 14404 // TODO: get signature OID from private key 14405 cert.md = md || forge.md.sha1.create(); 14406 var algorithmOid = oids[cert.md.algorithm + 'WithRSAEncryption']; 14407 if(!algorithmOid) { 14408 var error = new Error('Could not compute certificate digest. ' + 14409 'Unknown message digest algorithm OID.'); 14410 error.algorithm = cert.md.algorithm; 14411 throw error; 14412 } 14413 cert.signatureOid = cert.siginfo.algorithmOid = algorithmOid; 14414 14415 // get TBSCertificate, convert to DER 14416 cert.tbsCertificate = pki.getTBSCertificate(cert); 14417 var bytes = asn1.toDer(cert.tbsCertificate); 14418 14419 // digest and sign 14420 cert.md.update(bytes.getBytes()); 14421 cert.signature = key.sign(cert.md); 14422 }; 14423 14424 /** 14425 * Attempts verify the signature on the passed certificate using this 14426 * certificate's public key. 14427 * 14428 * @param child the certificate to verify. 14429 * 14430 * @return true if verified, false if not. 14431 */ 14432 cert.verify = function(child) { 14433 var rval = false; 14434 14435 if(!cert.issued(child)) { 14436 var issuer = child.issuer; 14437 var subject = cert.subject; 14438 var error = new Error('The parent certificate did not issue the given child ' + 14439 'certificate; the child certificate\'s issuer does not match the ' + 14440 'parent\'s subject.'); 14441 error.expectedIssuer = issuer.attributes; 14442 error.actualIssuer = subject.attributes; 14443 throw error; 14444 } 14445 14446 var md = child.md; 14447 if(md === null) { 14448 // check signature OID for supported signature types 14449 if(child.signatureOid in oids) { 14450 var oid = oids[child.signatureOid]; 14451 switch(oid) { 14452 case 'sha1WithRSAEncryption': 14453 md = forge.md.sha1.create(); 14454 break; 14455 case 'md5WithRSAEncryption': 14456 md = forge.md.md5.create(); 14457 break; 14458 case 'sha256WithRSAEncryption': 14459 md = forge.md.sha256.create(); 14460 break; 14461 case 'sha512WithRSAEncryption': 14462 md = forge.md.sha512.create(); 14463 break; 14464 case 'RSASSA-PSS': 14465 md = forge.md.sha256.create(); 14466 break; 14467 } 14468 } 14469 if(md === null) { 14470 var error = new Error('Could not compute certificate digest. ' + 14471 'Unknown signature OID.'); 14472 error.signatureOid = child.signatureOid; 14473 throw error; 14474 } 14475 14476 // produce DER formatted TBSCertificate and digest it 14477 var tbsCertificate = child.tbsCertificate || pki.getTBSCertificate(child); 14478 var bytes = asn1.toDer(tbsCertificate); 14479 md.update(bytes.getBytes()); 14480 } 14481 14482 if(md !== null) { 14483 var scheme; 14484 14485 switch(child.signatureOid) { 14486 case oids.sha1WithRSAEncryption: 14487 scheme = undefined; /* use PKCS#1 v1.5 padding scheme */ 14488 break; 14489 case oids['RSASSA-PSS']: 14490 var hash, mgf; 14491 14492 /* initialize mgf */ 14493 hash = oids[child.signatureParameters.mgf.hash.algorithmOid]; 14494 if(hash === undefined || forge.md[hash] === undefined) { 14495 var error = new Error('Unsupported MGF hash function.'); 14496 error.oid = child.signatureParameters.mgf.hash.algorithmOid; 14497 error.name = hash; 14498 throw error; 14499 } 14500 14501 mgf = oids[child.signatureParameters.mgf.algorithmOid]; 14502 if(mgf === undefined || forge.mgf[mgf] === undefined) { 14503 var error = new Error('Unsupported MGF function.'); 14504 error.oid = child.signatureParameters.mgf.algorithmOid; 14505 error.name = mgf; 14506 throw error; 14507 } 14508 14509 mgf = forge.mgf[mgf].create(forge.md[hash].create()); 14510 14511 /* initialize hash function */ 14512 hash = oids[child.signatureParameters.hash.algorithmOid]; 14513 if(hash === undefined || forge.md[hash] === undefined) { 14514 throw { 14515 message: 'Unsupported RSASSA-PSS hash function.', 14516 oid: child.signatureParameters.hash.algorithmOid, 14517 name: hash 14518 }; 14519 } 14520 14521 scheme = forge.pss.create(forge.md[hash].create(), mgf, 14522 child.signatureParameters.saltLength); 14523 break; 14524 } 14525 14526 // verify signature on cert using public key 14527 rval = cert.publicKey.verify( 14528 md.digest().getBytes(), child.signature, scheme); 14529 } 14530 14531 return rval; 14532 }; 14533 14534 /** 14535 * Returns true if this certificate's issuer matches the passed 14536 * certificate's subject. Note that no signature check is performed. 14537 * 14538 * @param parent the certificate to check. 14539 * 14540 * @return true if this certificate's issuer matches the passed certificate's 14541 * subject. 14542 */ 14543 cert.isIssuer = function(parent) { 14544 var rval = false;
14545 14546 var i = cert.issuer; 14547 var s = parent.subject; 14548 14549 // compare hashes if present 14550 if(i.hash && s.hash) { 14551 rval = (i.hash === s.hash); 14552 } else if(i.attributes.length === s.attributes.length) { 14553 // all attributes are the same so issuer matches subject 14554 rval = true; 14555 var iattr, sattr; 14556 for(var n = 0; rval && n < i.attributes.length; ++n) { 14557 iattr = i.attributes[n]; 14558 sattr = s.attributes[n]; 14559 if(iattr.type !== sattr.type || iattr.value !== sattr.value) { 14560 // attribute mismatch 14561 rval = false; 14562 } 14563 } 14564 } 14565 14566 return rval; 14567 }; 14568 14569 /** 14570 * Returns true if this certificate's subject matches the issuer of the 14571 * given certificate). Note that not signature check is performed. 14572 * 14573 * @param child the certificate to check. 14574 * 14575 * @return true if this certificate's subject matches the passed 14576 * certificate's issuer. 14577 */ 14578 cert.issued = function(child) { 14579 return child.isIssuer(cert); 14580 }; 14581 14582 /** 14583 * Generates the subjectKeyIdentifier for this certificate as byte buffer. 14584 * 14585 * @return the subjectKeyIdentifier for this certificate as byte buffer. 14586 */ 14587 cert.generateSubjectKeyIdentifier = function() { 14588 /* See: 4.2.1.2 section of the the RFC3280, keyIdentifier is either: 14589 14590 (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the 14591 value of the BIT STRING subjectPublicKey (excluding the tag, 14592 length, and number of unused bits). 14593 14594 (2) The keyIdentifier is composed of a four bit type field with 14595 the value 0100 followed by the least significant 60 bits of the 14596 SHA-1 hash of the value of the BIT STRING subjectPublicKey 14597 (excluding the tag, length, and number of unused bit string bits). 14598 */ 14599 14600 // skipping the tag, length, and number of unused bits is the same 14601 // as just using the RSAPublicKey (for RSA keys, which are the 14602 // only ones supported) 14603 return pki.getPublicKeyFingerprint(cert.publicKey, {type: 'RSAPublicKey'}); 14604 }; 14605 14606 /** 14607 * Verifies the subjectKeyIdentifier extension value for this certificate 14608 * against its public key. If no extension is found, false will be 14609 * returned. 14610 * 14611 * @return true if verified, false if not. 14612 */ 14613 cert.verifySubjectKeyIdentifier = function() { 14614 var oid = oids['subjectKeyIdentifier']; 14615 for(var i = 0; i < cert.extensions.length; ++i) { 14616 var ext = cert.extensions[i]; 14617 if(ext.id === oid) { 14618 var ski = cert.generateSubjectKeyIdentifier().getBytes(); 14619 return (forge.util.hexToBytes(ext.subjectKeyIdentifier) === ski); 14620 } 14621 } 14622 return false; 14623 }; 14624 14625 return cert; 14626}; 14627 14628/** 14629 * Converts an X.509v3 RSA certificate from an ASN.1 object. 14630 * 14631 * Note: If the certificate is to be verified then compute hash should 14632 * be set to true. There is currently no implementation for converting 14633 * a certificate back to ASN.1 so the TBSCertificate part of the ASN.1 14634 * object needs to be scanned before the cert object is created. 14635 * 14636 * @param obj the asn1 representation of an X.509v3 RSA certificate. 14637 * @param computeHash true to compute the hash for verification. 14638 * 14639 * @return the certificate. 14640 */ 14641pki.certificateFromAsn1 = function(obj, computeHash) { 14642 // validate certificate and capture data 14643 var capture = {}; 14644 var errors = []; 14645 if(!asn1.validate(obj, x509CertificateValidator, capture, errors)) { 14646 var error = new Error('Cannot read X.509 certificate. ' + 14647 'ASN.1 object is not an X509v3 Certificate.'); 14648 error.errors = errors; 14649 throw error; 14650 } 14651 14652 // ensure signature is not interpreted as an embedded ASN.1 object 14653 if(typeof capture.certSignature !== 'string') { 14654 var certSignature = '\x00'; 14655 for(var i = 0; i < capture.certSignature.length; ++i) { 14656 certSignature += asn1.toDer(capture.certSignature[i]).getBytes(); 14657 } 14658 capture.certSignature = certSignature; 14659 } 14660 14661 // get oid 14662 var oid = asn1.derToOid(capture.publicKeyOid); 14663 if(oid !== pki.oids['rsaEncryption']) { 14664 throw new Error('Cannot read public key. OID is not RSA.'); 14665 } 14666 14667 // create certificate 14668 var cert = pki.createCertificate(); 14669 cert.version = capture.certVersion ? 14670 capture.certVersion.charCodeAt(0) : 0; 14671 var serial = forge.util.createBuffer(capture.certSerialNumber); 14672 cert.serialNumber = serial.toHex(); 14673 cert.signatureOid = forge.asn1.derToOid(capture.certSignatureOid); 14674 cert.signatureParameters = _readSignatureParameters(
14675 cert.signatureOid, capture.certSignatureParams, true); 14676 cert.siginfo.algorithmOid = forge.asn1.derToOid(capture.certinfoSignatureOid); 14677 cert.siginfo.parameters = _readSignatureParameters(cert.siginfo.algorithmOid, 14678 capture.certinfoSignatureParams, false); 14679 // skip "unused bits" in signature value BITSTRING 14680 var signature = forge.util.createBuffer(capture.certSignature); 14681 ++signature.read; 14682 cert.signature = signature.getBytes(); 14683 14684 var validity = []; 14685 if(capture.certValidity1UTCTime !== undefined) { 14686 validity.push(asn1.utcTimeToDate(capture.certValidity1UTCTime)); 14687 } 14688 if(capture.certValidity2GeneralizedTime !== undefined) { 14689 validity.push(asn1.generalizedTimeToDate( 14690 capture.certValidity2GeneralizedTime)); 14691 } 14692 if(capture.certValidity3UTCTime !== undefined) { 14693 validity.push(asn1.utcTimeToDate(capture.certValidity3UTCTime)); 14694 } 14695 if(capture.certValidity4GeneralizedTime !== undefined) { 14696 validity.push(asn1.generalizedTimeToDate( 14697 capture.certValidity4GeneralizedTime)); 14698 } 14699 if(validity.length > 2) { 14700 throw new Error('Cannot read notBefore/notAfter validity times; more ' + 14701 'than two times were provided in the certificate.'); 14702 } 14703 if(validity.length < 2) { 14704 throw new Error('Cannot read notBefore/notAfter validity times; they ' + 14705 'were not provided as either UTCTime or GeneralizedTime.'); 14706 } 14707 cert.validity.notBefore = validity[0]; 14708 cert.validity.notAfter = validity[1]; 14709
14710 // keep TBSCertificate to preserve signature when exporting 14711 cert.tbsCertificate = capture.tbsCertificate; 14712 14713 if(computeHash) { 14714 // check signature OID for supported signature types 14715 cert.md = null; 14716 if(cert.signatureOid in oids) { 14717 var oid = oids[cert.signatureOid]; 14718 switch(oid) { 14719 case 'sha1WithRSAEncryption': 14720 cert.md = forge.md.sha1.create(); 14721 break; 14722 case 'md5WithRSAEncryption': 14723 cert.md = forge.md.md5.create(); 14724 break; 14725 case 'sha256WithRSAEncryption': 14726 cert.md = forge.md.sha256.create(); 14727 break; 14728 case 'sha512WithRSAEncryption': 14729 cert.md = forge.md.sha512.create(); 14730 break; 14731 case 'RSASSA-PSS': 14732 cert.md = forge.md.sha256.create(); 14733 break; 14734 } 14735 } 14736 if(cert.md === null) { 14737 var error = new Error('Could not compute certificate digest. ' + 14738 'Unknown signature OID.'); 14739 error.signatureOid = cert.signatureOid; 14740 throw error; 14741 } 14742 14743 // produce DER formatted TBSCertificate and digest it 14744 var bytes = asn1.toDer(cert.tbsCertificate); 14745 cert.md.update(bytes.getBytes()); 14746 } 14747 14748 // handle issuer, build issuer message digest 14749 var imd = forge.md.sha1.create(); 14750 cert.issuer.getField = function(sn) { 14751 return _getAttribute(cert.issuer, sn); 14752 }; 14753 cert.issuer.addField = function(attr) { 14754 _fillMissingFields([attr]); 14755 cert.issuer.attributes.push(attr); 14756 }; 14757 cert.issuer.attributes = pki.RDNAttributesAsArray(capture.certIssuer, imd); 14758 if(capture.certIssuerUniqueId) { 14759 cert.issuer.uniqueId = capture.certIssuerUniqueId; 14760 } 14761 cert.issuer.hash = imd.digest().toHex(); 14762 14763 // handle subject, build subject message digest 14764 var smd = forge.md.sha1.create(); 14765 cert.subject.getField = function(sn) { 14766 return _getAttribute(cert.subject, sn); 14767 }; 14768 cert.subject.addField = function(attr) { 14769 _fillMissingFields([attr]); 14770 cert.subject.attributes.push(attr); 14771 }; 14772 cert.subject.attributes = pki.RDNAttributesAsArray(capture.certSubject, smd); 14773 if(capture.certSubjectUniqueId) { 14774 cert.subject.uniqueId = capture.certSubjectUniqueId; 14775 } 14776 cert.subject.hash = smd.digest().toHex(); 14777 14778 // handle extensions 14779 if(capture.certExtensions) { 14780 cert.extensions = pki.certificateExtensionsFromAsn1(capture.certExtensions); 14781 } else { 14782 cert.extensions = []; 14783 } 14784 14785 // convert RSA public key from ASN.1 14786 cert.publicKey = pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo); 14787 14788 return cert; 14789}; 14790 14791/** 14792 * Converts an ASN.1 extensions object (with extension sequences as its 14793 * values) into an array of extension objects with types and values. 14794 * 14795 * Supported extensions: 14796 * 14797 * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } 14798 * KeyUsage ::= BIT STRING { 14799 * digitalSignature (0), 14800 * nonRepudiation (1), 14801 * keyEncipherment (2), 14802 * dataEncipherment (3), 14803 * keyAgreement (4), 14804 * keyCertSign (5), 14805 * cRLSign (6), 14806 * encipherOnly (7), 14807 * decipherOnly (8) 14808 * } 14809 * 14810 * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } 14811 * BasicConstraints ::= SEQUENCE { 14812 * cA BOOLEAN DEFAULT FALSE, 14813 * pathLenConstraint INTEGER (0..MAX) OPTIONAL 14814 * } 14815 * 14816 * subjectAltName EXTENSION ::= { 14817 * SYNTAX GeneralNames 14818 * IDENTIFIED BY id-ce-subjectAltName 14819 * } 14820 * 14821 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 14822 * 14823 * GeneralName ::= CHOICE { 14824 * otherName [0] INSTANCE OF OTHER-NAME, 14825 * rfc822Name [1] IA5String, 14826 * dNSName [2] IA5String, 14827 * x400Address [3] ORAddress, 14828 * directoryName [4] Name, 14829 * ediPartyName [5] EDIPartyName, 14830 * uniformResourceIdentifier [6] IA5String, 14831 * IPAddress [7] OCTET STRING, 14832 * registeredID [8] OBJECT IDENTIFIER 14833 * } 14834 * 14835 * OTHER-NAME ::= TYPE-IDENTIFIER 14836 * 14837 * EDIPartyName ::= SEQUENCE { 14838 * nameAssigner [0] DirectoryString {ub-name} OPTIONAL, 14839 * partyName [1] DirectoryString {ub-name} 14840 * } 14841 * 14842 * @param exts the extensions ASN.1 with extension sequences to parse. 14843 * 14844 * @return the array. 14845 */ 14846pki.certificateExtensionsFromAsn1 = function(exts) { 14847 var rval = []; 14848 for(var i = 0; i < exts.value.length; ++i) { 14849 // get extension sequence 14850 var extseq = exts.value[i]; 14851 for(var ei = 0; ei < extseq.value.length; ++ei) { 14852 rval.push(pki.certificateExtensionFromAsn1(extseq.value[ei])
14852); 14853 } 14854 } 14855 14856 return rval; 14857}; 14858 14859/** 14860 * Parses a single certificate extension from ASN.1. 14861 * 14862 * @param ext the extension in ASN.1 format. 14863 * 14864 * @return the parsed extension as an object. 14865 */ 14866pki.certificateExtensionFromAsn1 = function(ext) { 14867 // an extension has: 14868 // [0] extnID OBJECT IDENTIFIER 14869 // [1] critical BOOLEAN DEFAULT FALSE 14870 // [2] extnValue OCTET STRING 14871 var e = {}; 14872 e.id = asn1.derToOid(ext.value[0].value); 14873 e.critical = false; 14874 if(ext.value[1].type === asn1.Type.BOOLEAN) { 14875 e.critical = (ext.value[1].value.charCodeAt(0) !== 0x00); 14876 e.value = ext.value[2].value; 14877 } else { 14878 e.value = ext.value[1].value; 14879 } 14880 // if the oid is known, get its name 14881 if(e.id in oids) { 14882 e.name = oids[e.id]; 14883 14884 // handle key usage 14885 if(e.name === 'keyUsage') { 14886 // get value as BIT STRING 14887 var ev = asn1.fromDer(e.value); 14888 var b2 = 0x00; 14889 var b3 = 0x00; 14890 if(ev.value.length > 1) { 14891 // skip first byte, just indicates unused bits which 14892 // will be padded with 0s anyway 14893 // get bytes with flag bits 14894 b2 = ev.value.charCodeAt(1); 14895 b3 = ev.value.length > 2 ? ev.value.charCodeAt(2) : 0; 14896 } 14897 // set flags 14898 e.digitalSignature = (b2 & 0x80) === 0x80; 14899 e.nonRepudiation = (b2 & 0x40) === 0x40; 14900 e.keyEncipherment = (b2 & 0x20) === 0x20; 14901 e.dataEncipherment = (b2 & 0x10) === 0x10; 14902 e.keyAgreement = (b2 & 0x08) === 0x08; 14903 e.keyCertSign = (b2 & 0x04) === 0x04; 14904 e.cRLSign = (b2 & 0x02) === 0x02; 14905 e.encipherOnly = (b2 & 0x01) === 0x01; 14906 e.decipherOnly = (b3 & 0x80) === 0x80; 14907 } else if(e.name === 'basicConstraints') { 14908 // handle basic constraints 14909 // get value as SEQUENCE 14910 var ev = asn1.fromDer(e.value); 14911 // get cA BOOLEAN flag (defaults to false) 14912 if(ev.value.length > 0 && ev.value[0].type === asn1.Type.BOOLEAN) { 14913 e.cA = (ev.value[0].value.charCodeAt(0) !== 0x00); 14914 } else { 14915 e.cA = false; 14916 } 14917 // get path length constraint 14918 var value = null; 14919 if(ev.value.length > 0 && ev.value[0].type === asn1.Type.INTEGER) { 14920 value = ev.value[0].value; 14921 } else if(ev.value.length > 1) { 14922 value = ev.value[1].value; 14923 } 14924 if(value !== null) { 14925 e.pathLenConstraint = asn1.derToInteger(value); 14926 } 14927 } else if(e.name === 'extKeyUsage') { 14928 // handle extKeyUsage 14929 // value is a SEQUENCE of OIDs 14930 var ev = asn1.fromDer(e.value); 14931 for(var vi = 0; vi < ev.value.length; ++vi) { 14932 var oid = asn1.derToOid(ev.value[vi].value); 14933 if(oid in oids) { 14934 e[oids[oid]] = true; 14935 } else { 14936 e[oid] = true; 14937 } 14938 } 14939 } else if(e.name === 'nsCertType') { 14940 // handle nsCertType 14941 // get value as BIT STRING 14942 var ev = asn1.fromDer(e.value); 14943 var b2 = 0x00; 14944 if(ev.value.length > 1) { 14945 // skip first byte, just indicates unused bits which 14946 // will be padded with 0s anyway 14947 // get bytes with flag bits 14948 b2 = ev.value.charCodeAt(1); 14949 } 14950 // set flags 14951 e.client = (b2 & 0x80) === 0x80; 14952 e.server = (b2 & 0x40) === 0x40; 14953 e.email = (b2 & 0x20) === 0x20; 14954 e.objsign = (b2 & 0x10) === 0x10; 14955 e.reserved = (b2 & 0x08) === 0x08; 14956 e.sslCA = (b2 & 0x04) === 0x04; 14957 e.emailCA = (b2 & 0x02) === 0x02; 14958 e.objCA = (b2 & 0x01) === 0x01; 14959 } else if( 14960 e.name === 'subjectAltName' || 14961 e.name === 'issuerAltName') { 14962 // handle subjectAltName/issuerAltName 14963 e.altNames = []; 14964 14965 // ev is a SYNTAX SEQUENCE 14966 var gn; 14967 var ev = asn1.fromDer(e.value); 14968 for(var n = 0; n < ev.value.length; ++n) { 14969 // get GeneralName 14970 gn = ev.value[n]; 14971 14972 var altName = { 14973 type: gn.type, 14974 value: gn.value 14975 }; 14976 e.altNames.push(altName); 14977 14978 // Note: Support for types 1,2,6,7,8 14979 switch(gn.type) { 14980 // rfc822Name 14981 case 1: 14982 // dNSName 14983 case 2: 14984 // uniformResourceIdentifier (URI) 14985 case 6: 14986 break; 14987 // IPAddress 14988 case 7: 14989 // convert to IPv4/IPv6 string representation 14990 altName.ip = forge.util.bytesToIP(gn.value); 14991 break; 14992 // registeredID 14993 case 8: 14994 altName.oid = asn1.derToOid(gn.value); 14995 break; 14996 default: 14997 // unsupported 14998 } 14999 } 15000 } else if(e.name === 'subjectKeyIdentifier') { 15001 // value is an OCTETSTRING w/the hash of the key-type specific 15002 // public key structure (eg: RSAPublicKey) 15003 var ev = asn1.fromDer(e.value); 15004 e.subjectKeyIdentifier = forge.util.bytesToHex(ev.value); 15005 } 15006 } 15007 return e; 15008}; 15009 15010/** 15011 * Converts a PKCS#10 certification request (CSR) from an ASN.1 object. 15012 *
15013 * Note: If the certification request is to be verified then compute hash 15014 * should be set to true. There is currently no implementation for converting 15015 * a certificate back to ASN.1 so the CertificationRequestInfo part of the 15016 * ASN.1 object needs to be scanned before the csr object is created. 15017 * 15018 * @param obj the asn1 representation of a PKCS#10 certification request (CSR). 15019 * @param computeHash true to compute the hash for verification. 15020 * 15021 * @return the certification request (CSR). 15022 */ 15023pki.certificationRequestFromAsn1 = function(obj, computeHash) { 15024 // validate certification request and capture data 15025 var capture = {}; 15026 var errors = []; 15027 if(!asn1.validate(obj, certificationRequestValidator, capture, errors)) { 15028 var error = new Error('Cannot read PKCS#10 certificate request. ' + 15029 'ASN.1 object is not a PKCS#10 CertificationRequest.'); 15030 error.errors = errors; 15031 throw error; 15032 } 15033 15034 // ensure signature is not interpreted as an embedded ASN.1 object 15035 if(typeof capture.csrSignature !== 'string') { 15036 var csrSignature = '\x00'; 15037 for(var i = 0; i < capture.csrSignature.length; ++i) { 15038 csrSignature += asn1.toDer(capture.csrSignature[i]).getBytes(); 15039 } 15040 capture.csrSignature = csrSignature; 15041 } 15042 15043 // get oid 15044 var oid = asn1.derToOid(capture.publicKeyOid); 15045 if(oid !== pki.oids.rsaEncryption) { 15046 throw new Error('Cannot read public key. OID is not RSA.'); 15047 } 15048 15049 // create certification request 15050 var csr = pki.createCertificationRequest(); 15051 csr.version = capture.csrVersion ? capture.csrVersion.charCodeAt(0) : 0; 15052 csr.signatureOid = forge.asn1.derToOid(capture.csrSignatureOid); 15053 csr.signatureParameters = _readSignatureParameters( 15054 csr.signatureOid, capture.csrSignatureParams, true); 15055 csr.siginfo.algorithmOid = forge.asn1.derToOid(capture.csrSignatureOid); 15056 csr.siginfo.parameters = _readSignatureParameters( 15057 csr.siginfo.algorithmOid, capture.csrSignatureParams, false); 15058 // skip "unused bits" in signature value BITSTRING 15059 var signature = forge.util.createBuffer(capture.csrSignature); 15060 ++signature.read; 15061 csr.signature = signature.getBytes(); 15062 15063 // keep CertificationRequestInfo to preserve signature when exp
15063orting 15064 csr.certificationRequestInfo = capture.certificationRequestInfo; 15065 15066 if(computeHash) { 15067 // check signature OID for supported signature types 15068 csr.md = null; 15069 if(csr.signatureOid in oids) { 15070 var oid = oids[csr.signatureOid]; 15071 switch(oid) { 15072 case 'sha1WithRSAEncryption': 15073 csr.md = forge.md.sha1.create(); 15074 break; 15075 case 'md5WithRSAEncryption': 15076 csr.md = forge.md.md5.create(); 15077 break; 15078 case 'sha256WithRSAEncryption': 15079 csr.md = forge.md.sha256.create(); 15080 break; 15081 case 'sha512WithRSAEncryption': 15082 csr.md = forge.md.sha512.create(); 15083 break; 15084 case 'RSASSA-PSS': 15085 csr.md = forge.md.sha256.create(); 15086 break; 15087 } 15088 } 15089 if(csr.md === null) { 15090 var error = new Error('Could not compute certification request digest. ' + 15091 'Unknown signature OID.'); 15092 error.signatureOid = csr.signatureOid; 15093 throw error; 15094 } 15095 15096 // produce DER formatted CertificationRequestInfo and digest it 15097 var bytes = asn1.toDer(csr.certificationRequestInfo); 15098 csr.md.update(bytes.getBytes()); 15099 } 15100 15101 // handle subject, build subject message digest 15102 var smd = forge.md.sha1.create(); 15103 csr.subject.getField = function(sn) { 15104 return _getAttribute(csr.subject, sn); 15105 }; 15106 csr.subject.addField = function(attr) { 15107 _fillMissingFields([attr]); 15108 csr.subject.attributes.push(attr); 15109 }; 15110 csr.subject.attributes = pki.RDNAttributesAsArray( 15111 capture.certificationRequestInfoSubject, smd); 15112 csr.subject.hash = smd.digest().toHex(); 15113 15114 // convert RSA public key from ASN.1 15115 csr.publicKey = pki.publicKeyFromAsn1(capture.subjectPublicKeyInfo); 15116 15117 // convert attributes from ASN.1 15118 csr.getAttribute = function(sn) { 15119 return _getAttribute(csr, sn); 15120 }; 15121 csr.addAttribute = function(attr) { 15122 _fillMissingFields([attr]); 15123 csr.attributes.push(attr); 15124 }; 15125 csr.attributes = pki.CRIAttributesAsArray( 15126 capture.certificationRequestInfoAttributes || []); 15127 15128 return csr; 15129}; 15130 15131/** 15132 * Creates an empty certification request (a CSR or certificate signing 15133 * request). Once created, its public key and attributes can be set and then 15134 * it can be signed. 15135 * 15136 * @return the empty certification request. 15137 */ 15138pki.createCertificationRequest = function() { 15139 var csr = {}; 15140 csr.version = 0x00; 15141 csr.signatureOid = null; 15142 csr.signature = null; 15143 csr.siginfo = {}; 15144 csr.siginfo.algorithmOid = null; 15145 15146 csr.subject = {}; 15147 csr.subject.getField = function(sn) { 15148 return _getAttribute(csr.subject, sn); 15149 }; 15150 csr.subject.addField = function(attr) { 15151 _fillMissingFields([attr]); 15152 csr.subject.attributes.push(attr); 15153 }; 15154 csr.subject.attributes = []; 15155 csr.subject.hash = null; 15156 15157 csr.publicKey = null; 15158 csr.attributes = []; 15159 csr.getAttribute = function(sn) { 15160 return _getAttribute(csr, sn); 15161 }; 15162 csr.addAttribute = function(attr) { 15163 _fillMissingFields([attr]); 15164 csr.attributes.push(attr); 15165 }; 15166 csr.md = null; 15167 15168 /** 15169 * Sets the subject of this certification request. 15170 * 15171 * @param attrs the array of subject attributes to use. 15172 */ 15173 csr.setSubject = function(attrs) { 15174 // set new attributes 15175 _fillMissingFields(attrs); 15176 csr.subject.attributes = attrs; 15177 csr.subject.hash = null; 15178 }; 15179 15180 /** 15181 * Sets the attributes of this certification request. 15182 * 15183 * @param attrs the array of attributes to use. 15184 */ 15185 csr.setAttributes = function(attrs) { 15186 // set new attributes 15187 _fillMissingFields(attrs); 15188 csr.attributes = attrs; 15189 }; 15190 15191 /** 15192 * Signs this certification request using the given private key. 15193 * 15194 * @param key the private key to sign with. 15195 * @param md the message digest object to use (defaults to forge.md.sha1). 15196 */ 15197 csr.sign = function(key, md) { 15198 // TODO: get signature OID from private key 15199 csr.md = md || forge.md.sha1.create(); 15200 var algorithmOid = oids[csr.md.algorithm + 'WithRSAEncryption']; 15201 if(!algorithmOid) { 15202 var error = new Error('Could not compute certification request digest. ' + 15203 'Unknown message digest algorithm OID.'); 15204 error.algorithm = csr.md.algorithm; 15205 throw error; 15206 } 15207 csr.signatureOid = csr.siginfo.algorithmOid = algorithmOid; 15208 15209 // get CertificationRequestInfo, convert to DER 15210 csr.certificationRequestInfo = pki.getCertificationRequestInfo(csr); 15211 var bytes = asn1.toDer(csr.certificationRequestInfo); 15212 15213 // digest and sign 15214 csr.md.update(bytes.getBytes()); 15215 csr.signature = key.sign(csr.md); 15216 }; 15217 15218 /** 15219 * Attempts verify the signature on the passed certification request using 15220 * its public key. 15221 *
15222 * A CSR that has been exported to a file in PEM format can be verified using 15223 * OpenSSL using this command: 15224 * 15225 * openssl req -in <the-csr-pem-file> -verify -noout -text 15226 * 15227 * @return true if verified, false if not. 15228 */ 15229 csr.verify = function() { 15230 var rval = false; 15231 15232 var md = csr.md; 15233 if(md === null) { 15234 // check signature OID for supported signature types 15235 if(csr.signatureOid in oids) { 15236 // TODO: create DRY `OID to md` function 15237 var oid = oids[csr.signatureOid]; 15238 switch(oid) { 15239 case 'sha1WithRSAEncryption': 15240 md = forge.md.sha1.create(); 15241 break; 15242 case 'md5WithRSAEncryption': 15243 md = forge.md.md5.create(); 15244 break; 15245 case 'sha256WithRSAEncryption': 15246 md = forge.md.sha256.create(); 15247 break; 15248 case 'sha512WithRSAEncryption': 15249 md = forge.md.sha512.create(); 15250 break; 15251 case 'RSASSA-PSS': 15252 md = forge.md.sha256.create(); 15253 break; 15254 } 15255 } 15256 if(md === null) { 15257 var error = new Error('Could not compute certification request digest. ' + 15258 'Unknown signature OID.'); 15259 error.signatureOid = csr.signatureOid; 15260 throw error; 15261 } 15262 15263 // produce DER formatted CertificationRequestInfo and digest it 15264 var cri = csr.certificationRequestInfo || 15265 pki.getCertificationRequestInfo(csr); 15266 var bytes = asn1.toDer(cri); 15267 md.update(bytes.getBytes()); 15268 } 15269 15270 if(md !== null) { 15271 var scheme; 15272 15273 switch(csr.signatureOid) { 15274 case oids.sha1WithRSAEncryption: 15275 /* use PKCS#1 v1.5 padding scheme */ 15276 break; 15277 case oids['RSASSA-PSS']: 15278 var hash, mgf; 15279 15280 /* initialize mgf */ 15281 hash = oids[csr.signatureParameters.mgf.hash.algorithmOid]; 15282 if(hash === undefined || forge.md[hash] === undefined) { 15283 var error = new Error('Unsupported MGF hash function.'); 15284 error.oid = csr.signatureParameters.mgf.hash.algorithmOid; 15285 error.name = hash; 15286 throw error; 15287 } 15288 15289 mgf = oids[csr.signatureParameters.mgf.algorithmOid]; 15290 if(mgf === undefined || forge.mgf[mgf] === undefined) { 15291 var error = new Error('Unsupported MGF function.'); 15292 error.oid = csr.signatureParameters.mgf.algorithmOid; 15293 error.name = mgf; 15294 throw error; 15295 } 15296 15297 mgf = forge.mgf[mgf].create(forge.md[hash].create()); 15298 15299 /* initialize hash function */ 15300 hash = oids[csr.signatureParameters.hash.algorithmOid]; 15301 if(hash === undefined || forge.md[hash] === undefined) { 15302 var error = new Error('Unsupported RSASSA-PSS hash function.'); 15303 error.oid = csr.signatureParameters.hash.algorithmOid; 15304 error.name = hash; 15305 throw error; 15306 } 15307 15308 scheme = forge.pss.create(forge.md[hash].create(), mgf, 15309 csr.signatureParameters.saltLength); 15310 break; 15311 } 15312 15313 // verify signature on csr using its public key 15314 rval = csr.publicKey.verify( 15315 md.digest().getBytes(), csr.signature, scheme); 15316 } 15317 15318 return rval; 15319 }; 15320 15321 return csr; 15322}; 15323 15324/** 15325 * Converts an X.509 subject or issuer to an ASN.1 RDNSequence. 15326 * 15327 * @param obj the subject or issuer (distinguished name). 15328 * 15329 * @return the ASN.1 RDNSequence. 15330 */ 15331function _dnToAsn1(obj) { 15332 // create an empty RDNSequence 15333 var rval = asn1.create( 15334 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 15335 15336 // iterate over attributes 15337 var attr, set; 15338 var attrs = obj.attributes; 15339 for(var i = 0; i < attrs.length; ++i) { 15340 attr = attrs[i]; 15341 var value = attr.value; 15342 15343 // reuse tag class for attribute value if available 15344 var valueTagClass = asn1.Type.PRINTABLESTRING; 15345 if('valueTagClass' in attr) { 15346 valueTagClass = attr.valueTagClass; 15347 15348 if(valueTagClass === asn1.Type.UTF8) { 15349 value = forge.util.encodeUtf8(value); 15350 } 15351 // FIXME: handle more encodings 15352 } 15353 15354 // create a RelativeDistinguishedName set 15355 // each value in the set is an AttributeTypeAndValue first 15356 // containing the type (an OID) and second the value 15357 set = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [ 15358 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15359 // AttributeType 15360 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 15361 asn1.oidToDer(attr.type).getBytes()), 15362 // AttributeValue 15363 asn1.create(asn1.Class.UNIVERSAL, valueTagClass, false, value) 15364 ]) 15365 ]); 15366 rval.value.push(set); 15367 } 15368 15369 return rval; 15370} 15371 15372/** 15373 * Gets all printable attributes (typically of an issuer or subject) in a 15374 * simplified JSON format for display. 15375 * 15376 * @param attrs the attributes. 15377 * 15378 * @return the JSON for display. 15379 */ 15380function _getAttributesAsJson(attrs) { 15381 var rval = {}; 15382 for(var i = 0; i < attrs.length; ++i) { 15383 var attr = attrs[i]; 15384 if(attr.shortName && ( 15385 attr.valueTagClass === asn1.Type.UTF8 || 15386 attr.valueTagClass === asn1.Type.PRINTABLESTRING || 15387 attr.valueTagClass === asn1.Type.IA5STRING)) { 15388 var value = attr.value; 15389 if(attr.valueTagClass === asn1.Type.UTF8) { 15390 value = forge.util.encodeUtf8(attr.value); 15391 } 15392 if(!(attr.shortName in rval)) { 15393 rval[attr.shortName] = value; 15394 } else if(forge.util.isArray(rval[attr.shortName])) { 15395 rval[attr.shortName].push(value); 15396 } else { 15397 rval[attr.shortName] = [rval[attr.shortName], value]; 15398 } 15399 } 15400 } 15401 return rval; 15402} 15403 15404/** 15405 * Fills in missing fields in attributes. 15406 * 15407 * @param attrs the attributes to fill missing fields in. 15408 */ 15409function _fillMissingFields(attrs) { 15410 var attr; 15411 for(var i = 0; i < attrs.length; ++i) { 15412 attr = attrs[i]; 15413 15414 // populate missing name 15415 if(typeof attr.name === 'undefined') { 15416 if(attr.type && attr.type in pki.oids) { 15417 attr.name = pki.oids[attr.type]; 15418 }
15418 else if(attr.shortName && attr.shortName in _shortNames) { 15419 attr.name = pki.oids[_shortNames[attr.shortName]]; 15420 } 15421 } 15422 15423 // populate missing type (OID) 15424 if(typeof attr.type === 'undefined') { 15425 if(attr.name && attr.name in pki.oids) { 15426 attr.type = pki.oids[attr.name]; 15427 } else { 15428 var error = new Error('Attribute type not specified.'); 15429 error.attribute = attr; 15430 throw error; 15431 } 15432 } 15433 15434 // populate missing shortname 15435 if(typeof attr.shortName === 'undefined') { 15436 if(attr.name && attr.name in _shortNames) { 15437 attr.shortName = _shortNames[attr.name]; 15438 } 15439 } 15440 15441 // convert extensions to value 15442 if(attr.type === oids.extensionRequest) { 15443 attr.valueConstructed = true; 15444 attr.valueTagClass = asn1.Type.SEQUENCE; 15445 if(!attr.value && attr.extensions) { 15446 attr.value = []; 15447 for(var ei = 0; ei < attr.extensions.length; ++ei) { 15448 attr.value.push(pki.certificateExtensionToAsn1( 15449 _fillMissingExtensionFields(attr.extensions[ei]))); 15450 } 15451 } 15452 } 15453 15454 if(typeof attr.value === 'undefined') { 15455 var error = new Error('Attribute value not specified.'); 15456 error.attribute = attr; 15457 throw error; 15458 } 15459 } 15460} 15461 15462/** 15463 * Fills in missing fields in certificate extensions. 15464 * 15465 * @param e the extension. 15466 * @param [options] the options to use. 15467 * [cert] the certificate the extensions are for. 15468 * 15469 * @return the extension. 15470 */ 15471function _fillMissingExtensionFields(e, options) { 15472 options = options || {}; 15473 15474 // populate missing name 15475 if(typeof e.name === 'undefined') { 15476 if(e.id && e.id in pki.oids) { 15477 e.name = pki.oids[e.id]; 15478 } 15479 } 15480 15481 // populate missing id 15482 if(typeof e.id === 'undefined') { 15483 if(e.name && e.name in pki.oids) { 15484 e.id = pki.oids[e.name]; 15485 } else { 15486 var error = new Error('Extension ID not specified.'); 15487 error.extension = e; 15488 throw error; 15489 } 15490 } 15491 15492 if(typeof e.value !== 'undefined') { 15493 return e; 15494 } 15495 15496 // handle missing value: 15497 15498 // value is a BIT STRING 15499 if(e.name === 'keyUsage') { 15500 // build flags 15501 var unused = 0; 15502 var b2 = 0x00; 15503 var b3 = 0x00; 15504 if(e.digitalSignature) { 15505 b2 |= 0x80; 15506 unused = 7; 15507 } 15508 if(e.nonRepudiation) { 15509 b2 |= 0x40; 15510 unused = 6; 15511 } 15512 if(e.keyEncipherment) { 15513 b2 |= 0x20; 15514 unused = 5; 15515 } 15516 if(e.dataEncipherment) { 15517 b2 |= 0x10; 15518 unused = 4; 15519 } 15520 if(e.keyAgreement) { 15521 b2 |= 0x08; 15522 unused = 3; 15523 } 15524 if(e.keyCertSign) { 15525 b2 |= 0x04; 15526 unused = 2; 15527 } 15528 if(e.cRLSign) { 15529 b2 |= 0x02; 15530 unused = 1; 15531 } 15532 if(e.encipherOnly) { 15533 b2 |= 0x01; 15534 unused = 0; 15535 } 15536 if(e.decipherOnly) { 15537 b3 |= 0x80; 15538 unused = 7; 15539 } 15540 15541 // create bit string 15542 var value = String.fromCharCode(unused); 15543 if(b3 !== 0) { 15544 value += String.fromCharCode(b2) + String.fromCharCode(b3); 15545 } else if(b2 !== 0) { 15546 value += String.fromCharCode(b2); 15547 } 15548 e.value = asn1.create( 15549 asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, value); 15550 } else if(e.name === 'basicConstraints') { 15551 // basicConstraints is a SEQUENCE 15552 e.value = asn1.create( 15553 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 15554 // cA BOOLEAN flag defaults to false 15555 if(e.cA) { 15556 e.value.value.push(asn1.create( 15557 asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false, 15558 String.fromCharCode(0xFF))); 15559 } 15560 if('pathLenConstraint' in e) { 15561 e.value.value.push(asn1.create( 15562 asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 15563 asn1.integerToDer(e.pathLenConstraint).getBytes())); 15564 } 15565 } else if(e.name === 'extKeyUsage') { 15566 // extKeyUsage is a SEQUENCE of OIDs 15567 e.value = asn1.create( 15568 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 15569 var seq = e.value.value; 15570 for(var key in e) { 15571 if(e[key] !== true) { 15572 continue; 15573 } 15574 // key is name in OID map 15575 if(key in oids) { 15576 seq.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, 15577 false, asn1.oidToDer(oids[key]).getBytes())); 15578 } else if(key.indexOf('.') !== -1) { 15579 // assume key is an OID 15580 seq.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, 15581 false, asn1.oidToDer(key).getBytes())); 15582 } 15583 } 15584 } else if(e.name === 'nsCertType') { 15585 // nsCertType is a BIT STRING 15586 // build flags 15587 var unused = 0; 15588 var b2 = 0x00; 15589 15590 if(e.client) { 15591 b2 |= 0x80; 15592 unused = 7; 15593 } 15594 if(e.server) { 15595 b2 |= 0x40; 15596 unused = 6; 15597 } 15598 if(e.email) { 15599 b2 |= 0x20; 15600 unused = 5; 15601 } 15602 if(e.objsign) { 15603 b2 |= 0x10; 15604 unused = 4; 15605 } 15606 if(e.reserved) { 15607 b2 |= 0x08; 15608 unused = 3; 15609 } 15610 if(e.sslCA) { 15611 b2 |= 0x04; 15612 unused = 2; 15613 } 15614 if(e.emailCA) { 15615 b2 |= 0x02; 15616 unused = 1; 15617 } 15618 if(e.objCA) { 15619 b2 |= 0x01; 15620 unused = 0; 15621 } 15622 15623 // create bit string
15624 var value = String.fromCharCode(unused); 15625 if(b2 !== 0) { 15626 value += String.fromCharCode(b2); 15627 } 15628 e.value = asn1.create( 15629 asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, value); 15630 } else if(e.name === 'subjectAltName' || e.name === 'issuerAltName') { 15631 // SYNTAX SEQUENCE 15632 e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 15633 15634 var altName; 15635 for(var n = 0; n < e.altNames.length; ++n) { 15636 altName = e.altNames[n]; 15637 var value = altName.value; 15638 // handle IP 15639 if(altName.type === 7 && altName.ip) { 15640 value = forge.util.bytesFromIP(altName.ip); 15641 if(value === null) { 15642 var error = new Error( 15643 'Extension "ip" value is not a valid IPv4 or IPv6 address.'); 15644 error.extension = e; 15645 throw error; 15646 } 15647 } else if(altName.type === 8) { 15648 // handle OID 15649 if(altName.oid) { 15650 value = asn1.oidToDer(asn1.oidToDer(altName.oid)); 15651 } else { 15652 // deprecated ... convert value to OID 15653 value = asn1.oidToDer(value); 15654 } 15655 } 15656 e.value.value.push(asn1.create( 15657 asn1.Class.CONTEXT_SPECIFIC, altName.type, false, 15658 value)); 15659 } 15660 } else if(e.name === 'subjectKeyIdentifier' && options.cert) { 15661 var ski = options.cert.generateSubjectKeyIdentifier(); 15662 e.subjectKeyIdentifier = ski.toHex(); 15663 // OCTETSTRING w/digest 15664 e.value = asn1.create( 15665 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, ski.getBytes()); 15666 } else if(e.name === 'authorityKeyIdentifier' && options.cert) { 15667 // SYNTAX SEQUENCE 15668 e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 15669 var seq = e.value.value; 15670 15671 if(e.keyIdentifier) { 15672 var keyIdentifier = (e.keyIdentifier === true ? 15673 options.cert.generateSubjectKeyIdentifier().getBytes() : 15674 e.keyIdentifier); 15675 seq.push( 15676 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, false, keyIdentifier)); 15677 } 15678 15679 if(e.authorityCertIssuer) { 15680 var authorityCertIssuer = [ 15681 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 4, true, [ 15682 _dnToAsn1(e.authorityCertIssuer === true ? 15683 options.cert.issuer : e.authorityCertIssuer) 15684 ]) 15685 ]; 15686 seq.push( 15687 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, authorityCertIssuer)); 15688 } 15689 15690 if(e.serialNumber) { 15691 var serialNumber = forge.util.hexToBytes(e.serialNumber === true ? 15692 options.cert.serialNumber : e.serialNumber); 15693 seq.push( 15694 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, false, serialNumber)); 15695 } 15696 } else if (e.name === 'cRLDistributionPoints') { 15697 e.value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 15698 var seq = e.value.value; 15699 15700 // Create sub SEQUENCE of DistributionPointName 15701 var subSeq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 15702 15703 // Create fullName CHOICE 15704 var fullNameGeneralNames = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, []); 15705 var altName; 15706 for(var n = 0; n < e.altNames.length; ++n) { 15707 altName = e.altNames[n]; 15708 var value = altName.value; 15709 // handle IP 15710 if(altName.type === 7 && altName.ip) { 15711 value = forge.util.bytesFromIP(altName.ip); 15712 if(value === null) { 15713 var error = new Error( 15714 'Extension "ip" value is not a valid IPv4 or IPv6 address.'); 15715 error.extension = e; 15716 throw error; 15717 } 15718 } else if(altName.type === 8) { 15719 // handle OID 15720 if(altName.oid) { 15721 value = asn1.oidToDer(asn1.oidToDer(altName.oid)); 15722 } else { 15723 // deprecated ... convert value to OID 15724 value = asn1.oidToDer(value); 15725 } 15726 } 15727 fullNameGeneralNames.value.push(asn1.create( 15728 asn1.Class.CONTEXT_SPECIFIC, altName.type, false, 15729 value)); 15730 } 15731 15732 // Add to the parent SEQUENCE 15733 subSeq.value.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [fullNameGeneralNames])); 15734 seq.push(subSeq); 15735 } 15736 15737 // ensure value has been defined by now 15738 if(typeof e.value === 'undefined') { 15739 var error = new Error('Extension value not specified.'); 15740 error.extension = e; 15741 throw error; 15742 } 15743 15744 return e; 15745} 15746
15747/** 15748 * Convert signature parameters object to ASN.1 15749 * 15750 * @param {String} oid Signature algorithm OID 15751 * @param params The signature parametrs object 15752 * @return ASN.1 object representing signature parameters 15753 */ 15754function _signatureParametersToAsn1(oid, params) { 15755 switch(oid) { 15756 case oids['RSASSA-PSS']: 15757 var parts = []; 15758 15759 if(params.hash.algorithmOid !== undefined) { 15760 parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 15761 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15762 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 15763 asn1.oidToDer(params.hash.algorithmOid).getBytes()), 15764 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 15765 ]) 15766 ])); 15767 } 15768 15769 if(params.mgf.algorithmOid !== undefined) { 15770 parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [ 15771 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15772 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 15773 asn1.oidToDer(params.mgf.algorithmOid).getBytes()), 15774 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15775 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 15776 asn1.oidToDer(params.mgf.hash.algorithmOid).getBytes()), 15777 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 15778 ]) 15779 ]) 15780 ])); 15781 } 15782 15783 if(params.saltLength !== undefined) { 15784 parts.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, true, [ 15785 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 15786 asn1.integerToDer(params.saltLength).getBytes()) 15787 ])); 15788 } 15789 15790 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, parts); 15791 15792 default: 15793 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, ''); 15794 } 15795} 15796 15797/** 15798 * Converts a certification request's attributes to an ASN.1 set of 15799 * CRIAttributes. 15800 * 15801 * @param csr certification request. 15802 * 15803 * @return the ASN.1 set of CRIAttributes. 15804 */ 15805function _CRIAttributesToAsn1(csr) { 15806 // create an empty context-specific container 15807 var rval = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, []); 15808 15809 // no attributes, return empty container 15810 if(csr.attributes.length === 0) { 15811 return rval; 15812 } 15813 15814 // each attribute has a sequence with a type and a set of values 15815 var attrs = csr.attributes; 15816 for(var i = 0; i < attrs.length; ++i) { 15817 var attr = attrs[i]; 15818 var value = attr.value; 15819 15820 // reuse tag class for attribute value if available 15821 var valueTagClass = asn1.Type.UTF8; 15822 if('valueTagClass' in attr) { 15823 valueTagClass = attr.valueTagClass; 15824 } 15825 if(valueTagClass === asn1.Type.UTF8) { 15826 value = forge.util.encodeUtf8(value); 15827 } 15828 var valueConstructed = false; 15829 if('valueConstructed' in attr) { 15830 valueConstructed = attr.valueConstructed; 15831 } 15832 // FIXME: handle more encodings 15833 15834 // create a RelativeDistinguishedName set 15835 // each value in the set is an AttributeTypeAndValue first 15836 // containing the type (an OID) and second the value 15837 var seq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15838 // AttributeType 15839 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 15840 asn1.oidToDer(attr.type).getBytes()), 15841 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [ 15842 // AttributeValue 15843 asn1.create( 15844 asn1.Class.UNIVERSAL, valueTagClass, valueConstructed, value) 15845 ]) 15846 ]); 15847 rval.value.push(seq); 15848 } 15849 15850 return rval; 15851} 15852 15853/** 15854 * Gets the ASN.1 TBSCertificate part of an X.509v3 certificate. 15855 * 15856 * @param cert the certificate. 15857 * 15858 * @return the asn1 TBSCertificate. 15859 */ 15860pki.getTBSCertificate = function(cert) { 15861 // TBSCertificate 15862 var tbs = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15863 // version 15864 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 15865 // integer 15866 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 15867 asn1.integerToDer(cert.version).getBytes()) 15868 ]), 15869 // serialNumber 15870 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 15871 forge.util.hexToBytes(cert.serialNumber)), 15872 // signature 15873 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15874 // algorithm 15875 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 15876 asn1.oidToDer(cert.siginfo.algorithmOid).getBytes()), 15877 // parameters 15878 _signatureParametersToAsn1( 15879 cert.siginfo.algorithmOid, cert.siginfo.parameters) 15880 ]), 15881 // issuer 15882 _dnToAsn1(cert.issuer), 15883 // validity 15884 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15885 // notBefore 15886 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.UTCTIME, false, 15887 asn1.dateToUtcTime(cert.validity.notBefore)), 15888 // notAfter 15889 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.UTCTIME, false, 15890 asn1.dateToUtcTime(cert.validity.notAfter)) 15891 ]), 15892 // subject 15893 _dnToAsn1(cert.subject), 15894 // SubjectPublicKeyInfo 15895 pki.publicKeyToAsn1(cert.publicKey) 15896 ]); 15897 15898 if(cert.issuer.uniqueId) { 15899 // issuerUniqueID (optional) 15900 tbs.value.push( 15901 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, [ 15902 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, 15903 String.fromCharCode(0x00) + 15904 cert.issuer.uniqueId 15905 ) 15906 ]) 15907 ); 15908 } 15909 if(cert.subject.uniqueId) { 15910 // subjectUniqueID (optional) 15911 tbs.value.push( 15912 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, true, [ 15913 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, 15914 String.fromCharCode(0x00) + 15915 cert.subject.uniqueId 15916 ) 15917 ]) 15918 ); 15919 } 15920 15921 if(cert.extensions.length > 0) { 15922 // extensions (optional) 15923 tbs.value.push(pki.certificateExtensionsToAsn1(cert.extensions)); 15924 } 15925 15926 return tbs; 15927}; 15928 15929/** 15930 * Gets the ASN.1 CertificationRequestInfo part of a 15931 * PKCS#10 CertificationRequest. 15932 * 15933 * @param csr the certification request. 15934 * 15935 * @return the asn1 CertificationRequestInfo. 15936 */ 15937pki.getCertificationRequestInfo = function(csr) { 15938 // CertificationRequestInfo 15939 var cri = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15940 // version 15941 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 15942 asn1.integerToDer(csr.version).getBytes()), 15943 // subject 15944 _dnToAsn1(csr.subject), 15945 // SubjectPublicKeyInfo 15946 pki.publicKeyToAsn1(csr.publicKey), 15947 // attributes 15948 _CRIAttributesToAsn1(csr) 15949 ]); 15950 15951 return cri; 15952}; 15953 15954/** 15955 * Converts a DistinguishedName (subject or issuer) to an ASN.1 object. 15956 * 15957 * @param dn the DistinguishedName. 15958 * 15959 * @return the asn1 representation of a DistinguishedName. 15960 */ 15961pki.distinguishedNameToAsn1 = function(dn) { 15962 return _dnToAsn1(dn); 15963}; 15964 15965/** 15966 * Converts an X.509v3 RSA certificate to an ASN.1 object. 15967 * 15968 * @param cert the certificate. 15969 * 15970 * @return the asn1 representation of an X.509v3 RSA certificate. 15971 */ 15972pki.certificateToAsn1 = function(cert) { 15973 // prefer cached TBSCertificate over generating one 15974 var tbsCertificate = cert.tbsCertificate || pki.getTBSCertificate(cert); 15975 15976 // Certificate 15977 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15978 // TBSCertificate 15979 tbsCertificate, 15980 // AlgorithmIdentifier (signature algorithm) 15981 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 15982 // algorithm 15983 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 15984 asn1.oidToDer(cert.signatureOid).getBytes()), 15985 // parameters 15986 _signatureParametersToAsn1(cert.signatureOid, cert.signatureParameters) 15987 ]), 15988 // SignatureValue 15989 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, 15990 String.fromCharCode(0x00) + cert.signature) 15991 ]); 15992}; 15993 15994/** 15995 * Converts X.509v3 certificate extensions to ASN.1. 15996 * 15997 * @param exts the extensions to convert. 15998 * 15999 * @return the extensions in ASN.1 format. 16000 */ 16001pki.certificateExtensionsToAsn1 = function(exts) { 16002 // create top-level extension container 16003 var rval = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 3, true, []); 16004 16005 // create extension sequence (stores a sequence for each extension) 16006 var seq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 16007 rval.value.push(seq); 16008 16009 for(var i = 0; i < exts.length; ++i) { 16010 seq.value.push(pki.certificateExtensionToAsn1(exts[i])); 16011 } 16012 16013 return rval; 16014}; 16015 16016/** 16017 * Converts a single certificate extension to ASN.1. 16018 * 16019 * @param ext the extension to convert. 16020 * 16021 * @return the extension in ASN.1 format. 16022 */ 16023pki.certificateExtensionToAsn1 = function(ext) { 16024 // create a sequence for each extension 16025 var extseq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []); 16026 16027 // extnID (OID) 16028 extseq.value.push(asn1.create( 16029 asn1.Class.UNIVERSAL, asn1.Type.OID, false, 16030 asn1.oidToDer(ext.id).getBytes())); 16031 16032 // critical defaults to false 16033 if(ext.critical) { 16034 // critical BOOLEAN DEFAULT FALSE 16035 extseq.value.push(asn1.create( 16036 asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false, 16037 String.fromCharCode(0xFF))); 16038 } 16039 16040 var value = ext.value; 16041 if(typeof ext.value !== 'string') { 16042 // value is asn.1 16043 value = asn1.toDer(value).getBytes(); 16044 } 16045 16046 // extnValue (OCTET STRING) 16047 extseq.value.push(asn1.create( 16048 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, value)); 16049 16050 return extseq; 16051}; 16052 16053/** 16054 * Converts a PKCS#10 certification request to an ASN.1 object. 16055 * 16056 * @param csr the certification request. 16057 * 16058 * @return the asn1 representation of a certification request. 16059 */ 16060pki.certificationRequestToAsn1 = function(csr) { 16061 // prefer cached CertificationRequestInfo over generating one 16062 var cri = csr.certificationRequestInfo || 16063 pki.getCertificationRequestInfo(csr); 16064 16065 // Certificate 16066 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 16067 // CertificationRequestInfo 16068 cri, 16069 // AlgorithmIdentifier (signature algorithm) 16070 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 16071 // algorithm 16072 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 16073 asn1.oidToDer(csr.signatureOid).getBytes()), 16074 // parameters 16075 _signatureParametersToAsn1(csr.signatureOid, csr.signatureParameters) 16076 ]), 16077 // signature 16078 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BITSTRING, false, 16079 String.fromCharCode(0x00) + csr.signature) 16080 ]); 16081}; 16082 16083/** 16084 * Creates a CA store. 16085 * 16086 * @param certs an optional array of certificate objects or PEM-formatted 16087 * certificate strings to add to the CA store. 16088 * 16089 * @return the CA store. 16090 */ 16091pki.createCaStore = function(certs) { 16092 // create CA store 16093 var caStore = { 16094 // stored certificates 16095 certs: {} 16096 }; 16097 16098 /** 16099 * Gets the certificate that issued the passed certificate or its 16100 * 'parent'. 16101 * 16102 * @param cert the certificate to get the parent for. 16103 * 16104 * @return the parent certificate or null if none was found. 16105 */ 16106 caStore.getIssuer = function(cert) { 16107 var rval = getBySubject(cert.issuer); 16108 16109 // see if there are multiple matches 16110 /*if(forge.util.isArray(rval)) { 16111 // TODO: resolve multiple matches by checking 16112 // authorityKey/subjectKey/issuerUniqueID/other identifiers, etc. 16113 // FIXME: or alternatively do authority key mapping 16114 // if possible (X.509v1 certs can't work?) 16115 throw new Error('Resolving multiple issuer matches not implemented yet.'); 16116 }*/ 16117 16118 return rval; 16119 }; 16120 16121 /** 16122 * Adds a trusted certificate to the store. 16123 * 16124 * @param cert the certificate to add as a trusted certificate (either a 16125 * pki.certificate object or a PEM-formatted certificate). 16126 */ 16127 caStore.addCertificate = function(cert) { 16128 // convert from pem if necessary 16129 if(typeof cert === 'string') { 16130 cert = forge.pki.certificateFromPem(cert); 16131 } 16132 16133 ensureSubjectHasHash(cert.subject); 16134 16135 if(!caStore.hasCertificate(cert)) { // avoid duplicate certificates in store 16136 if(cert.subject.hash in caStore.certs) { 16137 // subject hash already exists, append to array 16138 var tmp = caStore.certs[cert.subject.hash]; 16139 if(!forge.util.isArray(tmp)) { 16140 tmp = [tmp]; 16141 } 16142 tmp.push(cert); 16143 caStore.certs[cert.subject.hash] = tmp; 16144 } else { 16145 caStore.certs[cert.subject.hash] = cert; 16146 } 16147 } 16148 }; 16149 16150 /** 16151 * Checks to see if the given certificate is in the store. 16152 * 16153 * @param cert the certificate to check (either a pki.certificate or a 16154 * PEM-formatted certificate). 16155 * 16156 * @return true if the certificate is in the store, false if not. 16157 */ 16158 caStore.hasCertificate = function(cert) { 16159 // convert from pem if necessary 16160 if(typeof cert === 'string') { 16161 cert = forge.pki.certificateFromPem(cert); 16162 } 16163 16164 var match = getBySubject(cert.subject); 16165 if(!match) { 16166 return false;
16167 } 16168 if(!forge.util.isArray(match)) { 16169 match = [match]; 16170 } 16171 // compare DER-encoding of certificates 16172 var der1 = asn1.toDer(pki.certificateToAsn1(cert)).getBytes(); 16173 for(var i = 0; i < match.length; ++i) { 16174 var der2 = asn1.toDer(pki.certificateToAsn1(match[i])).getBytes(); 16175 if(der1 === der2) { 16176 return true; 16177 } 16178 } 16179 return false; 16180 }; 16181 16182 /** 16183 * Lists all of the certificates kept in the store. 16184 * 16185 * @return an array of all of the pki.certificate objects in the store. 16186 */ 16187 caStore.listAllCertificates = function() { 16188 var certList = []; 16189 16190 for(var hash in caStore.certs) { 16191 if(caStore.certs.hasOwnProperty(hash)) { 16192 var value = caStore.certs[hash]; 16193 if(!forge.util.isArray(value)) { 16194 certList.push(value); 16195 } else { 16196 for(var i = 0; i < value.length; ++i) { 16197 certList.push(value[i]); 16198 } 16199 } 16200 } 16201 } 16202 16203 return certList; 16204 }; 16205 16206 /** 16207 * Removes a certificate from the store. 16208 * 16209 * @param cert the certificate to remove (either a pki.certificate or a 16210 * PEM-formatted certificate). 16211 * 16212 * @return the certificate that was removed or null if the certificate 16213 * wasn't in store. 16214 */ 16215 caStore.removeCertificate = function(cert) { 16216 var result; 16217 16218 // convert from pem if necessary 16219 if(typeof cert === 'string') { 16220 cert = forge.pki.certificateFromPem(cert); 16221 } 16222 ensureSubjectHasHash(cert.subject); 16223 if(!caStore.hasCertificate(cert)) { 16224 return null; 16225 } 16226 16227 var match = getBySubject(cert.subject); 16228 16229 if(!forge.util.isArray(match)) { 16230 result = caStore.certs[cert.subject.hash]; 16231 delete caStore.certs[cert.subject.hash]; 16232 return result; 16233 } 16234 16235 // compare DER-encoding of certificates 16236 var der1 = asn1.toDer(pki.certificateToAsn1(cert)).getBytes(); 16237 for(var i = 0; i < match.length; ++i) { 16238 var der2 = asn1.toDer(pki.certificateToAsn1(match[i])).getBytes(); 16239 if(der1 === der2) { 16240 result = match[i]; 16241 match.splice(i, 1); 16242 } 16243 } 16244 if(match.length === 0) { 16245 delete caStore.certs[cert.subject.hash]; 16246 } 16247 16248 return result; 16249 }; 16250 16251 function getBySubject(subject) { 16252 ensureSubjectHasHash(subject); 16253 return caStore.certs[subject.hash] || null; 16254 } 16255 16256 function ensureSubjectHasHash(subject) { 16257 // produce subject hash if it doesn't exist 16258 if(!subject.hash) { 16259 var md = forge.md.sha1.create(); 16260 subject.attributes = pki.RDNAttributesAsArray(_dnToAsn1(subject), md); 16261 subject.hash = md.digest().toHex(); 16262 } 16263 } 16264 16265 // auto-add passed in certs 16266 if(certs) { 16267 // parse PEM-formatted certificates as necessary 16268 for(var i = 0; i < certs.length; ++i) { 16269 var cert = certs[i]; 16270 caStore.addCertificate(cert); 16271 } 16272 } 16273 16274 return caStore; 16275}; 16276 16277/** 16278 * Certificate verification errors, based on TLS. 16279 */ 16280pki.certificateError = { 16281 bad_certificate: 'forge.pki.BadCertificate', 16282 unsupported_certificate: 'forge.pki.UnsupportedCertificate', 16283 certificate_revoked: 'forge.pki.CertificateRevoked', 16284 certificate_expired: 'forge.pki.CertificateExpired', 16285 certificate_unknown: 'forge.pki.CertificateUnknown', 16286 unknown_ca: 'forge.pki.UnknownCertificateAuthority' 16287}; 16288 16289/** 16290 * Verifies a certificate chain against the given Certificate Authority store 16291 * with an optional custom verify callback. 16292 * 16293 * @param caStore a certificate store to verify against. 16294 * @param chain the certificate chain to verify, with the root or highest 16295 * authority at the end (an array of certificates). 16296 * @param verify called for every certificate in the chain. 16297 * 16298 * The verify callback has the following signature: 16299 * 16300 * verified - Set to true if certificate was verified, otherwise the 16301 * pki.certificateError for why the certificate failed. 16302 * depth - The current index in the chain, where 0 is the end point's cert. 16303 * certs - The certificate chain, *NOTE* an empty chain indicates an anonymous 16304 * end point. 16305 * 16306 * The function returns true on success and on failure either the appropriate 16307 * pki.certificateError or an object with 'error' set to the appropriate 16308 * pki.certificateError and 'message' set to a custom error message. 16309 * 16310 * @return true if successful, error thrown if not. 16311 */ 16312pki.verifyCertificateChain = function(caStore, chain, verify) {
16313 /* From: RFC3280 - Internet X.509 Public Key Infrastructure Certificate 16314 Section 6: Certification Path Validation 16315 See inline parentheticals related to this particular implementation. 16316 16317 The primary goal of path validation is to verify the binding between 16318 a subject distinguished name or a subject alternative name and subject 16319 public key, as represented in the end entity certificate, based on the 16320 public key of the trust anchor. This requires obtaining a sequence of 16321 certificates that support that binding. That sequence should be provided 16322 in the passed 'chain'. The trust anchor should be in the given CA 16323 store. The 'end entity' certificate is the certificate provided by the 16324 end point (typically a server) and is the first in the chain. 16325 16326 To meet this goal, the path validation process verifies, among other 16327 things, that a prospective certification path (a sequence of n 16328 certificates or a 'chain') satisfies the following conditions: 16329 16330 (a) for all x in {1, ..., n-1}, the subject of certificate x is 16331 the issuer of certificate x+1; 16332 16333 (b) certificate 1 is issued by the trust anchor; 16334 16335 (c) certificate n is the certificate to be validated; and 16336 16337 (d) for all x in {1, ..., n}, the certificate was valid at the 16338 time in question. 16339 16340 Note that here 'n' is index 0 in the chain and 1 is the last certificate 16341 in the chain and it must be signed by a certificate in the connection's 16342 CA store. 16343 16344 The path validation process also determines the set of certificate 16345 policies that are valid for this path, based on the certificate policies 16346 extension, policy mapping extension, policy constraints extension, and 16347 inhibit any-policy extension. 16348 16349 Note: Policy mapping extension not supported (Not Required). 16350 16351 Note: If the certificate has an unsupported critical extension, then it 16352 must be rejected. 16353 16354 Note: A certificate is self-issued if the DNs that appear in the subject 16355 and issuer fields are identical and are not empty. 16356 16357 The path validation algorithm assumes the following seven inputs are 16358 provided to the path processing logic. What this specific implementation 16359 will use is provided parenthetically: 16360 16361 (a) a prospective certification path of length n (the 'chain') 16362 (b) the current date/time: ('now'). 16363 (c) user-initial-policy-set: A set of certificate policy identifiers 16364 naming the policies that are acceptable to the certificate user. 16365 The user-initial-policy-set contains the special value any-policy 16366 if the user is not concerned about certificate policy 16367 (Not implemented. Any policy is accepted). 16368 (d) trust anchor information, describing a CA that serves as a trust 16369 anchor for the certification path. The trust anchor information 16370 includes: 16371 16372 (1) the trusted issuer name, 16373 (2) the trusted public key algorithm, 16374 (3) the trusted public key, and 16375 (4) optionally, the trusted public key parameters associated 16376 with the public key. 16377 16378 (Trust anchors are provided via certificates in the CA store). 16379 16380 The trust anchor information may be provided to the path processing 16381 procedure in the form of a self-signed certificate. The trusted anchor 16382 information is trusted because it was delivered to the path processing 16383 procedure by some trustworthy out-of-band procedure. If the trusted 16384 public key algorithm requires parameters, then the parameters are 16385 provided along with the trusted public key (No parameters used in this 16386 implementation). 16387 16388 (e) initial-policy-mapping-inhibit, which indicates if policy mapping is 16389 allowed in the certification path. 16390 (Not implemented, no policy checking) 16391 16392 (f) initial-explicit-policy, which indicates if the path must be valid 16393 for at least one of the certificate policies in the user-initial- 16394 policy-set. 16395 (Not implemented, no policy checking) 16396 16397 (g) initial-any-policy-inhibit, which indicates whether the 16398 anyPolicy OID should be processed if it is included in a 16399 certificate. 16400 (Not implemented, so any policy is valid provided that it is 16401 not marked as critical) */ 16402 16403 /* Basic Path Processing: 16404 16405 For each certificate in the 'chain', the following is checked: 16406 16407 1. The certificate validity period includes the current time. 16408 2. The certificate was signed by its parent (where the parent is either 16409 the next in the chain or from the CA store). Allow processing to 16410 continue to the next step if no parent is found but the certificate is 16411 in the CA store. 16412 3. TODO: The certificate has not been revoked. 16413 4. The certificate issuer name matches the parent's subject name. 16414 5. TODO: If the certificate is self-issued and not the final certificate
16415 in the chain, skip this step, otherwise verify that the subject name 16416 is within one of the permitted subtrees of X.500 distinguished names 16417 and that each of the alternative names in the subjectAltName extension 16418 (critical or non-critical) is within one of the permitted subtrees for 16419 that name type. 16420 6. TODO: If the certificate is self-issued and not the final certificate 16421 in the chain, skip this step, otherwise verify that the subject name 16422 is not within one of the excluded subtrees for X.500 distinguished 16423 names and none of the subjectAltName extension names are excluded for 16424 that name type. 16425 7. The other steps in the algorithm for basic path processing involve 16426 handling the policy extension which is not presently supported in this 16427 implementation. Instead, if a critical policy extension is found, the 16428 certificate is rejected as not supported. 16429 8. If the certificate is not the first or if its the only certificate in 16430 the chain (having no parent from the CA store or is self-signed) and it 16431 has a critical key usage extension, verify that the keyCertSign bit is 16432 set. If the key usage extension exists, verify that the basic 16433 constraints extension exists. If the basic constraints extension exists, 16434 verify that the cA flag is set. If pathLenConstraint is set, ensure that 16435 the number of certificates that precede in the chain (come earlier 16436 in the chain as implemented below), excluding the very first in the 16437 chain (typically the end-entity one), isn't greater than the 16438 pathLenConstraint. This constraint limits the number of intermediate 16439 CAs that may appear below a CA before only end-entity certificates 16440 may be issued. */ 16441 16442 // copy cert chain references to another array to protect against changes 16443 // in verify callback 16444 chain = chain.slice(0); 16445 var certs = chain.slice(0); 16446 16447 // get current date 16448 var now = new Date(); 16449 16450 // verify each cert in the chain using its parent, where the parent 16451 // is either the next in the chain or from the CA store 16452 var first = true; 16453 var error = null; 16454 var depth = 0; 16455 do { 16456 var cert = chain.shift(); 16457 var parent = null; 16458 var selfSigned = false; 16459 16460 // 1. check valid time 16461 if(now < cert.validity.notBefore || now > cert.validity.notAfter) { 16462 error = { 16463 message: 'Certificate is not valid yet or has expired.', 16464 error: pki.certificateError.certificate_expired, 16465 notBefore: cert.validity.notBefore, 16466 notAfter: cert.validity.notAfter, 16467 now: now 16468 }; 16469 } 16470 16471 // 2. verify with parent from chain or CA store 16472 if(error === null) { 16473 parent = chain[0] || caStore.getIssuer(cert); 16474 if(parent === null) { 16475 // check for self-signed cert 16476 if(cert.isIssuer(cert)) { 16477 selfSigned = true; 16478 parent = cert; 16479 } 16480 } 16481 16482 if(parent) { 16483 // FIXME: current CA store implementation might have multiple 16484 // certificates where the issuer can't be determined from the 16485 // certificate (happens rarely with, eg: old certificates) so normalize 16486 // by always putting parents into an array 16487 // TODO: there's may be an extreme degenerate case currently uncovered 16488 // where an old intermediate certificate seems to have a matching parent 16489 // but none of the parents actually verify ... but the intermediate 16490 // is in the CA and it should pass this check; needs investigation 16491 var parents = parent; 16492 if(!forge.util.isArray(parents)) { 16493 parents = [parents]; 16494 } 16495 16496 // try to verify with each possible parent (typically only one) 16497 var verified = false; 16498 while(!verified && parents.length > 0) { 16499 parent = parents.shift(); 16500 try { 16501 verified = parent.verify(cert); 16502 } catch(ex) { 16503 // failure to verify, don't care why, try next one 16504 } 16505 } 16506 16507 if(!verified) { 16508 error = {
16509 message: 'Certificate signature is invalid.', 16510 error: pki.certificateError.bad_certificate 16511 }; 16512 } 16513 } 16514 16515 if(error === null && (!parent || selfSigned) && 16516 !caStore.hasCertificate(cert)) { 16517 // no parent issuer and certificate itself is not trusted 16518 error = { 16519 message: 'Certificate is not trusted.', 16520 error: pki.certificateError.unknown_ca 16521 }; 16522 } 16523 } 16524 16525 // TODO: 3. check revoked 16526 16527 // 4. check for matching issuer/subject 16528 if(error === null && parent && !cert.isIssuer(parent)) { 16529 // parent is not issuer 16530 error = { 16531 message: 'Certificate issuer is invalid.', 16532 error: pki.certificateError.bad_certificate 16533 }; 16534 } 16535 16536 // 5. TODO: check names with permitted names tree 16537 16538 // 6. TODO: check names against excluded names tree 16539 16540 // 7. check for unsupported critical extensions 16541 if(error === null) { 16542 // supported extensions 16543 var se = { 16544 keyUsage: true, 16545 basicConstraints: true 16546 }; 16547 for(var i = 0; error === null && i < cert.extensions.length; ++i) { 16548 var ext = cert.extensions[i]; 16549 if(ext.critical && !(ext.name in se)) { 16550 error = { 16551 message: 16552 'Certificate has an unsupported critical extension.', 16553 error: pki.certificateError.unsupported_certificate 16554 }; 16555 } 16556 } 16557 } 16558 16559 // 8. check for CA if cert is not first or is the only certificate 16560 // remaining in chain with no parent or is self-signed 16561 if(error === null && 16562 (!first || (chain.length === 0 && (!parent || selfSigned)))) { 16563 // first check keyUsage extension and then basic constraints 16564 var bcExt = cert.getExtension('basicConstraints'); 16565 var keyUsageExt = cert.getExtension('keyUsage'); 16566 if(keyUsageExt !== null) { 16567 // keyCertSign must be true and there must be a basic 16568 // constraints extension 16569 if(!keyUsageExt.keyCertSign || bcExt === null) { 16570 // bad certificate 16571 error = { 16572 message: 16573 'Certificate keyUsage or basicConstraints conflict ' + 16574 'or indicate that the certificate is not a CA. ' + 16575 'If the certificate is the only one in the chain or ' + 16576 'isn\'t the first then the certificate must be a ' + 16577 'valid CA.', 16578 error: pki.certificateError.bad_certificate 16579 }; 16580 } 16581 } 16582 // basic constraints cA flag must be set 16583 if(error === null && bcExt !== null && !bcExt.cA) { 16584 // bad certificate 16585 error = { 16586 message: 16587 'Certificate basicConstraints indicates the certificate ' + 16588 'is not a CA.', 16589 error: pki.certificateError.bad_certificate 16590 }; 16591 } 16592 // if error is not null and keyUsage is available, then we know it 16593 // has keyCertSign and there is a basic constraints extension too, 16594 // which means we can check pathLenConstraint (if it exists) 16595 if(error === null && keyUsageExt !== null && 16596 'pathLenConstraint' in bcExt) { 16597 // pathLen is the maximum # of intermediate CA certs that can be 16598 // found between the current certificate and the end-entity (depth 0) 16599 // certificate; this number does not include the end-entity (depth 0, 16600 // last in the chain) even if it happens to be a CA certificate itself 16601 var pathLen = depth - 1; 16602 if(pathLen > bcExt.pathLenConstraint) { 16603 // pathLenConstraint violated, bad certificate 16604 error = { 16605 message: 16606 'Certificate basicConstraints pathLenConstraint violated.', 16607 error: pki.certificateError.bad_certificate 16608 }; 16609 } 16610 } 16611 } 16612 16613 // call application callback 16614 var vfd = (error === null) ? true : error.error; 16615 var ret = verify ? verify(vfd, depth, certs) : vfd; 16616 if(ret === true) { 16617 // clear any set error 16618 error = null; 16619 } else { 16620 // if passed basic tests, set default message and alert 16621 if(vfd === true) { 16622 error = { 16623 message: 'The application rejected the certificate.', 16624 error: pki.certificateError.bad_certificate 16625 }; 16626 } 16627 16628 // check for custom error info 16629 if(ret || ret === 0) { 16630 // set custom message and error 16631 if(typeof ret === 'object' && !forge.util.isArray(ret)) { 16632 if(ret.message) { 16633 error.message = ret.message; 16634 } 16635 if(ret.error) { 16636 error.error = ret.error; 16637 } 16638 } else if(typeof ret === 'string') { 16639 // set custom error 16640 error.error = ret; 16641 } 16642 } 16643 16644 // throw error 16645 throw error; 16646 } 16647 16648 // no longer first cert in chain 16649 first = false;
16650 ++depth; 16651 } while(chain.length > 0); 16652 16653 return true; 16654}; 16655 16656} // end module implementation 16657 16658/* ########## Begin module wrapper ########## */ 16659var name = 'x509'; 16660if(typeof define !== 'function') { 16661 // NodeJS -> AMD 16662 if(typeof module === 'object' && module.exports) { 16663 var nodeJS = true; 16664 define = function(ids, factory) { 16665 factory(require, module); 16666 }; 16667 } else { 16668 // <script> 16669 if(typeof forge === 'undefined') { 16670 forge = {}; 16671 } 16672 return initModule(forge); 16673 } 16674} 16675// AMD 16676var deps; 16677var defineFunc = function(require, module) { 16678 module.exports = function(forge) { 16679 var mods = deps.map(function(dep) { 16680 return require(dep); 16681 }).concat(initModule); 16682 // handle circular dependencies 16683 forge = forge || {}; 16684 forge.defined = forge.defined || {}; 16685 if(forge.defined[name]) { 16686 return forge[name]; 16687 } 16688 forge.defined[name] = true; 16689 for(var i = 0; i < mods.length; ++i) { 16690 mods[i](forge); 16691 } 16692 return forge.pki; 16693 }; 16694}; 16695var tmpDefine = define; 16696define = function(ids, factory) { 16697 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 16698 if(nodeJS) { 16699 delete define; 16700 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 16701 } 16702 define = tmpDefine; 16703 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 16704}; 16705define([ 16706 'require', 16707 'module', 16708 './aes', 16709 './asn1', 16710 './des', 16711 './md', 16712 './mgf', 16713 './oids', 16714 './pem', 16715 './pss', 16716 './rsa', 16717 './util' 16718], function() { 16719 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 16720}); 16721})(); 16722 16723/** 16724 * Node.js module for Forge message digests. 16725 * 16726 * @author Dave Longley 16727 * 16728 * Copyright 2011-2014 Digital Bazaar, Inc. 16729 */ 16730(function() { 16731/* ########## Begin module implementation ########## */ 16732function initModule(forge) { 16733 16734forge.md = forge.md || {}; 16735forge.md.algorithms = { 16736 md5: forge.md5, 16737 sha1: forge.sha1, 16738 sha256: forge.sha256 16739}; 16740forge.md.md5 = forge.md5; 16741forge.md.sha1 = forge.sha1; 16742forge.md.sha256 = forge.sha256; 16743 16744} // end module implementation 16745 16746/* ########## Begin module wrapper ########## */ 16747var name = 'md'; 16748if(typeof define !== 'function') { 16749 // NodeJS -> AMD 16750 if(typeof module === 'object' && module.exports) { 16751 var nodeJS = true; 16752 define = function(ids, factory) { 16753 factory(require, module); 16754 }; 16755 } else { 16756 // <script> 16757 if(typeof forge === 'undefined') { 16758 forge = {}; 16759 } 16760 return initModule(forge); 16761 } 16762} 16763// AMD 16764var deps; 16765var defineFunc = function(require, module) { 16766 module.exports = function(forge) { 16767 var mods = deps.map(function(dep) { 16768 return require(dep); 16769 }).concat(initModule); 16770 // handle circular dependencies 16771 forge = forge || {}; 16772 forge.defined = forge.defined || {}; 16773 if(forge.defined[name]) { 16774 return forge[name]; 16775 } 16776 forge.defined[name] = true; 16777 for(var i = 0; i < mods.length; ++i) { 16778 mods[i](forge); 16779 } 16780 return forge[name]; 16781 }; 16782}; 16783var tmpDefine = define; 16784define = function(ids, factory) { 16785 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 16786 if(nodeJS) { 16787 delete define; 16788 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 16789 } 16790 define = tmpDefine; 16791 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 16792}; 16793define( 16794 ['require', 'module', './md5', './sha1', './sha256', './sha512'], function() { 16795 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 16796}); 16797})(); 16798 16799/** 16800 * Password-based encryption functions. 16801 * 16802 * @author Dave Longley 16803 * @author Stefan Siegl <[email protected]> 16804 * 16805 * Copyright (c) 2010-2013 Digital Bazaar, Inc. 16806 * Copyright (c) 2012 Stefan Siegl <[email protected]> 16807 * 16808 * An EncryptedPrivateKeyInfo: 16809 * 16810 * EncryptedPrivateKeyInfo ::= SEQUENCE { 16811 * encryptionAlgorithm EncryptionAlgorithmIdentifier, 16812 * encryptedData EncryptedData } 16813 * 16814 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 16815 * 16816 * EncryptedData ::= OCTET STRING 16817 */ 16818(function() { 16819/* ########## Begin module implementation ########## */ 16820function initModule(forge) { 16821 16822if(typeof BigInteger === 'undefined') { 16823 var BigInteger = forge.jsbn.BigInteger; 16824} 16825 16826// shortcut for asn.1 API 16827var asn1 = forge.asn1; 16828 16829/* Password-based encryption implementation. */ 16830var pki = forge.pki = forge.pki || {}; 16831pki.pbe = forge.pbe = forge.pbe || {}; 16832var oids = pki.oids; 16833 16834// validator for an EncryptedPrivateKeyInfo structure
16835// Note: Currently only works w/algorithm params 16836var encryptedPrivateKeyValidator = { 16837 name: 'EncryptedPrivateKeyInfo', 16838 tagClass: asn1.Class.UNIVERSAL, 16839 type: asn1.Type.SEQUENCE, 16840 constructed: true, 16841 value: [{ 16842 name: 'EncryptedPrivateKeyInfo.encryptionAlgorithm', 16843 tagClass: asn1.Class.UNIVERSAL, 16844 type: asn1.Type.SEQUENCE, 16845 constructed: true, 16846 value: [{ 16847 name: 'AlgorithmIdentifier.algorithm', 16848 tagClass: asn1.Class.UNIVERSAL, 16849 type: asn1.Type.OID, 16850 constructed: false, 16851 capture: 'encryptionOid' 16852 }, { 16853 name: 'AlgorithmIdentifier.parameters', 16854 tagClass: asn1.Class.UNIVERSAL, 16855 type: asn1.Type.SEQUENCE, 16856 constructed: true, 16857 captureAsn1: 'encryptionParams' 16858 }] 16859 }, { 16860 // encryptedData 16861 name: 'EncryptedPrivateKeyInfo.encryptedData', 16862 tagClass: asn1.Class.UNIVERSAL, 16863 type: asn1.Type.OCTETSTRING, 16864 constructed: false, 16865 capture: 'encryptedData' 16866 }] 16867}; 16868 16869// validator for a PBES2Algorithms structure 16870// Note: Currently only works w/PBKDF2 + AES encryption schemes 16871var PBES2AlgorithmsValidator = { 16872 name: 'PBES2Algorithms', 16873 tagClass: asn1.Class.UNIVERSAL, 16874 type: asn1.Type.SEQUENCE, 16875 constructed: true, 16876 value: [{ 16877 name: 'PBES2Algorithms.keyDerivationFunc', 16878 tagClass: asn1.Class.UNIVERSAL, 16879 type: asn1.Type.SEQUENCE, 16880 constructed: true, 16881 value: [{ 16882 name: 'PBES2Algorithms.keyDerivationFunc.oid', 16883 tagClass: asn1.Class.UNIVERSAL, 16884 type: asn1.Type.OID, 16885 constructed: false, 16886 capture: 'kdfOid' 16887 }, { 16888 name: 'PBES2Algorithms.params', 16889 tagClass: asn1.Class.UNIVERSAL, 16890 type: asn1.Type.SEQUENCE, 16891 constructed: true, 16892 value: [{ 16893 name: 'PBES2Algorithms.params.salt', 16894 tagClass: asn1.Class.UNIVERSAL, 16895 type: asn1.Type.OCTETSTRING, 16896 constructed: false, 16897 capture: 'kdfSalt' 16898 }, { 16899 name: 'PBES2Algorithms.params.iterationCount', 16900 tagClass: asn1.Class.UNIVERSAL, 16901 type: asn1.Type.INTEGER, 16902 constructed: false, 16903 capture: 'kdfIterationCount' 16904 }, { 16905 name: 'PBES2Algorithms.params.keyLength', 16906 tagClass: asn1.Class.UNIVERSAL, 16907 type: asn1.Type.INTEGER, 16908 constructed: false, 16909 optional: true, 16910 capture: 'keyLength' 16911 }, { 16912 // prf 16913 name: 'PBES2Algorithms.params.prf', 16914 tagClass: asn1.Class.UNIVERSAL, 16915 type: asn1.Type.SEQUENCE, 16916 constructed: true, 16917 optional: true, 16918 value: [{ 16919 name: 'PBES2Algorithms.params.prf.algorithm', 16920 tagClass: asn1.Class.UNIVERSAL, 16921 type: asn1.Type.OID, 16922 constructed: false, 16923 capture: 'prfOid' 16924 }] 16925 }] 16926 }] 16927 }, { 16928 name: 'PBES2Algorithms.encryptionScheme', 16929 tagClass: asn1.Class.UNIVERSAL, 16930 type: asn1.Type.SEQUENCE, 16931 constructed: true, 16932 value: [{ 16933 name: 'PBES2Algorithms.encryptionScheme.oid', 16934 tagClass: asn1.Class.UNIVERSAL, 16935 type: asn1.Type.OID, 16936 constructed: false, 16937 capture: 'encOid' 16938 }, { 16939 name: 'PBES2Algorithms.encryptionScheme.iv', 16940 tagClass: asn1.Class.UNIVERSAL, 16941 type: asn1.Type.OCTETSTRING, 16942 constructed: false, 16943 capture: 'encIv' 16944 }] 16945 }] 16946}; 16947 16948var pkcs12PbeParamsValidator = { 16949 name: 'pkcs-12PbeParams', 16950 tagClass: asn1.Class.UNIVERSAL, 16951 type: asn1.Type.SEQUENCE, 16952 constructed: true, 16953 value: [{ 16954 name: 'pkcs-12PbeParams.salt', 16955 tagClass: asn1.Class.UNIVERSAL, 16956 type: asn1.Type.OCTETSTRING, 16957 constructed: false, 16958 capture: 'salt' 16959 }, { 16960 name: 'pkcs-12PbeParams.iterations', 16961 tagClass: asn1.Class.UNIVERSAL, 16962 type: asn1.Type.INTEGER, 16963 constructed: false, 16964 capture: 'iterations' 16965 }] 16966}; 16967 16968/** 16969 * Encrypts a ASN.1 PrivateKeyInfo object, producing an EncryptedPrivateKeyInfo. 16970 * 16971 * PBES2Algorithms ALGORITHM-IDENTIFIER ::= 16972 * { {PBES2-params IDENTIFIED BY id-PBES2}, ...} 16973 * 16974 * id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} 16975 * 16976 * PBES2-params ::= SEQUENCE { 16977 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 16978 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} 16979 * } 16980 * 16981 * PBES2-KDFs ALGORITHM-IDENTIFIER ::= 16982 * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... } 16983 * 16984 * PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... } 16985 * 16986 * PBKDF2-params ::= SEQUENCE { 16987 * salt CHOICE { 16988 * specified OCTET STRING, 16989 * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} 16990 * }, 16991 * iterationCount INTEGER (1..MAX), 16992 * keyLength INTEGER (1..MAX) OPTIONAL, 16993 * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 16994 * } 16995 * 16996 * @param obj the ASN.1 PrivateKeyInfo object. 16997 * @param password the password to encrypt with. 16998 * @param options: 16999 * algorithm the encryption algorithm to use 17000 * ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. 17001 * count the iteration count to use. 17002 * saltSize the salt size to use. 17003 * prfAlgorithm the PRF message digest algorithm to use 17004 * ('sha1', 'sha224', 'sha256', 'sha384', 'sha512') 17005 * 17006 * @return the ASN.1 EncryptedPrivateKeyInfo. 17007 */ 17008pki.encryptPrivateKeyInfo = function(obj, password, options) { 17009 // set default options 17010 options = options || {}; 17011 options.saltSize = options.saltSize || 8; 17012 options.count = options.count || 2048; 17013 options.algorithm = options.algorithm || 'aes128'; 17014 options.prfAlgorithm = options.prfAlgorithm || 'sha1'; 17015 17016 // generate PBE params 17017 var salt = forge.random.getBytesSync(options.saltSize); 17018 var count = options.count; 17019 var countBytes = asn1.integerToDer(count); 17020 var dkLen; 17021 var encryptionAlgorithm; 17022 var encryptedData; 17023 if(options.algorithm.indexOf('aes') === 0 || options.algorithm === 'des') { 17024 // do PBES2 17025 var ivLen, encOid, cipherFn; 17026 switch(options.algorithm) { 17027 case 'aes128': 17028 dkLen = 16; 17029 ivLen = 16; 17030 encOid = oids['aes128-CBC']; 17031 cipherFn = forge.aes.createEncryptionCipher; 17032 break; 17033 case 'aes192': 17034 dkLen = 24; 17035 ivLen = 16; 17036 encOid = oids['aes192-CBC']; 17037 cipherFn = forge.aes.createEncryptionCipher; 17038 break; 17039 case 'aes256': 17040 dkLen = 32; 17041 ivLen = 16; 17042 encOid = oids['aes256-CBC']; 17043 cipherFn = forge.aes.createEncryptionCipher; 17044 break; 17045 case 'des': 17046 dkLen = 8; 17047 ivLen = 8; 17048 encOid = oids['desCBC']; 17049 cipherFn = forge.des.createEncryptionCipher; 17050 break; 17051 default: 17052 var error = new Error('Cannot encrypt private key. Unknown encryption algorithm.'); 17053 error.algorithm = options.algorithm; 17054 throw error; 17055 } 17056 17057 // get PRF message digest 17058 var prfAlgorithm = 'hmacWith' + options.prfAlgorithm.toUpperCase(); 17059 var md = prfAlgorithmToMessageDigest(prfAlgorithm); 17060 17061 // encrypt private key using pbe SHA-1 and AES/DES 17062 var dk = forge.pkcs5.pbkdf2(password, salt, count, dkLen, md); 17063 var iv = forge.random.getBytesSync(ivLen); 17064 var cipher = cipherFn(dk); 17065 cipher.start(iv); 17066 cipher.update(asn1.toDer(obj)); 17067 cipher.finish(); 17068 encryptedData = cipher.output.getBytes(); 17069 17070 // get PBKDF2-params 17071 var params = createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm); 17072 17073 encryptionAlgorithm = asn1.create( 17074 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17075 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 17076 asn1.oidToDer(oids['pkcs5PBES2']).getBytes()), 17077 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17078 // keyDerivationFunc 17079 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17080 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 17081 asn1.oidToDer(oids['pkcs5PBKDF2']).getBytes()), 17082 // PBKDF2-params 17083 params 17084 ]), 17085 // encryptionScheme 17086 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17087 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 17088 asn1.oidToDer(encOid).getBytes()), 17089 // iv 17090 asn1.create( 17091 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, iv) 17092 ]) 17093 ]) 17094 ]); 17095 } else if(options.algorithm === '3des') { 17096 // Do PKCS12 PBE 17097 dkLen = 24; 17098 17099 var saltBytes = new forge.util.ByteBuffer(salt); 17100 var dk = pki.pbe.generatePkcs12Key(password, saltBytes, 1, count, dkLen); 17101 var iv = pki.pbe.generatePkcs12Key(password, saltBytes, 2, count, dkLen); 17102 var cipher = forge.des.createEncryptionCipher(dk); 17103 cipher.start(iv); 17104 cipher.update(asn1.toDer(obj)); 17105 cipher.finish(); 17106 encryptedData = cipher.output.getBytes(); 17107 17108 encryptionAlgorithm = asn1.create( 17109 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17110 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 17111 asn1.oidToDer(oids['pbeWithSHAAnd3-KeyTripleDES-CBC']).getBytes()),
17112 // pkcs-12PbeParams 17113 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17114 // salt 17115 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, salt), 17116 // iteration count 17117 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 17118 countBytes.getBytes()) 17119 ]) 17120 ]); 17121 } else { 17122 var error = new Error('Cannot encrypt private key. Unknown encryption algorithm.'); 17123 error.algorithm = options.algorithm; 17124 throw error; 17125 } 17126 17127 // EncryptedPrivateKeyInfo 17128 var rval = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17129 // encryptionAlgorithm 17130 encryptionAlgorithm, 17131 // encryptedData 17132 asn1.create( 17133 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, encryptedData) 17134 ]); 17135 return rval; 17136}; 17137 17138/** 17139 * Decrypts a ASN.1 PrivateKeyInfo object. 17140 * 17141 * @param obj the ASN.1 EncryptedPrivateKeyInfo object. 17142 * @param password the password to decrypt with. 17143 * 17144 * @return the ASN.1 PrivateKeyInfo on success, null on failure. 17145 */ 17146pki.decryptPrivateKeyInfo = function(obj, password) { 17147 var rval = null; 17148 17149 // get PBE params 17150 var capture = {}; 17151 var errors = []; 17152 if(!asn1.validate(obj, encryptedPrivateKeyValidator, capture, errors)) { 17153 var error = new Error('Cannot read encrypted private key. ' + 17154 'ASN.1 object is not a supported EncryptedPrivateKeyInfo.'); 17155 error.errors = errors; 17156 throw error; 17157 } 17158 17159 // get cipher 17160 var oid = asn1.derToOid(capture.encryptionOid); 17161 var cipher = pki.pbe.getCipher(oid, capture.encryptionParams, password); 17162 17163 // get encrypted data 17164 var encrypted = forge.util.createBuffer(capture.encryptedData); 17165 17166 cipher.update(encrypted); 17167 if(cipher.finish()) { 17168 rval = asn1.fromDer(cipher.output); 17169 } 17170 17171 return rval; 17172}; 17173 17174/** 17175 * Converts a EncryptedPrivateKeyInfo to PEM format. 17176 * 17177 * @param epki the EncryptedPrivateKeyInfo. 17178 * @param maxline the maximum characters per line, defaults to 64. 17179 * 17180 * @return the PEM-formatted encrypted private key. 17181 */ 17182pki.encryptedPrivateKeyToPem = function(epki, maxline) { 17183 // convert to DER, then PEM-encode 17184 var msg = { 17185 type: 'ENCRYPTED PRIVATE KEY', 17186 body: asn1.toDer(epki).getBytes() 17187 }; 17188 return forge.pem.encode(msg, {maxline: maxline}); 17189}; 17190 17191/** 17192 * Converts a PEM-encoded EncryptedPrivateKeyInfo to ASN.1 format. Decryption 17193 * is not performed. 17194 * 17195 * @param pem the EncryptedPrivateKeyInfo in PEM-format. 17196 * 17197 * @return the ASN.1 EncryptedPrivateKeyInfo. 17198 */ 17199pki.encryptedPrivateKeyFromPem = function(pem) { 17200 var msg = forge.pem.decode(pem)[0]; 17201 17202 if(msg.type !== 'ENCRYPTED PRIVATE KEY') { 17203 var error = new Error('Could not convert encrypted private key from PEM; ' + 17204 'PEM header type is "ENCRYPTED PRIVATE KEY".'); 17205 error.headerType = msg.type; 17206 throw error; 17207 } 17208 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 17209 throw new Error('Could not convert encrypted private key from PEM; ' + 17210 'PEM is encrypted.'); 17211 } 17212 17213 // convert DER to ASN.1 object 17214 return asn1.fromDer(msg.body); 17215}; 17216 17217/** 17218 * Encrypts an RSA private key. By default, the key will be wrapped in 17219 * a PrivateKeyInfo and encrypted to produce a PKCS#8 EncryptedPrivateKeyInfo. 17220 * This is the standard, preferred way to encrypt a private key. 17221 * 17222 * To produce a non-standard PEM-encrypted private key that uses encapsulated 17223 * headers to indicate the encryption algorithm (old-style non-PKCS#8 OpenSSL 17224 * private key encryption), set the 'legacy' option to true. Note: Using this 17225 * option will cause the iteration count to be forced to 1. 17226 * 17227 * Note: The 'des' algorithm is supported, but it is not considered to be 17228 * secure because it only uses a single 56-bit key. If possible, it is highly 17229 * recommended that a different algorithm be used. 17230 * 17231 * @param rsaKey the RSA key to encrypt. 17232 * @param password the password to use. 17233 * @param options: 17234 * algorithm: the encryption algorithm to use 17235 * ('aes128', 'aes192', 'aes256', '3des', 'des'). 17236 * count: the iteration count to use. 17237 * saltSize: the salt size to use. 17238 * legacy: output an old non-PKCS#8 PEM-encrypted+encapsulated 17239 * headers (DEK-Info) private key. 17240 * 17241 * @return the PEM-encoded ASN.1 EncryptedPrivateKeyInfo. 17242 */ 17243pki.encryptRsaPrivateKey = function(rsaKey, password, options) { 17244 // standard PKCS#8 17245 options = options || {}; 17246 if(!options.legacy) { 17247 // encrypt PrivateKeyInfo 17248 var rval = pki.wrapRsaPrivateKey(pki.privateKeyToAsn1(rsaKey)); 17249 rval = pki.encryptPrivateKeyInfo(rval, password, options); 17250 return pki.encryptedPrivateKeyToPem(rval); 17251 } 17252 17253 // legacy non-PKCS#8 17254 var algorithm; 17255 var iv; 17256 var dkLen; 17257 var cipherFn; 17258 switch(options.algorithm) { 17259 case 'aes128': 17260 algorithm = 'AES-128-CBC'; 17261 dkLen = 16; 17262 iv = forge.random.getBytesSync(16); 17263 cipherFn = forge.aes.createEncryptionCipher; 17264 break; 17265 case 'aes192': 17266 algorithm = 'AES-192-CBC'; 17267 dkLen = 24; 17268 iv = forge.random.getBytesSync(16); 17269 cipherFn = forge.aes.createEncryptionCipher; 17270 break; 17271 case 'aes256': 17272 algorithm = 'AES-256-CBC'; 17273 dkLen = 32; 17274 iv = forge.random.getBytesSync(16); 17275 cipherFn = forge.aes.createEncryptionCipher; 17276 break; 17277 case '3des': 17278 algorithm = 'DES-EDE3-CBC'; 17279 dkLen = 24; 17280 iv = forge.random.getBytesSync(8); 17281 cipherFn = forge.des.createEncryptionCipher; 17282 break; 17283 case 'des': 17284 algorithm = 'DES-CBC'; 17285 dkLen = 8; 17286 iv = forge.random.getBytesSync(8); 17287 cipherFn = forge.des.createEncryptionCipher; 17288 break; 17289 default: 17290 var error = new Error('Could not encrypt RSA private key; unsupported ' + 17291 'encryption algorithm "' + options.algorithm + '".'); 17292 error.algorithm = options.algorithm; 17293 throw error; 17294 } 17295 17296 // encrypt private key using OpenSSL legacy key derivation 17297 var dk = forge.pbe.opensslDeriveBytes(password, iv.substr(0, 8), dkLen); 17298 var cipher = cipherFn(dk); 17299 cipher.start(iv); 17300 cipher.update(asn1.toDer(pki.privateKeyToAsn1(rsaKey))); 17301 cipher.finish(); 17302 17303 var msg = { 17304 type: 'RSA PRIVATE KEY', 17305 procType: { 17306 version: '4', 17307 type: 'ENCRYPTED' 17308 }, 17309 dekInfo: { 17310 algorithm: algorithm, 17311 parameters: forge.util.bytesToHex(iv).toUpperCase() 17312 }, 17313 body: cipher.output.getBytes() 17314 }; 17315 return forge.pem.encode(msg); 17316}; 17317 17318/** 17319 * Decrypts an RSA private key. 17320 * 17321 * @param pem the PEM-formatted EncryptedPrivateKeyInfo to decrypt. 17322 * @param password the password to use. 17323 * 17324 * @return the RSA key on success, null on failure. 17325 */ 17326pki.decryptRsaPrivateKey = function(pem, password) { 17327 var rval = null; 17328 17329 var msg = forge.pem.decode(pem)[0]; 17330 17331 if(msg.type !== 'ENCRYPTED PRIVATE KEY' && 17332 msg.type !== 'PRIVATE KEY' && 17333 msg.type !== 'RSA PRIVATE KEY') { 17334 var error = new Error('Could not convert private key from PEM; PEM header type ' + 17335 'is not "ENCRYPTED PRIVATE KEY", "PRIVATE KEY", or "RSA PRIVATE KEY".'); 17336 error.headerType = error; 17337 throw error; 17338 } 17339 17340 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 17341 var dkLen; 17342 var cipherFn; 17343 switch(msg.dekInfo.algorithm) { 17344 case 'DES-CBC': 17345 dkLen = 8; 17346 cipherFn = forge.des.createDecryptionCipher; 17347 break; 17348 case 'DES-EDE3-CBC': 17349 dkLen = 24; 17350 cipherFn = forge.des.createDecryptionCipher; 17351 break; 17352 case 'AES-128-CBC': 17353 dkLen = 16; 17354 cipherFn = forge.aes.createDecryptionCipher; 17355 break; 17356 case 'AES-192-CBC': 17357 dkLen = 24; 17358 cipherFn = forge.aes.createDecryptionCipher; 17359 break; 17360 case 'AES-256-CBC': 17361 dkLen = 32; 17362 cipherFn = forge.aes.createDecryptionCipher; 17363 break; 17364 case 'RC2-40-CBC': 17365 dkLen = 5; 17366 cipherFn = function(key) { 17367 return forge.rc2.createDecryptionCipher(key, 40); 17368 }; 17369 break; 17370 case 'RC2-64-CBC': 17371 dkLen = 8; 17372 cipherFn = function(key) { 17373 return forge.rc2.createDecryptionCipher(key, 64); 17374 }; 17375 break; 17376 case 'RC2-128-CBC': 17377 dkLen = 16; 17378 cipherFn = function(key) { 17379 return forge.rc2.createDecryptionCipher(key, 128); 17380 }; 17381 break; 17382 default: 17383 var error = new Error('Could not decrypt private key; unsupported ' + 17384 'encryption algorithm "' + msg.dekInfo.algorithm + '".'); 17385 error.algorithm = msg.dekInfo.algorithm; 17386 throw error; 17387 } 17388 17389 // use OpenSSL legacy key derivation 17390 var iv = forge.util.hexToBytes(msg.dekInfo.parameters); 17391 var dk = forge.pbe.opensslDeriveBytes(password, iv.substr(0, 8), dkLen); 17392 var cipher = cipherFn(dk); 17393 cipher.start(iv); 17394 cipher.update(forge.util.createBuffer(msg.body)); 17395 if(cipher.finish()) { 17396 rval = cipher.output.getBytes(); 17397 } else { 17398 return rval; 17399 } 17400 } else { 17401 rval = msg.body; 17402 } 17403 17404 if(msg.type === 'ENCRYPTED PRIVATE KEY') { 17405 rval = pki.decryptPrivateKeyInfo(asn1.fromDer(rval), password); 17406 } else { 17407 // decryption already performed above 17408 rval = asn1.fromDer(rval); 17409 } 17410 17411 if(rval !== null) { 17412 rval = pki.privateKeyFromAsn1(rval); 17413 } 17414 17415 return rval; 17416}; 17417 17418/** 17419 * Derives a PKCS#12 key. 17420 * 17421 * @param password the password to derive the key material from, null or 17422 * undefined for none. 17423 * @param salt the salt, as a ByteBuffer, to use. 17424 * @param id the PKCS#12 ID byte (1 = key material, 2 = IV, 3 = MAC). 17425 * @param iter the iteration count. 17426 * @param n the number of bytes to derive from the password. 17427 * @param md the message digest to use, defaults to SHA-1. 17428 * 17429 * @return a ByteBuffer with the bytes derived from the password. 17430 */ 17431pki.pbe.generatePkcs12Key = function(password, salt, id, iter, n, md) { 17432 var j, l; 17433 17434 if(typeof md === 'undefined' || md === null) { 17435 md = forge.md.sha1.create(); 17436 } 17437 17438 var u = md.digestLength; 17439 var v = md.blockLength; 17440 var result = new forge.util.ByteBuffer(); 17441 17442 /* Convert password to Unicode byte buffer + trailing 0-byte. */ 17443 var passBuf = new forge.util.ByteBuffer(); 17444 if(password !== null && password !== undefined) { 17445 for(l = 0; l < password.length; l++) { 17446 passBuf.putInt16(password.charCodeAt(l)); 17447 } 17448 passBuf.putInt16(0); 17449 } 17450 17451 /* Length of salt and password in BYTES. */ 17452 var p = passBuf.length(); 17453 var s = salt.length(); 17454 17455 /* 1. Construct a string, D (the "diversifier"), by concatenating 17456 v copies of ID. */ 17457 var D = new forge.util.ByteBuffer(); 17458 D.fillWithByte(id, v); 17459 17460 /* 2. Concatenate copies of the salt together to create a string S of length 17461 v * ceil(s / v) bytes (the final copy of the salt may be trunacted 17462 to create S). 17463 Note that if the salt is the empty string, then so is S. */ 17464 var Slen = v * Math.ceil(s / v); 17465 var S = new forge.util.ByteBuffer(); 17466 for(l = 0; l < Slen; l ++) { 17467 S.putByte(salt.at(l % s)); 17468 } 17469 17470 /* 3. Concatenate copies of the password together to create a string P of 17471 length v * ceil(p / v) bytes (the final copy of the password may be 17472 truncated to create P). 17473 Note that if the password is the empty string, then so is P. */ 17474 var Plen = v * Math.ceil(p / v); 17475 var P = new forge.util.ByteBuffer(); 17476 for(l = 0; l < Plen; l ++) { 17477 P.putByte(passBuf.at(l % p)); 17478 } 17479 17480 /* 4. Set I=S||P to be the concatenation of S and P. */ 17481 var I = S; 17482 I.putBuffer(P); 17483 17484 /* 5. Set c=ceil(n / u). */ 17485 var c = Math.ceil(n / u); 17486 17487 /* 6. For i=1, 2, ..., c, do the following: */ 17488 for(var i = 1; i <= c; i ++) { 17489 /* a) Set Ai=H^r(D||I). (l.e. the rth hash of D||I, H(H(H(...H(D||I)))) */ 17490 var buf = new forge.util.ByteBuffer(); 17491 buf.putBytes(D.bytes()); 17492 buf.putBytes(I.bytes());
17493 for(var round = 0; round < iter; round ++) { 17494 md.start(); 17495 md.update(buf.getBytes()); 17496 buf = md.digest(); 17497 } 17498 17499 /* b) Concatenate copies of Ai to create a string B of length v bytes (the 17500 final copy of Ai may be truncated to create B). */ 17501 var B = new forge.util.ByteBuffer(); 17502 for(l = 0; l < v; l ++) { 17503 B.putByte(buf.at(l % u)); 17504 } 17505 17506 /* c) Treating I as a concatenation I0, I1, ..., Ik-1 of v-byte blocks, 17507 where k=ceil(s / v) + ceil(p / v), modify I by setting 17508 Ij=(Ij+B+1) mod 2v for each j. */ 17509 var k = Math.ceil(s / v) + Math.ceil(p / v); 17510 var Inew = new forge.util.ByteBuffer(); 17511 for(j = 0; j < k; j ++) { 17512 var chunk = new forge.util.ByteBuffer(I.getBytes(v)); 17513 var x = 0x1ff; 17514 for(l = B.length() - 1; l >= 0; l --) { 17515 x = x >> 8; 17516 x += B.at(l) + chunk.at(l); 17517 chunk.setAt(l, x & 0xff); 17518 } 17519 Inew.putBuffer(chunk); 17520 } 17521 I = Inew; 17522 17523 /* Add Ai to A. */ 17524 result.putBuffer(buf); 17525 } 17526 17527 result.truncate(result.length() - n); 17528 return result; 17529}; 17530 17531/** 17532 * Get new Forge cipher object instance. 17533 * 17534 * @param oid the OID (in string notation). 17535 * @param params the ASN.1 params object. 17536 * @param password the password to decrypt with. 17537 * 17538 * @return new cipher object instance. 17539 */ 17540pki.pbe.getCipher = function(oid, params, password) { 17541 switch(oid) { 17542 case pki.oids['pkcs5PBES2']: 17543 return pki.pbe.getCipherForPBES2(oid, params, password); 17544 17545 case pki.oids['pbeWithSHAAnd3-KeyTripleDES-CBC']: 17546 case pki.oids['pbewithSHAAnd40BitRC2-CBC']: 17547 return pki.pbe.getCipherForPKCS12PBE(oid, params, password); 17548 17549 default: 17550 var error = new Error('Cannot read encrypted PBE data block. Unsupported OID.'); 17551 error.oid = oid; 17552 error.supportedOids = [ 17553 'pkcs5PBES2', 17554 'pbeWithSHAAnd3-KeyTripleDES-CBC', 17555 'pbewithSHAAnd40BitRC2-CBC' 17556 ]; 17557 throw error; 17558 } 17559}; 17560 17561/** 17562 * Get new Forge cipher object instance according to PBES2 params block. 17563 * 17564 * The returned cipher instance is already started using the IV 17565 * from PBES2 parameter block. 17566 * 17567 * @param oid the PKCS#5 PBKDF2 OID (in string notation). 17568 * @param params the ASN.1 PBES2-params object. 17569 * @param password the password to decrypt with. 17570 * 17571 * @return new cipher object instance. 17572 */ 17573pki.pbe.getCipherForPBES2 = function(oid, params, password) { 17574 // get PBE params 17575 var capture = {}; 17576 var errors = []; 17577 if(!asn1.validate(params, PBES2AlgorithmsValidator, capture, errors)) { 17578 var error = new Error('Cannot read password-based-encryption algorithm ' + 17579 'parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo.'); 17580 error.errors = errors; 17581 throw error; 17582 } 17583 17584 // check oids 17585 oid = asn1.derToOid(capture.kdfOid); 17586 if(oid !== pki.oids['pkcs5PBKDF2']) { 17587 var error = new Error('Cannot read encrypted private key. ' + 17588 'Unsupported key derivation function OID.'); 17589 error.oid = oid; 17590 error.supportedOids = ['pkcs5PBKDF2']; 17591 throw error; 17592 } 17593 oid = asn1.derToOid(capture.encOid); 17594 if(oid !== pki.oids['aes128-CBC'] && 17595 oid !== pki.oids['aes192-CBC'] && 17596 oid !== pki.oids['aes256-CBC'] && 17597 oid !== pki.oids['des-EDE3-CBC'] && 17598 oid !== pki.oids['desCBC']) { 17599 var error = new Error('Cannot read encrypted private key. ' + 17600 'Unsupported encryption scheme OID.'); 17601 error.oid = oid; 17602 error.supportedOids = [ 17603 'aes128-CBC', 'aes192-CBC', 'aes256-CBC', 'des-EDE3-CBC', 'desCBC']; 17604 throw error; 17605 } 17606 17607 // set PBE params 17608 var salt = capture.kdfSalt; 17609 var count = forge.util.createBuffer(capture.kdfIterationCount); 17610 count = count.getInt(count.length() << 3); 17611 var dkLen; 17612 var cipherFn; 17613 switch(pki.oids[oid]) { 17614 case 'aes128-CBC': 17615 dkLen = 16; 17616 cipherFn = forge.aes.createDecryptionCipher; 17617 break; 17618 case 'aes192-CBC': 17619 dkLen = 24; 17620 cipherFn = forge.aes.createDecryptionCipher; 17621 break; 17622 case 'aes256-CBC': 17623 dkLen = 32; 17624 cipherFn = forge.aes.createDecryptionCipher; 17625 break; 17626 case 'des-EDE3-CBC': 17627 dkLen = 24; 17628 cipherFn = forge.des.createDecryptionCipher; 17629 break; 17630 case 'desCBC': 17631 dkLen = 8; 17632 cipherFn = forge.des.createDecryptionCipher; 17633 break; 17634 } 17635 17636 // get PRF message digest 17637 var md = prfOidToMessageDigest(capture.prfOid); 17638 17639 // decrypt private key using pbe with chosen PRF and AES/DES 17640 var dk = forge.pkcs5.pbkdf2(password, salt, count, dkLen, md); 17641 var iv = capture.encIv; 17642 var cipher = cipherFn(dk); 17643 cipher.start(iv); 17644 17645 return cipher; 17646}; 17647 17648/** 17649 * Get new Forge cipher object instance for PKCS#12 PBE. 17650 * 17651 * The returned cipher instance is already started using the key & IV 17652 * derived from the provided password and PKCS#12 PBE salt. 17653 * 17654 * @param oid The PKCS#12 PBE OID (in string notation). 17655 * @param params The ASN.1 PKCS#12 PBE-params object. 17656 * @param password The password to decrypt with. 17657 * 17658 * @return the new cipher object instance. 17659 */ 17660pki.pbe.getCipherForPKCS12PBE = function(oid, params, password) { 17661 // get PBE params 17662 var capture = {}; 17663 var errors = [];
17664 if(!asn1.validate(params, pkcs12PbeParamsValidator, capture, errors)) { 17665 var error = new Error('Cannot read password-based-encryption algorithm ' + 17666 'parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo.'); 17667 error.errors = errors; 17668 throw error; 17669 } 17670 17671 var salt = forge.util.createBuffer(capture.salt); 17672 var count = forge.util.createBuffer(capture.iterations); 17673 count = count.getInt(count.length() << 3); 17674 17675 var dkLen, dIvLen, cipherFn; 17676 switch(oid) { 17677 case pki.oids['pbeWithSHAAnd3-KeyTripleDES-CBC']: 17678 dkLen = 24; 17679 dIvLen = 8; 17680 cipherFn = forge.des.startDecrypting; 17681 break; 17682 17683 case pki.oids['pbewithSHAAnd40BitRC2-CBC']: 17684 dkLen = 5; 17685 dIvLen = 8; 17686 cipherFn = function(key, iv) { 17687 var cipher = forge.rc2.createDecryptionCipher(key, 40); 17688 cipher.start(iv, null); 17689 return cipher; 17690 }; 17691 break; 17692 17693 default: 17694 var error = new Error('Cannot read PKCS #12 PBE data block. Unsupported OID.'); 17695 error.oid = oid; 17696 throw error; 17697 } 17698 17699 // get PRF message digest 17700 var md = prfOidToMessageDigest(capture.prfOid); 17701 var key = pki.pbe.generatePkcs12Key(password, salt, 1, count, dkLen, md); 17702 md.start(); 17703 var iv = pki.pbe.generatePkcs12Key(password, salt, 2, count, dIvLen, md); 17704 17705 return cipherFn(key, iv); 17706}; 17707 17708/** 17709 * OpenSSL's legacy key derivation function. 17710 * 17711 * See: http://www.openssl.org/docs/crypto/EVP_BytesToKey.html 17712 * 17713 * @param password the password to derive the key from. 17714 * @param salt the salt to use, null for none. 17715 * @param dkLen the number of bytes needed for the derived key. 17716 * @param [options] the options to use: 17717 * [md] an optional message digest object to use. 17718 */ 17719pki.pbe.opensslDeriveBytes = function(password, salt, dkLen, md) { 17720 if(typeof md === 'undefined' || md === null) { 17721 md = forge.md.md5.create(); 17722 } 17723 if(salt === null) { 17724 salt = ''; 17725 } 17726 var digests = [hash(md, password + salt)]; 17727 for(var length = 16, i = 1; length < dkLen; ++i, length += 16) { 17728 digests.push(hash(md, digests[i - 1] + password + salt)); 17729 } 17730 return digests.join('').substr(0, dkLen); 17731}; 17732 17733function hash(md, bytes) { 17734 return md.start().update(bytes).digest().getBytes(); 17735} 17736 17737function prfOidToMessageDigest(prfOid) { 17738 // get PRF algorithm, default to SHA-1 17739 var prfAlgorithm; 17740 if(!prfOid) { 17741 prfAlgorithm = 'hmacWithSHA1'; 17742 } else { 17743 prfAlgorithm = pki.oids[asn1.derToOid(prfOid)]; 17744 if(!prfAlgorithm) { 17745 var error = new Error('Unsupported PRF OID.'); 17746 error.oid = prfOid; 17747 error.supported = [ 17748 'hmacWithSHA1', 'hmacWithSHA224', 'hmacWithSHA256', 'hmacWithSHA384', 17749 'hmacWithSHA512']; 17750 throw error; 17751 } 17752 } 17753 return prfAlgorithmToMessageDigest(prfAlgorithm); 17754} 17755 17756function prfAlgorithmToMessageDigest(prfAlgorithm) { 17757 var factory = forge.md; 17758 switch(prfAlgorithm) { 17759 case 'hmacWithSHA224': 17760 factory = forge.md.sha512; 17761 case 'hmacWithSHA1': 17762 case 'hmacWithSHA256': 17763 case 'hmacWithSHA384': 17764 case 'hmacWithSHA512': 17765 prfAlgorithm = prfAlgorithm.substr(8).toLowerCase(); 17766 break; 17767 default: 17768 var error = new Error('Unsupported PRF algorithm.'); 17769 error.algorithm = prfAlgorithm; 17770 error.supported = [ 17771 'hmacWithSHA1', 'hmacWithSHA224', 'hmacWithSHA256', 'hmacWithSHA384', 17772 'hmacWithSHA512']; 17773 throw error; 17774 } 17775 return factory[prfAlgorithm].create(); 17776} 17777 17778function createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm) { 17779 var params = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17780 // salt 17781 asn1.create( 17782 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, salt), 17783 // iteration count 17784 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 17785 countBytes.getBytes()) 17786 ]); 17787 // when PRF algorithm is not SHA-1 default, add key length and PRF algorithm 17788 if(prfAlgorithm !== 'hmacWithSHA1') { 17789 params.value.push( 17790 // key length 17791 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 17792 forge.util.hexToBytes(dkLen.toString(16))), 17793 // AlgorithmIdentifier 17794 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 17795 // algorithm 17796 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 17797 asn1.oidToDer(pki.oids[prfAlgorithm]).getBytes()), 17798 // parameters (null) 17799 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 17800 ])); 17801 } 17802 return params; 17803} 17804 17805} // end module implementation 17806 17807/* ########## Begin module wrapper ########## */ 17808var name = 'pbe'; 17809if(typeof define !== 'function') { 17810 // NodeJS -> AMD 17811 if(typeof module === 'object' && module.exports) { 17812 var nodeJS = true; 17813 define = function(ids, factory) { 17814 factory(require, module); 17815 }; 17816 } else { 17817 // <script> 17818 if(typeof forge === 'undefined') { 17819 forge = {}; 17820 } 17821 return initModule(forge); 17822 } 17823} 17824// AMD 17825var deps;
17826var defineFunc = function(require, module) { 17827 module.exports = function(forge) { 17828 var mods = deps.map(function(dep) { 17829 return require(dep); 17830 }).concat(initModule); 17831 // handle circular dependencies 17832 forge = forge || {}; 17833 forge.defined = forge.defined || {}; 17834 if(forge.defined[name]) { 17835 return forge[name]; 17836 } 17837 forge.defined[name] = true; 17838 for(var i = 0; i < mods.length; ++i) { 17839 mods[i](forge); 17840 } 17841 return forge[name]; 17842 }; 17843}; 17844var tmpDefine = define; 17845define = function(ids, factory) { 17846 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 17847 if(nodeJS) { 17848 delete define; 17849 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 17850 } 17851 define = tmpDefine; 17852 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 17853}; 17854define([ 17855 'require', 17856 'module', 17857 './aes', 17858 './asn1', 17859 './des', 17860 './md', 17861 './oids', 17862 './pem', 17863 './pbkdf2', 17864 './random', 17865 './rc2', 17866 './rsa', 17867 './util' 17868], function() { 17869 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 17870}); 17871})(); 17872 17873/** 17874 * Hash-based Message Authentication Code implementation. Requires a message 17875 * digest object that can be obtained, for example, from forge.md.sha1 or 17876 * forge.md.md5. 17877 * 17878 * @author Dave Longley 17879 * 17880 * Copyright (c) 2010-2012 Digital Bazaar, Inc. All rights reserved. 17881 */ 17882(function() { 17883/* ########## Begin module implementation ########## */ 17884function initModule(forge) { 17885 17886/* HMAC API */ 17887var hmac = forge.hmac = forge.hmac || {}; 17888 17889/** 17890 * Creates an HMAC object that uses the given message digest object. 17891 * 17892 * @return an HMAC object. 17893 */ 17894hmac.create = function() { 17895 // the hmac key to use 17896 var _key = null; 17897 17898 // the message digest to use 17899 var _md = null; 17900 17901 // the inner padding 17902 var _ipadding = null; 17903 17904 // the outer padding 17905 var _opadding = null; 17906 17907 // hmac context 17908 var ctx = {}; 17909 17910 /** 17911 * Starts or restarts the HMAC with the given key and message digest. 17912 * 17913 * @param md the message digest to use, null to reuse the previous one, 17914 * a string to use builtin 'sha1', 'md5', 'sha256'. 17915 * @param key the key to use as a string, array of bytes, byte buffer, 17916 * or null to reuse the previous key. 17917 */ 17918 ctx.start = function(md, key) { 17919 if(md !== null) { 17920 if(typeof md === 'string') { 17921 // create builtin message digest 17922 md = md.toLowerCase(); 17923 if(md in forge.md.algorithms) { 17924 _md = forge.md.algorithms[md].create(); 17925 } else { 17926 throw new Error('Unknown hash algorithm "' + md + '"'); 17927 } 17928 } else { 17929 // store message digest 17930 _md = md; 17931 } 17932 } 17933 17934 if(key === null) { 17935 // reuse previous key 17936 key = _key; 17937 } else { 17938 if(typeof key === 'string') { 17939 // convert string into byte buffer 17940 key = forge.util.createBuffer(key); 17941 } else if(forge.util.isArray(key)) { 17942 // convert byte array into byte buffer 17943 var tmp = key; 17944 key = forge.util.createBuffer(); 17945 for(var i = 0; i < tmp.length; ++i) { 17946 key.putByte(tmp[i]); 17947 } 17948 } 17949 17950 // if key is longer than blocksize, hash it 17951 var keylen = key.length(); 17952 if(keylen > _md.blockLength) { 17953 _md.start(); 17954 _md.update(key.bytes()); 17955 key = _md.digest(); 17956 } 17957 17958 // mix key into inner and outer padding 17959 // ipadding = [0x36 * blocksize] ^ key 17960 // opadding = [0x5C * blocksize] ^ key 17961 _ipadding = forge.util.createBuffer(); 17962 _opadding = forge.util.createBuffer(); 17963 keylen = key.length(); 17964 for(var i = 0; i < keylen; ++i) { 17965 var tmp = key.at(i); 17966 _ipadding.putByte(0x36 ^ tmp); 17967 _opadding.putByte(0x5C ^ tmp); 17968 } 17969 17970 // if key is shorter than blocksize, add additional padding 17971 if(keylen < _md.blockLength) { 17972 var tmp = _md.blockLength - keylen; 17973 for(var i = 0; i < tmp; ++i) { 17974 _ipadding.putByte(0x36); 17975 _opadding.putByte(0x5C); 17976 } 17977 } 17978 _key = key; 17979 _ipadding = _ipadding.bytes(); 17980 _opadding = _opadding.bytes(); 17981 } 17982 17983 // digest is done like so: hash(opadding | hash(ipadding | message)) 17984 17985 // prepare to do inner hash 17986 // hash(ipadding | message) 17987 _md.start(); 17988 _md.update(_ipadding); 17989 }; 17990 17991 /** 17992 * Updates the HMAC with the given message bytes. 17993 * 17994 * @param bytes the bytes to update with. 17995 */ 17996 ctx.update = function(bytes) { 17997 _md.update(bytes); 17998 }; 17999 18000 /** 18001 * Produces the Message Authentication Code (MAC). 18002 * 18003 * @return a byte buffer containing the digest value. 18004 */ 18005 ctx.getMac = function() { 18006 // digest is done like so: hash(opadding | hash(ipadding | message)) 18007 // here we do the outer hashing 18008 var inner = _md.digest().bytes(); 18009 _md.start(); 18010 _md.update(_opadding); 18011 _md.update(inner); 18012 return _md.digest(); 18013 }; 18014 // alias for getMac 18015 ctx.digest = ctx.getMac; 18016 18017 return ctx; 18018}; 18019 18020} // end module implementation 18021 18022/* ########## Begin module wrapper ########## */ 18023var name = 'hmac'; 18024if(typeof define !== 'function') { 18025 // NodeJS -> AMD 18026 if(typeof module === 'object' && module.exports) { 18027 var nodeJS = true; 18028 define = function(ids, factory) { 18029 factory(require, module); 18030 }; 18031 } else { 18032 // <script> 18033 if(typeof forge === 'undefined') { 18034 forge = {}; 18035 } 18036 return initModule(forge); 18037 } 18038} 18039// AMD 18040var deps;
18041var defineFunc = function(require, module) { 18042 module.exports = function(forge) { 18043 var mods = deps.map(function(dep) { 18044 return require(dep); 18045 }).concat(initModule); 18046 // handle circular dependencies 18047 forge = forge || {}; 18048 forge.defined = forge.defined || {}; 18049 if(forge.defined[name]) { 18050 return forge[name]; 18051 } 18052 forge.defined[name] = true; 18053 for(var i = 0; i < mods.length; ++i) { 18054 mods[i](forge); 18055 } 18056 return forge[name]; 18057 }; 18058}; 18059var tmpDefine = define; 18060define = function(ids, factory) { 18061 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 18062 if(nodeJS) { 18063 delete define; 18064 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 18065 } 18066 define = tmpDefine; 18067 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 18068}; 18069define(['require', 'module', './md', './util'], function() { 18070 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 18071}); 18072})(); 18073 18074/** 18075 * Password-Based Key-Derivation Function #2 implementation. 18076 * 18077 * See RFC 2898 for details. 18078 * 18079 * @author Dave Longley 18080 * 18081 * Copyright (c) 2010-2013 Digital Bazaar, Inc. 18082 */ 18083(function() { 18084/* ########## Begin module implementation ########## */ 18085function initModule(forge) { 18086 18087var pkcs5 = forge.pkcs5 = forge.pkcs5 || {}; 18088 18089var _nodejs = ( 18090 typeof process !== 'undefined' && process.versions && process.versions.node); 18091var crypto; 18092if(_nodejs && !forge.disableNativeCode) { 18093 crypto = require('crypto'); 18094} 18095 18096/** 18097 * Derives a key from a password. 18098 * 18099 * @param p the password as a binary-encoded string of bytes. 18100 * @param s the salt as a binary-encoded string of bytes. 18101 * @param c the iteration count, a positive integer. 18102 * @param dkLen the intended length, in bytes, of the derived key, 18103 * (max: 2^32 - 1) * hash length of the PRF. 18104 * @param [md] the message digest (or algorithm identifier as a string) to use 18105 * in the PRF, defaults to SHA-1. 18106 * @param [callback(err, key)] presence triggers asynchronous version, called 18107 * once the operation completes. 18108 * 18109 * @return the derived key, as a binary-encoded string of bytes, for the 18110 * synchronous version (if no callback is specified). 18111 */ 18112forge.pbkdf2 = pkcs5.pbkdf2 = function(p, s, c, dkLen, md, callback) { 18113 if(typeof md === 'function') { 18114 callback = md; 18115 md = null; 18116 } 18117 18118 // use native implementation if possible and not disabled, note that 18119 // some node versions only support SHA-1, others allow digest to be changed 18120 if(_nodejs && !forge.disableNativeCode && crypto.pbkdf2 && 18121 (md === null || typeof md !== 'object') && 18122 (crypto.pbkdf2Sync.length > 4 || (!md || md === 'sha1'))) { 18123 if(typeof md !== 'string') { 18124 // default prf to SHA-1 18125 md = 'sha1'; 18126 } 18127 s = new Buffer(s, 'binary'); 18128 if(!callback) { 18129 if(crypto.pbkdf2Sync.length === 4) { 18130 return crypto.pbkdf2Sync(p, s, c, dkLen).toString('binary'); 18131 } 18132 return crypto.pbkdf2Sync(p, s, c, dkLen, md).toString('binary'); 18133 } 18134 if(crypto.pbkdf2Sync.length === 4) { 18135 return crypto.pbkdf2(p, s, c, dkLen, function(err, key) { 18136 if(err) { 18137 return callback(err); 18138 } 18139 callback(null, key.toString('binary')); 18140 }); 18141 } 18142 return crypto.pbkdf2(p, s, c, dkLen, md, function(err, key) { 18143 if(err) { 18144 return callback(err); 18145 } 18146 callback(null, key.toString('binary')); 18147 }); 18148 } 18149 18150 if(typeof md === 'undefined' || md === null) { 18151 // default prf to SHA-1 18152 md = forge.md.sha1.create(); 18153 } 18154 if(typeof md === 'string') { 18155 if(!(md in forge.md.algorithms)) { 18156 throw new Error('Unknown hash algorithm: ' + md); 18157 } 18158 md = forge.md[md].create(); 18159 } 18160 18161 var hLen = md.digestLength; 18162 18163 /* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and 18164 stop. */ 18165 if(dkLen > (0xFFFFFFFF * hLen)) { 18166 var err = new Error('Derived key is too long.'); 18167 if(callback) { 18168 return callback(err); 18169 } 18170 throw err; 18171 } 18172 18173 /* 2. Let len be the number of hLen-octet blocks in the derived key, 18174 rounding up, and let r be the number of octets in the last 18175 block: 18176 18177 len = CEIL(dkLen / hLen), 18178 r = dkLen - (len - 1) * hLen. */
18179 var len = Math.ceil(dkLen / hLen); 18180 var r = dkLen - (len - 1) * hLen; 18181 18182 /* 3. For each block of the derived key apply the function F defined 18183 below to the password P, the salt S, the iteration count c, and 18184 the block index to compute the block: 18185 18186 T_1 = F(P, S, c, 1), 18187 T_2 = F(P, S, c, 2), 18188 ... 18189 T_len = F(P, S, c, len), 18190 18191 where the function F is defined as the exclusive-or sum of the 18192 first c iterates of the underlying pseudorandom function PRF 18193 applied to the password P and the concatenation of the salt S 18194 and the block index i: 18195 18196 F(P, S, c, i) = u_1 XOR u_2 XOR ... XOR u_c 18197 18198 where 18199 18200 u_1 = PRF(P, S || INT(i)), 18201 u_2 = PRF(P, u_1), 18202 ... 18203 u_c = PRF(P, u_{c-1}). 18204 18205 Here, INT(i) is a four-octet encoding of the integer i, most 18206 significant octet first. */ 18207 var prf = forge.hmac.create(); 18208 prf.start(md, p); 18209 var dk = ''; 18210 var xor, u_c, u_c1; 18211 18212 // sync version 18213 if(!callback) { 18214 for(var i = 1; i <= len; ++i) { 18215 // PRF(P, S || INT(i)) (first iteration) 18216 prf.start(null, null); 18217 prf.update(s); 18218 prf.update(forge.util.int32ToBytes(i)); 18219 xor = u_c1 = prf.digest().getBytes(); 18220 18221 // PRF(P, u_{c-1}) (other iterations) 18222 for(var j = 2; j <= c; ++j) { 18223 prf.start(null, null); 18224 prf.update(u_c1); 18225 u_c = prf.digest().getBytes(); 18226 // F(p, s, c, i) 18227 xor = forge.util.xorBytes(xor, u_c, hLen); 18228 u_c1 = u_c; 18229 } 18230 18231 /* 4. Concatenate the blocks and extract the first dkLen octets to 18232 produce a derived key DK: 18233 18234 DK = T_1 || T_2 || ... || T_len<0..r-1> */ 18235 dk += (i < len) ? xor : xor.substr(0, r); 18236 } 18237 /* 5. Output the derived key DK. */ 18238 return dk; 18239 } 18240 18241 // async version 18242 var i = 1, j; 18243 function outer() { 18244 if(i > len) { 18245 // done 18246 return callback(null, dk); 18247 } 18248 18249 // PRF(P, S || INT(i)) (first iteration) 18250 prf.start(null, null); 18251 prf.update(s); 18252 prf.update(forge.util.int32ToBytes(i)); 18253 xor = u_c1 = prf.digest().getBytes(); 18254 18255 // PRF(P, u_{c-1}) (other iterations) 18256 j = 2; 18257 inner(); 18258 } 18259 18260 function inner() { 18261 if(j <= c) { 18262 prf.start(null, null); 18263 prf.update(u_c1); 18264 u_c = prf.digest().getBytes(); 18265 // F(p, s, c, i) 18266 xor = forge.util.xorBytes(xor, u_c, hLen); 18267 u_c1 = u_c; 18268 ++j; 18269 return forge.util.setImmediate(inner); 18270 } 18271 18272 /* 4. Concatenate the blocks and extract the first dkLen octets to 18273 produce a derived key DK: 18274 18275 DK = T_1 || T_2 || ... || T_len<0..r-1> */ 18276 dk += (i < len) ? xor : xor.substr(0, r); 18277 18278 ++i; 18279 outer(); 18280 } 18281 18282 outer(); 18283}; 18284 18285} // end module implementation 18286 18287/* ########## Begin module wrapper ########## */ 18288var name = 'pbkdf2'; 18289if(typeof define !== 'function') { 18290 // NodeJS -> AMD 18291 if(typeof module === 'object' && module.exports) { 18292 var nodeJS = true; 18293 define = function(ids, factory) { 18294 factory(require, module); 18295 }; 18296 } else { 18297 // <script> 18298 if(typeof forge === 'undefined') { 18299 forge = {}; 18300 } 18301 return initModule(forge); 18302 } 18303} 18304// AMD 18305var deps; 18306var defineFunc = function(require, module) { 18307 module.exports = function(forge) { 18308 var mods = deps.map(function(dep) { 18309 return require(dep); 18310 }).concat(initModule); 18311 // handle circular dependencies 18312 forge = forge || {}; 18313 forge.defined = forge.defined || {}; 18314 if(forge.defined[name]) { 18315 return forge[name]; 18316 } 18317 forge.defined[name] = true; 18318 for(var i = 0; i < mods.length; ++i) { 18319 mods[i](forge); 18320 } 18321 return forge[name]; 18322 }; 18323}; 18324var tmpDefine = define; 18325define = function(ids, factory) { 18326 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 18327 if(nodeJS) { 18328 delete define; 18329 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 18330 } 18331 define = tmpDefine; 18332 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 18333}; 18334define(['require', 'module', './hmac', './md', './util'], function() { 18335 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 18336}); 18337})(); 18338 18339/** 18340 * Javascript implementation of PKCS#12. 18341 * 18342 * @author Dave Longley 18343 * @author Stefan Siegl <[email protected]> 18344 * 18345 * Copyright (c) 2010-2014 Digital Bazaar, Inc. 18346 * Copyright (c) 2012 Stefan Siegl <[email protected]> 18347 * 18348 * The ASN.1 representation of PKCS#12 is as follows 18349 * (see ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12-tc1.pdf for details) 18350 * 18351 * PFX ::= SEQUENCE { 18352 * version INTEGER {v3(3)}(v3,...), 18353 * authSafe ContentInfo, 18354 * macData MacData OPTIONAL 18355 * } 18356 * 18357 * MacData ::= SEQUENCE { 18358 * mac DigestInfo, 18359 * macSalt OCTET STRING, 18360 * iterations INTEGER DEFAULT 1 18361 * } 18362 * Note: The iterations default is for historical reasons and its use is 18363 * deprecated. A higher value, like 1024, is recommended.
18364 * 18365 * DigestInfo is defined in PKCS#7 as follows: 18366 * 18367 * DigestInfo ::= SEQUENCE { 18368 * digestAlgorithm DigestAlgorithmIdentifier, 18369 * digest Digest 18370 * } 18371 * 18372 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 18373 * 18374 * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters 18375 * for the algorithm, if any. In the case of SHA1 there is none. 18376 * 18377 * AlgorithmIdentifer ::= SEQUENCE { 18378 * algorithm OBJECT IDENTIFIER, 18379 * parameters ANY DEFINED BY algorithm OPTIONAL 18380 * } 18381 * 18382 * Digest ::= OCTET STRING 18383 * 18384 * 18385 * ContentInfo ::= SEQUENCE { 18386 * contentType ContentType, 18387 * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL 18388 * } 18389 * 18390 * ContentType ::= OBJECT IDENTIFIER 18391 * 18392 * AuthenticatedSafe ::= SEQUENCE OF ContentInfo 18393 * -- Data if unencrypted 18394 * -- EncryptedData if password-encrypted 18395 * -- EnvelopedData if public key-encrypted 18396 * 18397 * 18398 * SafeContents ::= SEQUENCE OF SafeBag 18399 * 18400 * SafeBag ::= SEQUENCE { 18401 * bagId BAG-TYPE.&id ({PKCS12BagSet}) 18402 * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}), 18403 * bagAttributes SET OF PKCS12Attribute OPTIONAL 18404 * } 18405 * 18406 * PKCS12Attribute ::= SEQUENCE { 18407 * attrId ATTRIBUTE.&id ({PKCS12AttrSet}), 18408 * attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId}) 18409 * } -- This type is compatible with the X.500 type �Attribute� 18410 * 18411 * PKCS12AttrSet ATTRIBUTE ::= { 18412 * friendlyName | -- from PKCS #9 18413 * localKeyId, -- from PKCS #9 18414 * ... -- Other attributes are allowed 18415 * } 18416 * 18417 * CertBag ::= SEQUENCE { 18418 * certId BAG-TYPE.&id ({CertTypes}), 18419 * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) 18420 * } 18421 * 18422 * x509Certificate BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1}} 18423 * -- DER-encoded X.509 certificate stored in OCTET STRING 18424 * 18425 * sdsiCertificate BAG-TYPE ::= {IA5String IDENTIFIED BY {certTypes 2}} 18426 * -- Base64-encoded SDSI certificate stored in IA5String 18427 * 18428 * CertTypes BAG-TYPE ::= { 18429 * x509Certificate | 18430 * sdsiCertificate, 18431 * ... -- For future extensions 18432 * } 18433 */ 18434(function() { 18435/* ########## Begin module implementation ########## */ 18436function initModule(forge) { 18437 18438// shortcut for asn.1 & PKI API 18439var asn1 = forge.asn1; 18440var pki = forge.pki; 18441 18442// shortcut for PKCS#12 API 18443var p12 = forge.pkcs12 = forge.pkcs12 || {}; 18444 18445var contentInfoValidator = { 18446 name: 'ContentInfo', 18447 tagClass: asn1.Class.UNIVERSAL, 18448 type: asn1.Type.SEQUENCE, // a ContentInfo 18449 constructed: true, 18450 value: [{ 18451 name: 'ContentInfo.contentType', 18452 tagClass: asn1.Class.UNIVERSAL, 18453 type: asn1.Type.OID, 18454 constructed: false, 18455 capture: 'contentType' 18456 }, { 18457 name: 'ContentInfo.content', 18458 tagClass: asn1.Class.CONTEXT_SPECIFIC, 18459 constructed: true, 18460 captureAsn1: 'content' 18461 }] 18462}; 18463 18464var pfxValidator = { 18465 name: 'PFX', 18466 tagClass: asn1.Class.UNIVERSAL, 18467 type: asn1.Type.SEQUENCE, 18468 constructed: true, 18469 value: [{ 18470 name: 'PFX.version', 18471 tagClass: asn1.Class.UNIVERSAL, 18472 type: asn1.Type.INTEGER, 18473 constructed: false, 18474 capture: 'version' 18475 }, 18476 contentInfoValidator, { 18477 name: 'PFX.macData', 18478 tagClass: asn1.Class.UNIVERSAL, 18479 type: asn1.Type.SEQUENCE, 18480 constructed: true, 18481 optional: true, 18482 captureAsn1: 'mac', 18483 value: [{ 18484 name: 'PFX.macData.mac', 18485 tagClass: asn1.Class.UNIVERSAL, 18486 type: asn1.Type.SEQUENCE, // DigestInfo 18487 constructed: true, 18488 value: [{ 18489 name: 'PFX.macData.mac.digestAlgorithm', 18490 tagClass: asn1.Class.UNIVERSAL, 18491 type: asn1.Type.SEQUENCE, // DigestAlgorithmIdentifier 18492 constructed: true, 18493 value: [{ 18494 name: 'PFX.macData.mac.digestAlgorithm.algorithm', 18495 tagClass: asn1.Class.UNIVERSAL, 18496 type: asn1.Type.OID, 18497 constructed: false, 18498 capture: 'macAlgorithm' 18499 }, { 18500 name: 'PFX.macData.mac.digestAlgorithm.parameters', 18501 tagClass: asn1.Class.UNIVERSAL, 18502 captureAsn1: 'macAlgorithmParameters' 18503 }] 18504 }, { 18505 name: 'PFX.macData.mac.digest', 18506 tagClass: asn1.Class.UNIVERSAL, 18507 type: asn1.Type.OCTETSTRING, 18508 constructed: false, 18509 capture: 'macDigest' 18510 }] 18511 }, {
18512 name: 'PFX.macData.macSalt', 18513 tagClass: asn1.Class.UNIVERSAL, 18514 type: asn1.Type.OCTETSTRING, 18515 constructed: false, 18516 capture: 'macSalt' 18517 }, { 18518 name: 'PFX.macData.iterations', 18519 tagClass: asn1.Class.UNIVERSAL, 18520 type: asn1.Type.INTEGER, 18521 constructed: false, 18522 optional: true, 18523 capture: 'macIterations' 18524 }] 18525 }] 18526}; 18527 18528var safeBagValidator = { 18529 name: 'SafeBag', 18530 tagClass: asn1.Class.UNIVERSAL, 18531 type: asn1.Type.SEQUENCE, 18532 constructed: true, 18533 value: [{ 18534 name: 'SafeBag.bagId', 18535 tagClass: asn1.Class.UNIVERSAL, 18536 type: asn1.Type.OID, 18537 constructed: false, 18538 capture: 'bagId' 18539 }, { 18540 name: 'SafeBag.bagValue', 18541 tagClass: asn1.Class.CONTEXT_SPECIFIC, 18542 constructed: true, 18543 captureAsn1: 'bagValue' 18544 }, { 18545 name: 'SafeBag.bagAttributes', 18546 tagClass: asn1.Class.UNIVERSAL, 18547 type: asn1.Type.SET, 18548 constructed: true, 18549 optional: true, 18550 capture: 'bagAttributes' 18551 }] 18552}; 18553 18554var attributeValidator = { 18555 name: 'Attribute', 18556 tagClass: asn1.Class.UNIVERSAL, 18557 type: asn1.Type.SEQUENCE, 18558 constructed: true, 18559 value: [{ 18560 name: 'Attribute.attrId', 18561 tagClass: asn1.Class.UNIVERSAL, 18562 type: asn1.Type.OID, 18563 constructed: false, 18564 capture: 'oid' 18565 }, { 18566 name: 'Attribute.attrValues', 18567 tagClass: asn1.Class.UNIVERSAL, 18568 type: asn1.Type.SET, 18569 constructed: true, 18570 capture: 'values' 18571 }] 18572}; 18573 18574var certBagValidator = { 18575 name: 'CertBag', 18576 tagClass: asn1.Class.UNIVERSAL, 18577 type: asn1.Type.SEQUENCE, 18578 constructed: true, 18579 value: [{ 18580 name: 'CertBag.certId', 18581 tagClass: asn1.Class.UNIVERSAL, 18582 type: asn1.Type.OID, 18583 constructed: false, 18584 capture: 'certId' 18585 }, { 18586 name: 'CertBag.certValue', 18587 tagClass: asn1.Class.CONTEXT_SPECIFIC, 18588 constructed: true, 18589 /* So far we only support X.509 certificates (which are wrapped in 18590 an OCTET STRING, hence hard code that here). */ 18591 value: [{ 18592 name: 'CertBag.certValue[0]', 18593 tagClass: asn1.Class.UNIVERSAL, 18594 type: asn1.Class.OCTETSTRING, 18595 constructed: false, 18596 capture: 'cert' 18597 }] 18598 }] 18599}; 18600 18601/** 18602 * Search SafeContents structure for bags with matching attributes. 18603 * 18604 * The search can optionally be narrowed by a certain bag type. 18605 * 18606 * @param safeContents the SafeContents structure to search in. 18607 * @param attrName the name of the attribute to compare against. 18608 * @param attrValue the attribute value to search for. 18609 * @param [bagType] bag type to narrow search by. 18610 * 18611 * @return an array of matching bags. 18612 */
18613function _getBagsByAttribute(safeContents, attrName, attrValue, bagType) { 18614 var result = []; 18615 18616 for(var i = 0; i < safeContents.length; i ++) { 18617 for(var j = 0; j < safeContents[i].safeBags.length; j ++) { 18618 var bag = safeContents[i].safeBags[j]; 18619 if(bagType !== undefined && bag.type !== bagType) { 18620 continue; 18621 } 18622 // only filter by bag type, no attribute specified 18623 if(attrName === null) { 18624 result.push(bag); 18625 continue; 18626 } 18627 if(bag.attributes[attrName] !== undefined && 18628 bag.attributes[attrName].indexOf(attrValue) >= 0) { 18629 result.push(bag); 18630 } 18631 } 18632 } 18633 18634 return result; 18635} 18636 18637/** 18638 * Converts a PKCS#12 PFX in ASN.1 notation into a PFX object. 18639 * 18640 * @param obj The PKCS#12 PFX in ASN.1 notation. 18641 * @param strict true to use strict DER decoding, false not to (default: true). 18642 * @param {String} password Password to decrypt with (optional). 18643 * 18644 * @return PKCS#12 PFX object. 18645 */ 18646p12.pkcs12FromAsn1 = function(obj, strict, password) { 18647 // handle args 18648 if(typeof strict === 'string') { 18649 password = strict; 18650 strict = true; 18651 } else if(strict === undefined) { 18652 strict = true; 18653 } 18654 18655 // validate PFX and capture data 18656 var capture = {}; 18657 var errors = []; 18658 if(!asn1.validate(obj, pfxValidator, capture, errors)) { 18659 var error = new Error('Cannot read PKCS#12 PFX. ' + 18660 'ASN.1 object is not an PKCS#12 PFX.'); 18661 error.errors = error; 18662 throw error; 18663 } 18664 18665 var pfx = { 18666 version: capture.version.charCodeAt(0), 18667 safeContents: [], 18668 18669 /** 18670 * Gets bags with matching attributes. 18671 * 18672 * @param filter the attributes to filter by: 18673 * [localKeyId] the localKeyId to search for. 18674 * [localKeyIdHex] the localKeyId in hex to search for. 18675 * [friendlyName] the friendly name to search for. 18676 * [bagType] bag type to narrow each attribute search by. 18677 * 18678 * @return a map of attribute type to an array of matching bags or, if no 18679 * attribute was given but a bag type, the map key will be the 18680 * bag type. 18681 */ 18682 getBags: function(filter) { 18683 var rval = {}; 18684 18685 var localKeyId; 18686 if('localKeyId' in filter) { 18687 localKeyId = filter.localKeyId; 18688 } else if('localKeyIdHex' in filter) { 18689 localKeyId = forge.util.hexToBytes(filter.localKeyIdHex); 18690 } 18691 18692 // filter on bagType only 18693 if(localKeyId === undefined && !('friendlyName' in filter) && 18694 'bagType' in filter) { 18695 rval[filter.bagType] = _getBagsByAttribute( 18696 pfx.safeContents, null, null, filter.bagType); 18697 } 18698 18699 if(localKeyId !== undefined) { 18700 rval.localKeyId = _getBagsByAttribute( 18701 pfx.safeContents, 'localKeyId', 18702 localKeyId, filter.bagType); 18703 } 18704 if('friendlyName' in filter) { 18705 rval.friendlyName = _getBagsByAttribute( 18706 pfx.safeContents, 'friendlyName', 18707 filter.friendlyName, filter.bagType); 18708 } 18709 18710 return rval; 18711 }, 18712 18713 /** 18714 * DEPRECATED: use getBags() instead. 18715 * 18716 * Get bags with matching friendlyName attribute. 18717 * 18718 * @param friendlyName the friendly name to search for. 18719 * @param [bagType] bag type to narrow search by. 18720 * 18721 * @return an array of bags with matching friendlyName attribute. 18722 */ 18723 getBagsByFriendlyName: function(friendlyName, bagType) { 18724 return _getBagsByAttribute( 18725 pfx.safeContents, 'friendlyName', friendlyName, bagType); 18726 }, 18727 18728 /** 18729 * DEPRECATED: use getBags() instead. 18730 * 18731 * Get bags with matching localKeyId attribute. 18732 * 18733 * @param localKeyId the localKeyId to search for. 18734 * @param [bagType] bag type to narrow search by. 18735 * 18736 * @return an array of bags with matching localKeyId attribute. 18737 */ 18738 getBagsByLocalKeyId: function(localKeyId, bagType) { 18739 return _getBagsByAttribute( 18740 pfx.safeContents, 'localKeyId', localKeyId, bagType); 18741 } 18742 }; 18743 18744 if(capture.version.charCodeAt(0) !== 3) { 18745 var error = new Error('PKCS#12 PFX of version other than 3 not supported.'); 18746 error.version = capture.version.charCodeAt(0); 18747 throw error; 18748 } 18749 18750 if(asn1.derToOid(capture.contentType) !== pki.oids.data) { 18751 var error = new Error('Only PKCS#12 PFX in password integrity mode supported.'); 18752 error.oid = asn1.derToOid(capture.contentType); 18753 throw error; 18754 } 18755 18756 var data = capture.content.value[0]; 18757 if(data.tagClass !== asn1.Class.UNIVERSAL || 18758 data.type !== asn1.Type.OCTETSTRING) { 18759 throw new Error('PKCS#12 authSafe content data is not an OCTET STRING.'); 18760 } 18761 data = _decodePkcs7Data(data); 18762 18763 // check for MAC 18764 if(capture.mac) { 18765 var md = null; 18766 var macKeyBytes = 0; 18767 var macAlgorithm = asn1.derToOid(capture.macAlgorithm); 18768 switch(macAlgorithm) { 18769 case pki.oids.sha1: 18770 md = forge.md.sha1.create(); 18771 macKeyBytes = 20; 18772 break; 18773 case pki.oids.sha256: 18774 md = forge.md.sha256.create(); 18775 macKeyBytes = 32; 18776 break; 18777 case pki.oids.sha384: 18778 md = forge.md.sha384.create(); 18779 macKeyBytes = 48; 18780 break; 18781 case pki.oids.sha512: 18782 md = forge.md.sha512.create(); 18783 macKeyBytes = 64; 18784 break; 18785 case pki.oids.md5: 18786 md = forge.md.md5.create(); 18787 macKeyBytes = 16; 18788 break; 18789 } 18790 if(md === null) { 18791 throw new Error('PKCS#12 uses unsupported MAC algorithm: ' + macAlgorithm); 18792 } 18793 18794 // verify MAC (iterations default to 1) 18795 var macSalt = new forge.util.ByteBuffer(capture.macSalt); 18796 var macIterations = (('macIterations' in capture) ? 18797 parseInt(forge.util.bytesToHex(capture.macIterations), 16) : 1); 18798 var macKey = p12.generateKey( 18799 password, macSalt, 3, macIterations, macKeyBytes, md); 18800 var mac = forge.hmac.create(); 18801 mac.start(md, macKey); 18802 mac.update(data.value); 18803 var macValue = mac.getMac(); 18804 if(macValue.getBytes() !== capture.macDigest) { 18805 throw new Error('PKCS#12 MAC could not be verified. Invalid password?'); 18806 } 18807 } 18808 18809 _decodeAuthenticatedSafe(pfx, data.value, strict, password); 18810 return pfx; 18811}; 18812 18813/** 18814 * Decodes PKCS#7 Data. PKCS#7 (RFC 2315) defines "Data" as an OCTET STRING, 18815 * but it is sometimes an OCTET STRING that is composed/constructed of chunks, 18816 * each its own OCTET STRING. This is BER-encoding vs. DER-encoding. This 18817 * function transforms this corner-case into the usual simple, 18818 * non-composed/constructed OCTET STRING. 18819 * 18820 * This function may be moved to ASN.1 at some point to better deal with 18821 * more BER-encoding issues, should they arise. 18822 * 18823 * @param data the ASN.1 Data object to transform. 18824 */ 18825function _decodePkcs7Data(data) { 18826 // handle special case of "chunked" data content: an octet string composed 18827 // of other octet strings 18828 if(data.composed || data.constructed) { 18829 var value = forge.util.createBuffer(); 18830 for(var i = 0; i < data.value.length; ++i) { 18831 value.putBytes(data.value[i].value); 18832 } 18833 data.composed = data.constructed = false;
18834 data.value = value.getBytes(); 18835 } 18836 return data; 18837} 18838 18839/** 18840 * Decode PKCS#12 AuthenticatedSafe (BER encoded) into PFX object. 18841 * 18842 * The AuthenticatedSafe is a BER-encoded SEQUENCE OF ContentInfo. 18843 * 18844 * @param pfx The PKCS#12 PFX object to fill. 18845 * @param {String} authSafe BER-encoded AuthenticatedSafe. 18846 * @param strict true to use strict DER decoding, false not to. 18847 * @param {String} password Password to decrypt with (optional). 18848 */ 18849function _decodeAuthenticatedSafe(pfx, authSafe, strict, password) { 18850 authSafe = asn1.fromDer(authSafe, strict); /* actually it's BER encoded */ 18851 18852 if(authSafe.tagClass !== asn1.Class.UNIVERSAL || 18853 authSafe.type !== asn1.Type.SEQUENCE || 18854 authSafe.constructed !== true) { 18855 throw new Error('PKCS#12 AuthenticatedSafe expected to be a ' + 18856 'SEQUENCE OF ContentInfo'); 18857 } 18858 18859 for(var i = 0; i < authSafe.value.length; i ++) { 18860 var contentInfo = authSafe.value[i]; 18861 18862 // validate contentInfo and capture data 18863 var capture = {}; 18864 var errors = []; 18865 if(!asn1.validate(contentInfo, contentInfoValidator, capture, errors)) { 18866 var error = new Error('Cannot read ContentInfo.'); 18867 error.errors = errors; 18868 throw error; 18869 } 18870 18871 var obj = { 18872 encrypted: false 18873 }; 18874 var safeContents = null; 18875 var data = capture.content.value[0]; 18876 switch(asn1.derToOid(capture.contentType)) { 18877 case pki.oids.data: 18878 if(data.tagClass !== asn1.Class.UNIVERSAL || 18879 data.type !== asn1.Type.OCTETSTRING) { 18880 throw new Error('PKCS#12 SafeContents Data is not an OCTET STRING.'); 18881 } 18882 safeContents = _decodePkcs7Data(data).value; 18883 break; 18884 case pki.oids.encryptedData: 18885 safeContents = _decryptSafeContents(data, password); 18886 obj.encrypted = true; 18887 break; 18888 default: 18889 var error = new Error('Unsupported PKCS#12 contentType.'); 18890 error.contentType = asn1.derToOid(capture.contentType); 18891 throw error; 18892 } 18893 18894 obj.safeBags = _decodeSafeContents(safeContents, strict, password); 18895 pfx.safeContents.push(obj); 18896 } 18897} 18898 18899/** 18900 * Decrypt PKCS#7 EncryptedData structure. 18901 * 18902 * @param data ASN.1 encoded EncryptedContentInfo object. 18903 * @param password The user-provided password. 18904 * 18905 * @return The decrypted SafeContents (ASN.1 object). 18906 */ 18907function _decryptSafeContents(data, password) { 18908 var capture = {}; 18909 var errors = []; 18910 if(!asn1.validate( 18911 data, forge.pkcs7.asn1.encryptedDataValidator, capture, errors)) { 18912 var error = new Error('Cannot read EncryptedContentInfo.'); 18913 error.errors = errors; 18914 throw error; 18915 } 18916 18917 var oid = asn1.derToOid(capture.contentType); 18918 if(oid !== pki.oids.data) { 18919 var error = new Error( 18920 'PKCS#12 EncryptedContentInfo ContentType is not Data.'); 18921 error.oid = oid; 18922 throw error; 18923 } 18924 18925 // get cipher 18926 oid = asn1.derToOid(capture.encAlgorithm); 18927 var cipher = pki.pbe.getCipher(oid, capture.encParameter, password); 18928 18929 // get encrypted data 18930 var encryptedContentAsn1 = _decodePkcs7Data(capture.encryptedContentAsn1); 18931 var encrypted = forge.util.createBuffer(encryptedContentAsn1.value); 18932 18933 cipher.update(encrypted); 18934 if(!cipher.finish()) { 18935 throw new Error('Failed to decrypt PKCS#12 SafeContents.'); 18936 } 18937 18938 return cipher.output.getBytes(); 18939} 18940 18941/** 18942 * Decode PKCS#12 SafeContents (BER-encoded) into array of Bag objects. 18943 * 18944 * The safeContents is a BER-encoded SEQUENCE OF SafeBag. 18945 * 18946 * @param {String} safeContents BER-encoded safeContents. 18947 * @param strict true to use strict DER decoding, false not to. 18948 * @param {String} password Password to decrypt with (optional). 18949 * 18950 * @return {Array} Array of Bag objects. 18951 */ 18952function _decodeSafeContents(safeContents, strict, password) { 18953 // if strict and no safe contents, return empty safes 18954 if(!strict && safeContents.length === 0) { 18955 return []; 18956 } 18957 18958 // actually it's BER-encoded 18959 safeContents = asn1.fromDer(safeContents, strict); 18960 18961 if(safeContents.tagClass !== asn1.Class.UNIVERSAL || 18962 safeContents.type !== asn1.Type.SEQUENCE || 18963 safeContents.constructed !== true) { 18964 throw new Error( 18965 'PKCS#12 SafeContents expected to be a SEQUENCE OF SafeBag.'); 18966 } 18967 18968 var res = []; 18969 for(var i = 0; i < safeContents.value.length; i++) { 18970 var safeBag = safeContents.value[i]; 18971 18972 // validate SafeBag and capture data 18973 var capture = {}; 18974 var errors = []; 18975 if(!asn1.validate(safeBag, safeBagValidator, capture, errors)) { 18976 var error = new Error('Cannot read SafeBag.'); 18977 error.errors = errors; 18978 throw error; 18979 } 18980 18981 /* Create bag object and push to result array. */ 18982 var bag = { 18983 type: asn1.derToOid(capture.bagId), 18984 attributes: _decodeBagAttributes(capture.bagAttributes) 18985 }; 18986 res.push(bag); 18987
18988 var validator, decoder; 18989 var bagAsn1 = capture.bagValue.value[0]; 18990 switch(bag.type) { 18991 case pki.oids.pkcs8ShroudedKeyBag: 18992 /* bagAsn1 has a EncryptedPrivateKeyInfo, which we need to decrypt. 18993 Afterwards we can handle it like a keyBag, 18994 which is a PrivateKeyInfo. */ 18995 bagAsn1 = pki.decryptPrivateKeyInfo(bagAsn1, password); 18996 if(bagAsn1 === null) { 18997 throw new Error( 18998 'Unable to decrypt PKCS#8 ShroudedKeyBag, wrong password?'); 18999 } 19000 19001 /* fall through */ 19002 case pki.oids.keyBag: 19003 /* A PKCS#12 keyBag is a simple PrivateKeyInfo as understood by our 19004 PKI module, hence we don't have to do validation/capturing here, 19005 just pass what we already got. */ 19006 try { 19007 bag.key = pki.privateKeyFromAsn1(bagAsn1); 19008 } catch(e) { 19009 // ignore unknown key type, pass asn1 value 19010 bag.key = null; 19011 bag.asn1 = bagAsn1; 19012 } 19013 continue; /* Nothing more to do. */ 19014 19015 case pki.oids.certBag: 19016 /* A PKCS#12 certBag can wrap both X.509 and sdsi certificates. 19017 Therefore put the SafeBag content through another validator to 19018 capture the fields. Afterwards check & store the results. */ 19019 validator = certBagValidator; 19020 decoder = function() { 19021 if(asn1.derToOid(capture.certId) !== pki.oids.x509Certificate) { 19022 var error = new Error( 19023 'Unsupported certificate type, only X.509 supported.'); 19024 error.oid = asn1.derToOid(capture.certId); 19025 throw error; 19026 } 19027 19028 // true=produce cert hash 19029 var certAsn1 = asn1.fromDer(capture.cert, strict); 19030 try { 19031 bag.cert = pki.certificateFromAsn1(certAsn1, true); 19032 } catch(e) { 19033 // ignore unknown cert type, pass asn1 value 19034 bag.cert = null; 19035 bag.asn1 = certAsn1; 19036 } 19037 }; 19038 break; 19039 19040 default: 19041 var error = new Error('Unsupported PKCS#12 SafeBag type.'); 19042 error.oid = bag.type; 19043 throw error; 19044 } 19045 19046 /* Validate SafeBag value (i.e. CertBag, etc.) and capture data if needed. */ 19047 if(validator !== undefined && 19048 !asn1.validate(bagAsn1, validator, capture, errors)) { 19049 var error = new Error('Cannot read PKCS#12 ' + validator.name); 19050 error.errors = errors; 19051 throw error; 19052 } 19053 19054 /* Call decoder function from above to store the results. */ 19055 decoder(); 19056 } 19057 19058 return res; 19059} 19060 19061/** 19062 * Decode PKCS#12 SET OF PKCS12Attribute into JavaScript object. 19063 * 19064 * @param attributes SET OF PKCS12Attribute (ASN.1 object). 19065 * 19066 * @return the decoded attributes. 19067 */ 19068function _decodeBagAttributes(attributes) { 19069 var decodedAttrs = {}; 19070 19071 if(attributes !== undefined) { 19072 for(var i = 0; i < attributes.length; ++i) { 19073 var capture = {}; 19074 var errors = []; 19075 if(!asn1.validate(attributes[i], attributeValidator, capture, errors)) { 19076 var error = new Error('Cannot read PKCS#12 BagAttribute.'); 19077 error.errors = errors; 19078 throw error; 19079 } 19080 19081 var oid = asn1.derToOid(capture.oid); 19082 if(pki.oids[oid] === undefined) { 19083 // unsupported attribute type, ignore. 19084 continue; 19085 } 19086 19087 decodedAttrs[pki.oids[oid]] = []; 19088 for(var j = 0; j < capture.values.length; ++j) { 19089 decodedAttrs[pki.oids[oid]].push(capture.values[j].value); 19090 } 19091 } 19092 } 19093 19094 return decodedAttrs; 19095} 19096 19097/** 19098 * Wraps a private key and certificate in a PKCS#12 PFX wrapper. If a 19099 * password is provided then the private key will be encrypted. 19100 * 19101 * An entire certificate chain may also be included. To do this, pass 19102 * an array for the "cert" parameter where the first certificate is 19103 * the one that is paired with the private key and each subsequent one 19104 * verifies the previous one. The certificates may be in PEM format or 19105 * have been already parsed by Forge. 19106 * 19107 * @todo implement password-based-encryption for the whole package 19108 * 19109 * @param key the private key. 19110 * @param cert the certificate (may be an array of certificates in order 19111 * to specify a certificate chain). 19112 * @param password the password to use, null for none. 19113 * @param options: 19114 * algorithm the encryption algorithm to use 19115 * ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. 19116 * count the iteration count to use. 19117 * saltSize the salt size to use. 19118 * useMac true to include a MAC, false not to, defaults to true. 19119 * localKeyId the local key ID to use, in hex. 19120 * friendlyName the friendly name to use. 19121 * generateLocalKeyId true to generate a random local key ID, 19122 * false not to, defaults to true. 19123 * 19124 * @return the PKCS#12 PFX ASN.1 object. 19125 */ 19126p12.toPkcs12Asn1 = function(key, cert, password, options) { 19127 // set default options 19128 options = options || {}; 19129 options.saltSize = options.saltSize || 8; 19130 options.count = options.count || 2048; 19131 options.algorithm = options.algorithm || options.encAlgorithm || 'aes128'; 19132 if(!('useMac' in options)) { 19133 options.useMac = true; 19134 } 19135 if(!('localKeyId' in options)) { 19136 options.localKeyId = null; 19137 } 19138 if(!('generateLocalKeyId' in options)) { 19139 options.generateLocalKeyId = true; 19140 } 19141 19142 var localKeyId = options.localKeyId; 19143 var bagAttrs; 19144 if(localKeyId !== null) { 19145 localKeyId = forge.util.hexToBytes(localKeyId); 19146 } else if(options.generateLocalKeyId) { 19147 // use SHA-1 of paired cert, if available 19148 if(cert) { 19149 var pairedCert = forge.util.isArray(cert) ? cert[0] : cert; 19150 if(typeof pairedCert === 'string') { 19151 pairedCert = pki.certificateFromPem(pairedCert); 19152 } 19153 var sha1 = forge.md.sha1.create(); 19154 sha1.update(asn1.toDer(pki.certificateToAsn1(pairedCert)).getBytes()); 19155 localKeyId = sha1.digest().getBytes(); 19156 } else { 19157 // FIXME: consider using SHA-1 of public key (which can be generated 19158 // from private key components), see: cert.generateSubjectKeyIdentifier 19159 // generate random bytes 19160 localKeyId = forge.random.getBytes(20); 19161 } 19162 } 19163 19164 var attrs = []; 19165 if(localKeyId !== null) { 19166 attrs.push( 19167 // localKeyID 19168 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19169 // attrId 19170 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19171 asn1.oidToDer(pki.oids.localKeyId).getBytes()), 19172 // attrValues 19173 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [ 19174 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 19175 localKeyId) 19176 ]) 19177 ])); 19178 } 19179 if('friendlyName' in options) { 19180 attrs.push( 19181 // friendlyName 19182 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19183 // attrId 19184 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19185 asn1.oidToDer(pki.oids.friendlyName).getBytes()), 19186 // attrValues 19187 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [ 19188 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BMPSTRING, false, 19189 options.friendlyName) 19190 ]) 19191 ])); 19192 } 19193 19194 if(attrs.length > 0) { 19195 bagAttrs = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, attrs); 19196 } 19197 19198 // collect contents for AuthenticatedSafe 19199 var contents = []; 19200 19201 // create safe bag(s) for certificate chain 19202 var chain = []; 19203 if(cert !== null) { 19204 if(forge.util.isArray(cert)) { 19205 chain = cert; 19206 } else { 19207 chain = [cert]; 19208 } 19209 } 19210 19211 var certSafeBags = []; 19212 for(var i = 0; i < chain.length; ++i) { 19213 // convert cert from PEM as necessary 19214 cert = chain[i]; 19215 if(typeof cert === 'string') { 19216 cert = pki.certificateFromPem(cert); 19217 } 19218 19219 // SafeBag 19220 var certBagAttrs = (i === 0) ? bagAttrs : undefined; 19221 var certAsn1 = pki.certificateToAsn1(cert); 19222 var certSafeBag = 19223 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19224 // bagId 19225 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19226 asn1.oidToDer(pki.oids.certBag).getBytes()), 19227 // bagValue 19228 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 19229 // CertBag 19230 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19231 // certId 19232 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19233 asn1.oidToDer(pki.oids.x509Certificate).getBytes()), 19234 // certValue (x509Certificate) 19235 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 19236 asn1.create( 19237 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 19238 asn1.toDer(certAsn1).getBytes()) 19239 ])])]), 19240 // bagAttributes (OPTIONAL) 19241 certBagAttrs 19242 ]); 19243 certSafeBags.push(certSafeBag); 19244 } 19245
19246 if(certSafeBags.length > 0) { 19247 // SafeContents 19248 var certSafeContents = asn1.create( 19249 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, certSafeBags); 19250 19251 // ContentInfo 19252 var certCI = 19253 // PKCS#7 ContentInfo 19254 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19255 // contentType 19256 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19257 // OID for the content type is 'data' 19258 asn1.oidToDer(pki.oids.data).getBytes()), 19259 // content 19260 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 19261 asn1.create( 19262 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 19263 asn1.toDer(certSafeContents).getBytes()) 19264 ]) 19265 ]); 19266 contents.push(certCI); 19267 } 19268 19269 // create safe contents for private key 19270 var keyBag = null; 19271 if(key !== null) { 19272 // SafeBag 19273 var pkAsn1 = pki.wrapRsaPrivateKey(pki.privateKeyToAsn1(key)); 19274 if(password === null) { 19275 // no encryption 19276 keyBag = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19277 // bagId 19278 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19279 asn1.oidToDer(pki.oids.keyBag).getBytes()), 19280 // bagValue 19281 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 19282 // PrivateKeyInfo 19283 pkAsn1 19284 ]), 19285 // bagAttributes (OPTIONAL) 19286 bagAttrs 19287 ]); 19288 } else { 19289 // encrypted PrivateKeyInfo 19290 keyBag = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19291 // bagId 19292 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19293 asn1.oidToDer(pki.oids.pkcs8ShroudedKeyBag).getBytes()), 19294 // bagValue 19295 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 19296 // EncryptedPrivateKeyInfo 19297 pki.encryptPrivateKeyInfo(pkAsn1, password, options) 19298 ]), 19299 // bagAttributes (OPTIONAL) 19300 bagAttrs 19301 ]); 19302 } 19303 19304 // SafeContents 19305 var keySafeContents = 19306 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [keyBag]); 19307 19308 // ContentInfo 19309 var keyCI = 19310 // PKCS#7 ContentInfo 19311 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19312 // contentType 19313 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19314 // OID for the content type is 'data' 19315 asn1.oidToDer(pki.oids.data).getBytes()), 19316 // content 19317 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 19318 asn1.create( 19319 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 19320 asn1.toDer(keySafeContents).getBytes()) 19321 ]) 19322 ]); 19323 contents.push(keyCI); 19324 } 19325 19326 // create AuthenticatedSafe by stringing together the contents 19327 var safe = asn1.create( 19328 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, contents); 19329 19330 var macData; 19331 if(options.useMac) { 19332 // MacData 19333 var sha1 = forge.md.sha1.create(); 19334 var macSalt = new forge.util.ByteBuffer( 19335 forge.random.getBytes(options.saltSize)); 19336 var count = options.count; 19337 // 160-bit key 19338 var key = p12.generateKey(password, macSalt, 3, count, 20); 19339 var mac = forge.hmac.create(); 19340 mac.start(sha1, key); 19341 mac.update(asn1.toDer(safe).getBytes()); 19342 var macValue = mac.getMac(); 19343 macData = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19344 // mac DigestInfo 19345 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19346 // digestAlgorithm 19347 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19348 // algorithm = SHA-1 19349 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19350 asn1.oidToDer(pki.oids.sha1).getBytes()), 19351 // parameters = Null 19352 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 19353 ]), 19354 // digest 19355 asn1.create( 19356 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, 19357 false, macValue.getBytes()) 19358 ]), 19359 // macSalt OCTET STRING 19360 asn1.create( 19361 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, macSalt.getBytes()), 19362 // iterations INTEGER (XXX: Only support count < 65536) 19363 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 19364 asn1.integerToDer(count).getBytes() 19365 ) 19366 ]); 19367 } 19368 19369 // PFX 19370 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19371 // version (3) 19372 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 19373 asn1.integerToDer(3).getBytes()), 19374 // PKCS#7 ContentInfo 19375 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 19376 // contentType 19377 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 19378 // OID for the content type is 'data' 19379 asn1.oidToDer(pki.oids.data).getBytes()), 19380 // content 19381 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 19382 asn1.create( 19383 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 19384 asn1.toDer(safe).getBytes()) 19385 ]) 19386 ]), 19387 macData 19388 ]); 19389}; 19390 19391/** 19392 * Derives a PKCS#12 key. 19393 * 19394 * @param password the password to derive the key material from, null or 19395 * undefined for none. 19396 * @param salt the salt, as a ByteBuffer, to use. 19397 * @param id the PKCS#12 ID byte (1 = key material, 2 = IV, 3 = MAC). 19398 * @param iter the iteration count. 19399 * @param n the number of bytes to derive from the password. 19400 * @param md the message digest to use, defaults to SHA-1. 19401 * 19402 * @return a ByteBuffer with the bytes derived from the password. 19403 */ 19404p12.generateKey = forge.pbe.generatePkcs12Key; 19405 19406} // end module implementation 19407 19408/* ########## Begin module wrapper ########## */ 19409var name = 'pkcs12'; 19410if(typeof define !== 'function') { 19411 // NodeJS -> AMD 19412 if(typeof module === 'object' && module.exports) { 19413 var nodeJS = true; 19414 define = function(ids, factory) { 19415 factory(require, module); 19416 }; 19417 } else { 19418 // <script> 19419 if(typeof forge === 'undefined') { 19420 forge = {}; 19421 } 19422 return initModule(forge); 19423 } 19424} 19425// AMD 19426var deps;
19427var defineFunc = function(require, module) { 19428 module.exports = function(forge) { 19429 var mods = deps.map(function(dep) { 19430 return require(dep); 19431 }).concat(initModule); 19432 // handle circular dependencies 19433 forge = forge || {}; 19434 forge.defined = forge.defined || {}; 19435 if(forge.defined[name]) { 19436 return forge[name]; 19437 } 19438 forge.defined[name] = true; 19439 for(var i = 0; i < mods.length; ++i) { 19440 mods[i](forge); 19441 } 19442 return forge[name]; 19443 }; 19444}; 19445var tmpDefine = define; 19446define = function(ids, factory) { 19447 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 19448 if(nodeJS) { 19449 delete define; 19450 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 19451 } 19452 define = tmpDefine; 19453 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 19454}; 19455define([ 19456 'require', 19457 'module', 19458 './asn1', 19459 './hmac', 19460 './oids', 19461 './pkcs7asn1', 19462 './pbe', 19463 './random', 19464 './rsa', 19465 './sha1', 19466 './util', 19467 './x509' 19468], function() { 19469 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 19470}); 19471})(); 19472 19473/** 19474 * Javascript implementation of ASN.1 validators for PKCS#7 v1.5. 19475 * 19476 * @author Dave Longley 19477 * @author Stefan Siegl 19478 * 19479 * Copyright (c) 2012-2015 Digital Bazaar, Inc. 19480 * Copyright (c) 2012 Stefan Siegl <[email protected]> 19481 * 19482 * The ASN.1 representation of PKCS#7 is as follows 19483 * (see RFC #2315 for details, http://www.ietf.org/rfc/rfc2315.txt): 19484 * 19485 * A PKCS#7 message consists of a ContentInfo on root level, which may 19486 * contain any number of further ContentInfo nested into it. 19487 * 19488 * ContentInfo ::= SEQUENCE { 19489 * contentType ContentType, 19490 * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL 19491 * } 19492 * 19493 * ContentType ::= OBJECT IDENTIFIER 19494 * 19495 * EnvelopedData ::= SEQUENCE { 19496 * version Version, 19497 * recipientInfos RecipientInfos, 19498 * encryptedContentInfo EncryptedContentInfo 19499 * } 19500 * 19501 * EncryptedData ::= SEQUENCE { 19502 * version Version, 19503 * encryptedContentInfo EncryptedContentInfo 19504 * } 19505 * 19506 * id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) 19507 * us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 } 19508 * 19509 * SignedData ::= SEQUENCE { 19510 * version INTEGER, 19511 * digestAlgorithms DigestAlgorithmIdentifiers, 19512 * contentInfo ContentInfo, 19513 * certificates [0] IMPLICIT Certificates OPTIONAL, 19514 * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, 19515 * signerInfos SignerInfos 19516 * } 19517 * 19518 * SignerInfos ::= SET OF SignerInfo 19519 * 19520 * SignerInfo ::= SEQUENCE { 19521 * version Version, 19522 * issuerAndSerialNumber IssuerAndSerialNumber, 19523 * digestAlgorithm DigestAlgorithmIdentifier, 19524 * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL, 19525 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, 19526 * encryptedDigest EncryptedDigest, 19527 * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL 19528 * } 19529 * 19530 * EncryptedDigest ::= OCTET STRING 19531 * 19532 * Attributes ::= SET OF Attribute 19533 * 19534 * Attribute ::= SEQUENCE { 19535 * attrType OBJECT IDENTIFIER, 19536 * attrValues SET OF AttributeValue 19537 * } 19538 * 19539 * AttributeValue ::= ANY 19540 * 19541 * Version ::= INTEGER 19542 * 19543 * RecipientInfos ::= SET OF RecipientInfo 19544 * 19545 * EncryptedContentInfo ::= SEQUENCE { 19546 * contentType ContentType, 19547 * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, 19548 * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL 19549 * } 19550 * 19551 * ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 19552 * 19553 * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters 19554 * for the algorithm, if any. In the case of AES and DES3, there is only one, 19555 * the IV. 19556 * 19557 * AlgorithmIdentifer ::= SEQUENCE { 19558 * algorithm OBJECT IDENTIFIER, 19559 * parameters ANY DEFINED BY algorithm OPTIONAL 19560 * } 19561 * 19562 * EncryptedContent ::= OCTET STRING 19563 * 19564 * RecipientInfo ::= SEQUENCE { 19565 * version Version, 19566 * issuerAndSerialNumber IssuerAndSerialNumber, 19567 * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, 19568 * encryptedKey EncryptedKey 19569 * } 19570 * 19571 * IssuerAndSerialNumber ::= SEQUENCE { 19572 * issuer Name, 19573 * serialNumber CertificateSerialNumber 19574 * } 19575 * 19576 * CertificateSerialNumber ::= INTEGER 19577 * 19578 * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 19579 * 19580 * EncryptedKey ::= OCTET STRING 19581 */ 19582(function() { 19583/* ########## Begin module implementation ########## */ 19584function initModule(forge) { 19585 19586// shortcut for ASN.1 API 19587var asn1 = forge.asn1; 19588 19589// shortcut for PKCS#7 API 19590var p7v = forge.pkcs7asn1 = forge.pkcs7asn1 || {}; 19591forge.pkcs7 = forge.pkcs7 || {}; 19592forge.pkcs7.asn1 = p7v; 19593 19594var contentInfoValidator = { 19595 name: 'ContentInfo', 19596 tagClass: asn1.Class.UNIVERSAL, 19597 type: asn1.Type.SEQUENCE, 19598 constructed: true, 19599 value: [{ 19600 name: 'ContentInfo.ContentType', 19601 tagClass: asn1.Class.UNIVERSAL, 19602 type: asn1.Type.OID, 19603 constructed: false, 19604 capture: 'contentType' 19605 }, { 19606 name: 'ContentInfo.content', 19607 tagClass: asn1.Class.CONTEXT_SPECIFIC, 19608 type: 0, 19609 constructed: true, 19610 optional: true, 19611 captureAsn1: 'content' 19612 }] 19613}; 19614p7v.contentInfoValidator = contentInfoValidator; 19615 19616var encryptedContentInfoValidator = { 19617 name: 'EncryptedContentInfo', 19618 tagClass: asn1.Class.UNIVERSAL, 19619 type: asn1.Type.SEQUENCE, 19620 constructed: true, 19621 value: [{ 19622 name: 'EncryptedContentInfo.contentType', 19623 tagClass: asn1.Class.UNIVERSAL, 19624 type: asn1.Type.OID, 19625 constructed: false, 19626 capture: 'contentType' 19627 }, { 19628 name: 'EncryptedContentInfo.contentEncryptionAlgorithm', 19629 tagClass: asn1.Class.UNIVERSAL, 19630 type: asn1.Type.SEQUENCE, 19631 constructed: true, 19632 value: [{ 19633 name: 'EncryptedContentInfo.contentEncryptionAlgorithm.algorithm', 19634 tagClass: asn1.Class.UNIVERSAL, 19635 type: asn1.Type.OID, 19636 constructed: false, 19637 capture: 'encAlgorithm' 19638 }, {
19639 name: 'EncryptedContentInfo.contentEncryptionAlgorithm.parameter', 19640 tagClass: asn1.Class.UNIVERSAL, 19641 captureAsn1: 'encParameter' 19642 }] 19643 }, { 19644 name: 'EncryptedContentInfo.encryptedContent', 19645 tagClass: asn1.Class.CONTEXT_SPECIFIC, 19646 type: 0, 19647 /* The PKCS#7 structure output by OpenSSL somewhat differs from what 19648 * other implementations do generate. 19649 * 19650 * OpenSSL generates a structure like this: 19651 * SEQUENCE { 19652 * ... 19653 * [0] 19654 * 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38 19655 * C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45 19656 * ... 19657 * } 19658 * 19659 * Whereas other implementations (and this PKCS#7 module) generate: 19660 * SEQUENCE { 19661 * ... 19662 * [0] { 19663 * OCTET STRING 19664 * 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38 19665 * C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45 19666 * ... 19667 * } 19668 * } 19669 * 19670 * In order to support both, we just capture the context specific 19671 * field here. The OCTET STRING bit is removed below. 19672 */ 19673 capture: 'encryptedContent', 19674 captureAsn1: 'encryptedContentAsn1' 19675 }] 19676}; 19677 19678p7v.envelopedDataValidator = { 19679 name: 'EnvelopedData', 19680 tagClass: asn1.Class.UNIVERSAL, 19681 type: asn1.Type.SEQUENCE, 19682 constructed: true, 19683 value: [{ 19684 name: 'EnvelopedData.Version', 19685 tagClass: asn1.Class.UNIVERSAL, 19686 type: asn1.Type.INTEGER, 19687 constructed: false, 19688 capture: 'version' 19689 }, { 19690 name: 'EnvelopedData.RecipientInfos', 19691 tagClass: asn1.Class.UNIVERSAL, 19692 type: asn1.Type.SET, 19693 constructed: true, 19694 captureAsn1: 'recipientInfos' 19695 }].concat(encryptedContentInfoValidator) 19696}; 19697 19698p7v.encryptedDataValidator = { 19699 name: 'EncryptedData', 19700 tagClass: asn1.Class.UNIVERSAL, 19701 type: asn1.Type.SEQUENCE, 19702 constructed: true, 19703 value: [{ 19704 name: 'EncryptedData.Version', 19705 tagClass: asn1.Class.UNIVERSAL, 19706 type: asn1.Type.INTEGER, 19707 constructed: false, 19708 capture: 'version' 19709 }].concat(encryptedContentInfoValidator) 19710}; 19711 19712var signerValidator = { 19713 name: 'SignerInfo', 19714 tagClass: asn1.Class.UNIVERSAL, 19715 type: asn1.Type.SEQUENCE, 19716 constructed: true, 19717 value: [{ 19718 name: 'SignerInfo.version', 19719 tagClass: asn1.Class.UNIVERSAL, 19720 type: asn1.Type.INTEGER, 19721 constructed: false 19722 }, { 19723 name: 'SignerInfo.issuerAndSerialNumber', 19724 tagClass: asn1.Class.UNIVERSAL, 19725 type: asn1.Type.SEQUENCE, 19726 constructed: true, 19727 value: [{ 19728 name: 'SignerInfo.issuerAndSerialNumber.issuer', 19729 tagClass: asn1.Class.UNIVERSAL, 19730 type: asn1.Type.SEQUENCE, 19731 constructed: true, 19732 captureAsn1: 'issuer' 19733 }, { 19734 name: 'SignerInfo.issuerAndSerialNumber.serialNumber', 19735 tagClass: asn1.Class.UNIVERSAL, 19736 type: asn1.Type.INTEGER, 19737 constructed: false, 19738 capture: 'serial' 19739 }] 19740 }, { 19741 name: 'SignerInfo.digestAlgorithm', 19742 tagClass: asn1.Class.UNIVERSAL, 19743 type: asn1.Type.SEQUENCE, 19744 constructed: true, 19745 value: [{ 19746 name: 'SignerInfo.digestAlgorithm.algorithm', 19747 tagClass: asn1.Class.UNIVERSAL, 19748 type: asn1.Type.OID, 19749 constructed: false, 19750 capture: 'digestAlgorithm' 19751 }, { 19752 name: 'SignerInfo.digestAlgorithm.parameter', 19753 tagClass: asn1.Class.UNIVERSAL, 19754 constructed: false, 19755 captureAsn1: 'digestParameter', 19756 optional: true 19757 }] 19758 }, { 19759 name: 'SignerInfo.authenticatedAttributes', 19760 tagClass: asn1.Class.CONTEXT_SPECIFIC, 19761 type: 0, 19762 constructed: true, 19763 optional: true, 19764 capture: 'authenticatedAttributes' 19765 }, { 19766 name: 'SignerInfo.digestEncryptionAlgorithm', 19767 tagClass: asn1.Class.UNIVERSAL, 19768 type: asn1.Type.SEQUENCE, 19769 constructed: true, 19770 capture: 'signatureAlgorithm' 19771 }, { 19772 name: 'SignerInfo.encryptedDigest', 19773 tagClass: asn1.Class.UNIVERSAL, 19774 type: asn1.Type.OCTETSTRING, 19775 constructed: false, 19776 capture: 'signature' 19777 }, { 19778 name: 'SignerInfo.unauthenticatedAttributes', 19779 tagClass: asn1.Class.CONTEXT_SPECIFIC, 19780 type: 1, 19781 constructed: true, 19782 optional: true, 19783 capture: 'unauthenticatedAttributes' 19784 }] 19785}; 19786 19787p7v.signedDataValidator = { 19788 name: 'SignedData', 19789 tagClass: asn1.Class.UNIVERSAL, 19790 type: asn1.Type.SEQUENCE, 19791 constructed: true, 19792 value: [{ 19793 name: 'SignedData.Version', 19794 tagClass: asn1.Class.UNIVERSAL, 19795 type: asn1.Type.INTEGER, 19796 constructed: false, 19797 capture: 'version' 19798 }, { 19799 name: 'SignedData.DigestAlgorithms', 19800 tagClass: asn1.Class.UNIVERSAL, 19801 type: asn1.Type.SET, 19802 constructed: true, 19803 captureAsn1: 'digestAlgorithms' 19804 }, 19805 contentInfoValidator, 19806 { 19807 name: 'SignedData.Certificates', 19808 tagClass: asn1.Class.CONTEXT_SPECIFIC, 19809 type: 0, 19810 optional: true, 19811 captureAsn1: 'certificates' 19812 }, { 19813 name: 'SignedData.CertificateRevocationLists', 19814 tagClass: asn1.Class.CONTEXT_SPECIFIC, 19815 type: 1, 19816 optional: true, 19817 captureAsn1: 'crls' 19818 }, { 19819 name: 'SignedData.SignerInfos', 19820 tagClass: asn1.Class.UNIVERSAL, 19821 type: asn1.Type.SET, 19822 capture: 'signerInfos', 19823 optional: true, 19824 value: [signerValidator] 19825 }] 19826}; 19827 19828p7v.recipientInfoValidator = { 19829 name: 'RecipientInfo', 19830 tagClass: asn1.Class.UNIVERSAL, 19831 type: asn1.Type.SEQUENCE, 19832 constructed: true, 19833 value: [{ 19834 name: 'RecipientInfo.version', 19835 tagClass: asn1.Class.UNIVERSAL, 19836 type: asn1.Type.INTEGER, 19837 constructed: false, 19838 capture: 'version' 19839 }, { 19840 name: 'RecipientInfo.issuerAndSerial', 19841 tagClass: asn1.Class.UNIVERSAL, 19842 type: asn1.Type.SEQUENCE, 19843 constructed: true, 19844 value: [{ 19845 name: 'RecipientInfo.issuerAndSerial.issuer', 19846 tagClass: asn1.Class.UNIVERSAL, 19847 type: asn1.Type.SEQUENCE, 19848 constructed: true,
19849 captureAsn1: 'issuer' 19850 }, { 19851 name: 'RecipientInfo.issuerAndSerial.serialNumber', 19852 tagClass: asn1.Class.UNIVERSAL, 19853 type: asn1.Type.INTEGER, 19854 constructed: false, 19855 capture: 'serial' 19856 }] 19857 }, { 19858 name: 'RecipientInfo.keyEncryptionAlgorithm', 19859 tagClass: asn1.Class.UNIVERSAL, 19860 type: asn1.Type.SEQUENCE, 19861 constructed: true, 19862 value: [{ 19863 name: 'RecipientInfo.keyEncryptionAlgorithm.algorithm', 19864 tagClass: asn1.Class.UNIVERSAL, 19865 type: asn1.Type.OID, 19866 constructed: false, 19867 capture: 'encAlgorithm' 19868 }, { 19869 name: 'RecipientInfo.keyEncryptionAlgorithm.parameter', 19870 tagClass: asn1.Class.UNIVERSAL, 19871 constructed: false, 19872 captureAsn1: 'encParameter' 19873 }] 19874 }, { 19875 name: 'RecipientInfo.encryptedKey', 19876 tagClass: asn1.Class.UNIVERSAL, 19877 type: asn1.Type.OCTETSTRING, 19878 constructed: false, 19879 capture: 'encKey' 19880 }] 19881}; 19882 19883} // end module implementation 19884 19885/* ########## Begin module wrapper ########## */ 19886var name = 'pkcs7asn1'; 19887if(typeof define !== 'function') { 19888 // NodeJS -> AMD 19889 if(typeof module === 'object' && module.exports) { 19890 var nodeJS = true; 19891 define = function(ids, factory) { 19892 factory(require, module); 19893 }; 19894 } else { 19895 // <script> 19896 if(typeof forge === 'undefined') { 19897 forge = {}; 19898 } 19899 return initModule(forge); 19900 } 19901} 19902// AMD 19903var deps; 19904var defineFunc = function(require, module) { 19905 module.exports = function(forge) { 19906 var mods = deps.map(function(dep) { 19907 return require(dep); 19908 }).concat(initModule); 19909 // handle circular dependencies 19910 forge = forge || {}; 19911 forge.defined = forge.defined || {}; 19912 if(forge.defined[name]) { 19913 return forge[name]; 19914 } 19915 forge.defined[name] = true; 19916 for(var i = 0; i < mods.length; ++i) { 19917 mods[i](forge); 19918 } 19919 return forge[name]; 19920 }; 19921}; 19922var tmpDefine = define; 19923define = function(ids, factory) { 19924 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 19925 if(nodeJS) { 19926 delete define; 19927 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 19928 } 19929 define = tmpDefine; 19930 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 19931}; 19932define(['require', 'module', './asn1', './util'], function() { 19933 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 19934}); 19935})(); 19936 19937/** 19938 * Javascript implementation of PKCS#7 v1.5. 19939 * 19940 * @author Stefan Siegl 19941 * @author Dave Longley 19942 * 19943 * Copyright (c) 2012 Stefan Siegl <[email protected]> 19944 * Copyright (c) 2012-2015 Digital Bazaar, Inc. 19945 * 19946 * Currently this implementation only supports ContentType of EnvelopedData, 19947 * EncryptedData, or SignedData at the root level. The top level elements may 19948 * contain only a ContentInfo of ContentType Data, i.e. plain data. Further 19949 * nesting is not (yet) supported. 19950 * 19951 * The Forge validators for PKCS #7's ASN.1 structures are available from 19952 * a separate file pkcs7asn1.js, since those are referenced from other 19953 * PKCS standards like PKCS #12. 19954 */ 19955(function() { 19956/* ########## Begin module implementation ########## */ 19957function initModule(forge) { 19958 19959// shortcut for ASN.1 API 19960var asn1 = forge.asn1; 19961 19962// shortcut for PKCS#7 API 19963var p7 = forge.pkcs7 = forge.pkcs7 || {}; 19964 19965/** 19966 * Converts a PKCS#7 message from PEM format. 19967 * 19968 * @param pem the PEM-formatted PKCS#7 message. 19969 * 19970 * @return the PKCS#7 message. 19971 */ 19972p7.messageFromPem = function(pem) { 19973 var msg = forge.pem.decode(pem)[0]; 19974 19975 if(msg.type !== 'PKCS7') { 19976 var error = new Error('Could not convert PKCS#7 message from PEM; PEM ' + 19977 'header type is not "PKCS#7".'); 19978 error.headerType = msg.type; 19979 throw error; 19980 } 19981 if(msg.procType && msg.procType.type === 'ENCRYPTED') { 19982 throw new Error('Could not convert PKCS#7 message from PEM; PEM is encrypted.'); 19983 } 19984 19985 // convert DER to ASN.1 object 19986 var obj = asn1.fromDer(msg.body); 19987 19988 return p7.messageFromAsn1(obj); 19989}; 19990 19991/** 19992 * Converts a PKCS#7 message to PEM format. 19993 * 19994 * @param msg The PKCS#7 message object 19995 * @param maxline The maximum characters per line, defaults to 64. 19996 * 19997 * @return The PEM-formatted PKCS#7 message. 19998 */ 19999p7.messageToPem = function(msg, maxline) { 20000 // convert to ASN.1, then DER, then PEM-encode 20001 var pemObj = { 20002 type: 'PKCS7', 20003 body: asn1.toDer(msg.toAsn1()).getBytes() 20004 }; 20005 return forge.pem.encode(pemObj, {maxline: maxline}); 20006}; 20007 20008/** 20009 * Converts a PKCS#7 message from an ASN.1 object. 20010 * 20011 * @param obj the ASN.1 representation of a ContentInfo. 20012 * 20013 * @return the PKCS#7 message. 20014 */ 20015p7.messageFromAsn1 = function(obj) { 20016 // validate root level ContentInfo and capture data 20017 var capture = {}; 20018 var errors = [];
20019 if(!asn1.validate(obj, p7.asn1.contentInfoValidator, capture, errors)) 20020 { 20021 var error = new Error('Cannot read PKCS#7 message. ' + 20022 'ASN.1 object is not an PKCS#7 ContentInfo.'); 20023 error.errors = errors; 20024 throw error; 20025 } 20026 20027 var contentType = asn1.derToOid(capture.contentType); 20028 var msg; 20029 20030 switch(contentType) { 20031 case forge.pki.oids.envelopedData: 20032 msg = p7.createEnvelopedData(); 20033 break; 20034 20035 case forge.pki.oids.encryptedData: 20036 msg = p7.createEncryptedData(); 20037 break; 20038 20039 case forge.pki.oids.signedData: 20040 msg = p7.createSignedData(); 20041 break; 20042 20043 default: 20044 throw new Error('Cannot read PKCS#7 message. ContentType with OID ' + 20045 contentType + ' is not (yet) supported.'); 20046 } 20047 20048 msg.fromAsn1(capture.content.value[0]); 20049 return msg; 20050}; 20051 20052p7.createSignedData = function() { 20053 var msg = null; 20054 msg = { 20055 type: forge.pki.oids.signedData, 20056 version: 1, 20057 certificates: [], 20058 crls: [], 20059 // TODO: add json-formatted signer stuff here? 20060 signers: [], 20061 // populated during sign() 20062 digestAlgorithmIdentifiers: [], 20063 contentInfo: null, 20064 signerInfos: [], 20065 20066 fromAsn1: function(obj) { 20067 // validate SignedData content block and capture data. 20068 _fromAsn1(msg, obj, p7.asn1.signedDataValidator); 20069 msg.certificates = []; 20070 msg.crls = []; 20071 msg.digestAlgorithmIdentifiers = []; 20072 msg.contentInfo = null; 20073 msg.signerInfos = []; 20074 20075 var certs = msg.rawCapture.certificates.value; 20076 for(var i = 0; i < certs.length; ++i) { 20077 msg.certificates.push(forge.pki.certificateFromAsn1(certs[i])); 20078 } 20079 20080 // TODO: parse crls 20081 }, 20082 20083 toAsn1: function() { 20084 // degenerate case with no content 20085 if(!msg.contentInfo) { 20086 msg.sign(); 20087 } 20088 20089 var certs = []; 20090 for(var i = 0; i < msg.certificates.length; ++i) { 20091 certs.push(forge.pki.certificateToAsn1(msg.certificates[i])); 20092 } 20093 20094 var crls = []; 20095 // TODO: implement CRLs 20096 20097 // [0] SignedData 20098 var signedData = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 20099 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20100 // Version 20101 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 20102 asn1.integerToDer(msg.version).getBytes()), 20103 // DigestAlgorithmIdentifiers 20104 asn1.create( 20105 asn1.Class.UNIVERSAL, asn1.Type.SET, true, 20106 msg.digestAlgorithmIdentifiers), 20107 // ContentInfo 20108 msg.contentInfo 20109 ]) 20110 ]); 20111 if(certs.length > 0) { 20112 // [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL 20113 signedData.value[0].value.push( 20114 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, certs)); 20115 } 20116 if(crls.length > 0) { 20117 // [1] IMPLICIT CertificateRevocationLists OPTIONAL 20118 signedData.value[0].value.push( 20119 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, crls)); 20120 } 20121 // SignerInfos 20122 signedData.value[0].value.push( 20123 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, 20124 msg.signerInfos)); 20125 20126 // ContentInfo 20127 return asn1.create( 20128 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20129 // ContentType 20130 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20131 asn1.oidToDer(msg.type).getBytes()), 20132 // [0] SignedData 20133 signedData 20134 ]); 20135 }, 20136 20137 /** 20138 * Add (another) entity to list of signers. 20139 * 20140 * Note: If authenticatedAttributes are provided, then, per RFC 2315, 20141 * they must include at least two attributes: content type and 20142 * message digest. The message digest attribute value will be 20143 * auto-calculated during signing and will be ignored if provided. 20144 * 20145 * Here's an example of providing these two attributes: 20146 * 20147 * forge.pkcs7.createSignedData(); 20148 * p7.addSigner({ 20149 * issuer: cert.issuer.attributes, 20150 * serialNumber: cert.serialNumber, 20151 * key: privateKey, 20152 * digestAlgorithm: forge.pki.oids.sha1, 20153 * authenticatedAttributes: [{ 20154 * type: forge.pki.oids.contentType, 20155 * value: forge.pki.oids.data 20156 * }, { 20157 * type: forge.pki.oids.messageDigest 20158 * }] 20159 * }); 20160 *
20161 * TODO: Support [subjectKeyIdentifier] as signer's ID. 20162 * 20163 * @param signer the signer information: 20164 * key the signer's private key. 20165 * [certificate] a certificate containing the public key 20166 * associated with the signer's private key; use this option as 20167 * an alternative to specifying signer.issuer and 20168 * signer.serialNumber. 20169 * [issuer] the issuer attributes (eg: cert.issuer.attributes). 20170 * [serialNumber] the signer's certificate's serial number in 20171 * hexadecimal (eg: cert.serialNumber). 20172 * [digestAlgorithm] the message digest OID, as a string, to use 20173 * (eg: forge.pki.oids.sha1). 20174 * [authenticatedAttributes] an optional array of attributes 20175 * to also sign along with the content. 20176 */ 20177 addSigner: function(signer) { 20178 var issuer = signer.issuer; 20179 var serialNumber = signer.serialNumber; 20180 if(signer.certificate) { 20181 var cert = signer.certificate; 20182 if(typeof cert === 'string') { 20183 cert = forge.pki.certificateFromPem(cert); 20184 } 20185 issuer = cert.issuer.attributes; 20186 serialNumber = cert.serialNumber; 20187 } 20188 var key = signer.key; 20189 if(!key) { 20190 throw new Error( 20191 'Could not add PKCS#7 signer; no private key specified.'); 20192 } 20193 if(typeof key === 'string') { 20194 key = forge.pki.privateKeyFromPem(key); 20195 } 20196 20197 // ensure OID known for digest algorithm 20198 var digestAlgorithm = signer.digestAlgorithm || forge.pki.oids.sha1; 20199 switch(digestAlgorithm) { 20200 case forge.pki.oids.sha1: 20201 case forge.pki.oids.sha256: 20202 case forge.pki.oids.sha384: 20203 case forge.pki.oids.sha512: 20204 case forge.pki.oids.md5: 20205 break; 20206 default: 20207 throw new Error( 20208 'Could not add PKCS#7 signer; unknown message digest algorithm: ' + 20209 digestAlgorithm); 20210 } 20211 20212 // if authenticatedAttributes is present, then the attributes 20213 // must contain at least PKCS #9 content-type and message-digest 20214 var authenticatedAttributes = signer.authenticatedAttributes || []; 20215 if(authenticatedAttributes.length > 0) { 20216 var contentType = false;
20217 var messageDigest = false; 20218 for(var i = 0; i < authenticatedAttributes.length; ++i) { 20219 var attr = authenticatedAttributes[i]; 20220 if(!contentType && attr.type === forge.pki.oids.contentType) { 20221 contentType = true; 20222 if(messageDigest) { 20223 break; 20224 } 20225 continue; 20226 } 20227 if(!messageDigest && attr.type === forge.pki.oids.messageDigest) { 20228 messageDigest = true; 20229 if(contentType) { 20230 break; 20231 } 20232 continue; 20233 } 20234 } 20235 20236 if(!contentType || !messageDigest) { 20237 throw new Error('Invalid signer.authenticatedAttributes. If ' + 20238 'signer.authenticatedAttributes is specified, then it must ' + 20239 'contain at least two attributes, PKCS #9 content-type and ' + 20240 'PKCS #9 message-digest.'); 20241 } 20242 } 20243 20244 msg.signers.push({ 20245 key: key, 20246 version: 1, 20247 issuer: issuer, 20248 serialNumber: serialNumber, 20249 digestAlgorithm: digestAlgorithm, 20250 signatureAlgorithm: forge.pki.oids.rsaEncryption, 20251 signature: null, 20252 authenticatedAttributes: authenticatedAttributes, 20253 unauthenticatedAttributes: [] 20254 }); 20255 }, 20256 20257 /** 20258 * Signs the content. 20259 */ 20260 sign: function() { 20261 // auto-generate content info 20262 if(typeof msg.content !== 'object' || msg.contentInfo === null) { 20263 // use Data ContentInfo 20264 msg.contentInfo = asn1.create( 20265 asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20266 // ContentType 20267 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20268 asn1.oidToDer(forge.pki.oids.data).getBytes()) 20269 ]); 20270 20271 // add actual content, if present 20272 if('content' in msg) { 20273 var content; 20274 if(msg.content instanceof forge.util.ByteBuffer) { 20275 content = msg.content.bytes(); 20276 } else if(typeof msg.content === 'string') { 20277 content = forge.util.encodeUtf8(msg.content); 20278 } 20279 20280 msg.contentInfo.value.push( 20281 // [0] EXPLICIT content 20282 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 20283 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 20284 content) 20285 ])); 20286 } 20287 } 20288 20289 // no signers, return early (degenerate case for certificate container) 20290 if(msg.signers.length === 0) { 20291 return; 20292 } 20293 20294 // generate digest algorithm identifiers 20295 var mds = addDigestAlgorithmIds(); 20296 20297 // generate signerInfos 20298 addSignerInfos(mds); 20299 }, 20300 20301 verify: function() { 20302 throw new Error('PKCS#7 signature verification not yet implemented.'); 20303 }, 20304 20305 /** 20306 * Add a certificate. 20307 * 20308 * @param cert the certificate to add. 20309 */ 20310 addCertificate: function(cert) { 20311 // convert from PEM 20312 if(typeof cert === 'string') { 20313 cert = forge.pki.certificateFromPem(cert); 20314 } 20315 msg.certificates.push(cert); 20316 }, 20317 20318 /** 20319 * Add a certificate revokation list. 20320 * 20321 * @param crl the certificate revokation list to add. 20322 */ 20323 addCertificateRevokationList: function(crl) { 20324 throw new Error('PKCS#7 CRL support not yet implemented.'); 20325 } 20326 }; 20327 return msg; 20328 20329 function addDigestAlgorithmIds() { 20330 var mds = {}; 20331 20332 for(var i = 0; i < msg.signers.length; ++i) { 20333 var signer = msg.signers[i]; 20334 var oid = signer.digestAlgorithm; 20335 if(!(oid in mds)) { 20336 // content digest 20337 mds[oid] = forge.md[forge.pki.oids[oid]].create(); 20338 } 20339 if(signer.authenticatedAttributes.length === 0) { 20340 // no custom attributes to digest; use content message digest 20341 signer.md = mds[oid]; 20342 } else { 20343 // custom attributes to be digested; use own message digest 20344 // TODO: optimize to just copy message digest state if that 20345 // feature is ever supported with message digests 20346 signer.md = forge.md[forge.pki.oids[oid]].create(); 20347 } 20348 } 20349 20350 // add unique digest algorithm identifiers 20351 msg.digestAlgorithmIdentifiers = []; 20352 for(var oid in mds) { 20353 msg.digestAlgorithmIdentifiers.push( 20354 // AlgorithmIdentifier 20355 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20356 // algorithm 20357 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20358 asn1.oidToDer(oid).getBytes()), 20359 // parameters (null) 20360 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 20361 ])); 20362 } 20363 20364 return mds; 20365 } 20366 20367 function addSignerInfos(mds) { 20368 // Note: ContentInfo is a SEQUENCE with 2 values, second value is 20369 // the content field and is optional for a ContentInfo but required here 20370 // since signers are present 20371 if(msg.contentInfo.value.length < 2) { 20372 throw new Error( 20373 'Could not sign PKCS#7 message; there is no content to sign.'); 20374 } 20375 20376 // get ContentInfo content type 20377 var contentType = asn1.derToOid(msg.contentInfo.value[0].value); 20378 20379 // get ContentInfo content 20380 var content = msg.contentInfo.value[1]; 20381 // skip [0] EXPLICIT content wrapper 20382 content = content.value[0]; 20383 20384 // serialize content 20385 var bytes = asn1.toDer(content); 20386 20387 // skip identifier and length per RFC 2315 9.3 20388 // skip identifier (1 byte) 20389 bytes.getByte(); 20390 // read and discard length bytes 20391 asn1.getBerValueLength(bytes); 20392 bytes = bytes.getBytes(); 20393
20394 // digest content DER value bytes 20395 for(var oid in mds) { 20396 mds[oid].start().update(bytes); 20397 } 20398 20399 // sign content 20400 var signingTime = new Date(); 20401 for(var i = 0; i < msg.signers.length; ++i) { 20402 var signer = msg.signers[i]; 20403 20404 if(signer.authenticatedAttributes.length === 0) { 20405 // if ContentInfo content type is not "Data", then 20406 // authenticatedAttributes must be present per RFC 2315 20407 if(contentType !== forge.pki.oids.data) { 20408 throw new Error( 20409 'Invalid signer; authenticatedAttributes must be present ' + 20410 'when the ContentInfo content type is not PKCS#7 Data.'); 20411 } 20412 } else { 20413 // process authenticated attributes 20414 // [0] IMPLICIT 20415 signer.authenticatedAttributesAsn1 = asn1.create( 20416 asn1.Class.CONTEXT_SPECIFIC, 0, true, []); 20417 20418 // per RFC 2315, attributes are to be digested using a SET container 20419 // not the above [0] IMPLICIT container 20420 var attrsAsn1 = asn1.create( 20421 asn1.Class.UNIVERSAL, asn1.Type.SET, true, []); 20422 20423 for(var ai = 0; ai < signer.authenticatedAttributes.length; ++ai) { 20424 var attr = signer.authenticatedAttributes[ai]; 20425 if(attr.type === forge.pki.oids.messageDigest) { 20426 // use content message digest as value 20427 attr.value = mds[signer.digestAlgorithm].digest(); 20428 } else if(attr.type === forge.pki.oids.signingTime) { 20429 // auto-populate signing time if not already set 20430 if(!attr.value) { 20431 attr.value = signingTime; 20432 } 20433 } 20434 20435 // convert to ASN.1 and push onto Attributes SET (for signing) and 20436 // onto authenticatedAttributesAsn1 to complete SignedData ASN.1 20437 // TODO: optimize away duplication 20438 attrsAsn1.value.push(_attributeToAsn1(attr)); 20439 signer.authenticatedAttributesAsn1.value.push(_attributeToAsn1(attr)); 20440 } 20441 20442 // DER-serialize and digest SET OF attributes only 20443 bytes = asn1.toDer(attrsAsn1).getBytes(); 20444 signer.md.start().update(bytes); 20445 } 20446 20447 // sign digest 20448 signer.signature = signer.key.sign(signer.md, 'RSASSA-PKCS1-V1_5'); 20449 } 20450 20451 // add signer info 20452 msg.signerInfos = _signersToAsn1(msg.signers); 20453 } 20454}; 20455 20456/** 20457 * Creates an empty PKCS#7 message of type EncryptedData. 20458 * 20459 * @return the message. 20460 */ 20461p7.createEncryptedData = function() { 20462 var msg = null; 20463 msg = { 20464 type: forge.pki.oids.encryptedData, 20465 version: 0, 20466 encryptedContent: { 20467 algorithm: forge.pki.oids['aes256-CBC'] 20468 }, 20469 20470 /** 20471 * Reads an EncryptedData content block (in ASN.1 format) 20472 * 20473 * @param obj The ASN.1 representation of the EncryptedData content block 20474 */ 20475 fromAsn1: function(obj) { 20476 // Validate EncryptedData content block and capture data. 20477 _fromAsn1(msg, obj, p7.asn1.encryptedDataValidator); 20478 }, 20479 20480 /** 20481 * Decrypt encrypted content 20482 * 20483 * @param key The (symmetric) key as a byte buffer 20484 */ 20485 decrypt: function(key) { 20486 if(key !== undefined) { 20487 msg.encryptedContent.key = key; 20488 } 20489 _decryptContent(msg); 20490 } 20491 }; 20492 return msg; 20493}; 20494 20495/** 20496 * Creates an empty PKCS#7 message of type EnvelopedData. 20497 * 20498 * @return the message. 20499 */ 20500p7.createEnvelopedData = function() { 20501 var msg = null; 20502 msg = { 20503 type: forge.pki.oids.envelopedData, 20504 version: 0, 20505 recipients: [], 20506 encryptedContent: { 20507 algorithm: forge.pki.oids['aes256-CBC'] 20508 }, 20509 20510 /** 20511 * Reads an EnvelopedData content block (in ASN.1 format) 20512 * 20513 * @param obj the ASN.1 representation of the EnvelopedData content block. 20514 */ 20515 fromAsn1: function(obj) { 20516 // validate EnvelopedData content block and capture data 20517 var capture = _fromAsn1(msg, obj, p7.asn1.envelopedDataValidator); 20518 msg.recipients = _recipientsFromAsn1(capture.recipientInfos.value); 20519 }, 20520 20521 toAsn1: function() { 20522 // ContentInfo 20523 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20524 // ContentType 20525 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20526 asn1.oidToDer(msg.type).getBytes()), 20527 // [0] EnvelopedData 20528 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 20529 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20530 // Version 20531 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 20532 asn1.integerToDer(msg.version).getBytes()), 20533 // RecipientInfos 20534 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, 20535 _recipientsToAsn1(msg.recipients)), 20536 // EncryptedContentInfo 20537 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, 20538 _encryptedContentToAsn1(msg.encryptedContent)) 20539 ]) 20540 ]) 20541 ]); 20542 }, 20543 20544 /** 20545 * Find recipient by X.509 certificate's issuer. 20546 * 20547 * @param cert the certificate with the issuer to look for. 20548 * 20549 * @return the recipient object. 20550 */ 20551 findRecipient: function(cert) { 20552 var sAttr = cert.issuer.attributes; 20553 20554 for(var i = 0; i < msg.recipients.length; ++i) { 20555 var r = msg.recipients[i]; 20556 var rAttr = r.issuer; 20557 20558 if(r.serialNumber !== cert.serialNumber) { 20559 continue; 20560 } 20561 20562 if(rAttr.length !== sAttr.length) { 20563 continue; 20564 } 20565 20566 var match = true; 20567 for(var j = 0; j < sAttr.length; ++j) {
20568 if(rAttr[j].type !== sAttr[j].type || 20569 rAttr[j].value !== sAttr[j].value) { 20570 match = false; 20571 break; 20572 } 20573 } 20574 20575 if(match) { 20576 return r; 20577 } 20578 } 20579 20580 return null; 20581 }, 20582 20583 /** 20584 * Decrypt enveloped content 20585 * 20586 * @param recipient The recipient object related to the private key 20587 * @param privKey The (RSA) private key object 20588 */ 20589 decrypt: function(recipient, privKey) { 20590 if(msg.encryptedContent.key === undefined && recipient !== undefined && 20591 privKey !== undefined) { 20592 switch(recipient.encryptedContent.algorithm) { 20593 case forge.pki.oids.rsaEncryption: 20594 case forge.pki.oids.desCBC: 20595 var key = privKey.decrypt(recipient.encryptedContent.content); 20596 msg.encryptedContent.key = forge.util.createBuffer(key); 20597 break; 20598 20599 default: 20600 throw new Error('Unsupported asymmetric cipher, ' + 20601 'OID ' + recipient.encryptedContent.algorithm); 20602 } 20603 } 20604 20605 _decryptContent(msg); 20606 }, 20607 20608 /** 20609 * Add (another) entity to list of recipients. 20610 * 20611 * @param cert The certificate of the entity to add. 20612 */ 20613 addRecipient: function(cert) { 20614 msg.recipients.push({ 20615 version: 0, 20616 issuer: cert.issuer.attributes, 20617 serialNumber: cert.serialNumber, 20618 encryptedContent: { 20619 // We simply assume rsaEncryption here, since forge.pki only 20620 // supports RSA so far. If the PKI module supports other 20621 // ciphers one day, we need to modify this one as well. 20622 algorithm: forge.pki.oids.rsaEncryption, 20623 key: cert.publicKey 20624 } 20625 }); 20626 }, 20627 20628 /** 20629 * Encrypt enveloped content. 20630 * 20631 * This function supports two optional arguments, cipher and key, which 20632 * can be used to influence symmetric encryption. Unless cipher is 20633 * provided, the cipher specified in encryptedContent.algorithm is used 20634 * (defaults to AES-256-CBC). If no key is provided, encryptedContent.key 20635 * is (re-)used. If that one's not set, a random key will be generated 20636 * automatically. 20637 * 20638 * @param [key] The key to be used for symmetric encryption. 20639 * @param [cipher] The OID of the symmetric cipher to use. 20640 */ 20641 encrypt: function(key, cipher) { 20642 // Part 1: Symmetric encryption 20643 if(msg.encryptedContent.content === undefined) { 20644 cipher = cipher || msg.encryptedContent.algorithm; 20645 key = key || msg.encryptedContent.key; 20646 20647 var keyLen, ivLen, ciphFn; 20648 switch(cipher) { 20649 case forge.pki.oids['aes128-CBC']: 20650 keyLen = 16; 20651 ivLen = 16; 20652 ciphFn = forge.aes.createEncryptionCipher; 20653 break; 20654 20655 case forge.pki.oids['aes192-CBC']: 20656 keyLen = 24; 20657 ivLen = 16; 20658 ciphFn = forge.aes.createEncryptionCipher; 20659 break; 20660 20661 case forge.pki.oids['aes256-CBC']: 20662 keyLen = 32; 20663 ivLen = 16; 20664 ciphFn = forge.aes.createEncryptionCipher; 20665 break; 20666 20667 case forge.pki.oids['des-EDE3-CBC']: 20668 keyLen = 24; 20669 ivLen = 8; 20670 ciphFn = forge.des.createEncryptionCipher; 20671 break; 20672 20673 default: 20674 throw new Error('Unsupported symmetric cipher, OID ' + cipher); 20675 } 20676 20677 if(key === undefined) { 20678 key = forge.util.createBuffer(forge.random.getBytes(keyLen)); 20679 } else if(key.length() != keyLen) { 20680 throw new Error('Symmetric key has wrong length; ' + 20681 'got ' + key.length() + ' bytes, expected ' + keyLen + '.'); 20682 } 20683 20684 // Keep a copy of the key & IV in the object, so the caller can 20685 // use it for whatever reason. 20686 msg.encryptedContent.algorithm = cipher; 20687 msg.encryptedContent.key = key; 20688 msg.encryptedContent.parameter = forge.util.createBuffer( 20689 forge.random.getBytes(ivLen)); 20690 20691 var ciph = ciphFn(key); 20692 ciph.start(msg.encryptedContent.parameter.copy()); 20693 ciph.update(msg.content); 20694 20695 // The finish function does PKCS#7 padding by default, therefore 20696 // no action required by us. 20697 if(!ciph.finish()) { 20698 throw new Error('Symmetric encryption failed.'); 20699 } 20700 20701 msg.encryptedContent.content = ciph.output; 20702 } 20703 20704 // Part 2: asymmetric encryption for each recipient 20705 for(var i = 0; i < msg.recipients.length; ++i) { 20706 var recipient = msg.recipients[i]; 20707 20708 // Nothing to do, encryption already done. 20709 if(recipient.encryptedContent.content !== undefined) { 20710 continue; 20711 } 20712 20713 switch(recipient.encryptedContent.algorithm) { 20714 case forge.pki.oids.rsaEncryption: 20715 recipient.encryptedContent.content =
20716 recipient.encryptedContent.key.encrypt( 20717 msg.encryptedContent.key.data); 20718 break; 20719 20720 default: 20721 throw new Error('Unsupported asymmetric cipher, OID ' + 20722 recipient.encryptedContent.algorithm); 20723 } 20724 } 20725 } 20726 }; 20727 return msg; 20728}; 20729 20730/** 20731 * Converts a single recipient from an ASN.1 object. 20732 * 20733 * @param obj the ASN.1 RecipientInfo. 20734 * 20735 * @return the recipient object. 20736 */ 20737function _recipientFromAsn1(obj) { 20738 // validate EnvelopedData content block and capture data 20739 var capture = {}; 20740 var errors = []; 20741 if(!asn1.validate(obj, p7.asn1.recipientInfoValidator, capture, errors)) { 20742 var error = new Error('Cannot read PKCS#7 RecipientInfo. ' + 20743 'ASN.1 object is not an PKCS#7 RecipientInfo.'); 20744 error.errors = errors; 20745 throw error; 20746 } 20747 20748 return { 20749 version: capture.version.charCodeAt(0), 20750 issuer: forge.pki.RDNAttributesAsArray(capture.issuer), 20751 serialNumber: forge.util.createBuffer(capture.serial).toHex(), 20752 encryptedContent: { 20753 algorithm: asn1.derToOid(capture.encAlgorithm), 20754 parameter: capture.encParameter.value, 20755 content: capture.encKey 20756 } 20757 }; 20758} 20759 20760/** 20761 * Converts a single recipient object to an ASN.1 object. 20762 * 20763 * @param obj the recipient object. 20764 * 20765 * @return the ASN.1 RecipientInfo. 20766 */ 20767function _recipientToAsn1(obj) { 20768 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20769 // Version 20770 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 20771 asn1.integerToDer(obj.version).getBytes()), 20772 // IssuerAndSerialNumber 20773 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20774 // Name 20775 forge.pki.distinguishedNameToAsn1({attributes: obj.issuer}), 20776 // Serial 20777 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 20778 forge.util.hexToBytes(obj.serialNumber)) 20779 ]), 20780 // KeyEncryptionAlgorithmIdentifier 20781 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20782 // Algorithm 20783 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20784 asn1.oidToDer(obj.encryptedContent.algorithm).getBytes()), 20785 // Parameter, force NULL, only RSA supported for now. 20786 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 20787 ]), 20788 // EncryptedKey 20789 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 20790 obj.encryptedContent.content) 20791 ]); 20792} 20793 20794/** 20795 * Map a set of RecipientInfo ASN.1 objects to recipient objects. 20796 * 20797 * @param infos an array of ASN.1 representations RecipientInfo (i.e. SET OF). 20798 * 20799 * @return an array of recipient objects. 20800 */ 20801function _recipientsFromAsn1(infos) { 20802 var ret = []; 20803 for(var i = 0; i < infos.length; ++i) { 20804 ret.push(_recipientFromAsn1(infos[i])); 20805 } 20806 return ret; 20807} 20808 20809/** 20810 * Map an array of recipient objects to ASN.1 RecipientInfo objects. 20811 * 20812 * @param recipients an array of recipientInfo objects. 20813 * 20814 * @return an array of ASN.1 RecipientInfos. 20815 */ 20816function _recipientsToAsn1(recipients) { 20817 var ret = []; 20818 for(var i = 0; i < recipients.length; ++i) { 20819 ret.push(_recipientToAsn1(recipients[i])); 20820 } 20821 return ret; 20822} 20823 20824/** 20825 * Converts a single signer from an ASN.1 object. 20826 * 20827 * @param obj the ASN.1 representation of a SignerInfo. 20828 * 20829 * @return the signer object. 20830 */ 20831function _signerFromAsn1(obj) { 20832 // validate EnvelopedData content block and capture data 20833 var capture = {}; 20834 var errors = []; 20835 if(!asn1.validate(obj, p7.asn1.signerInfoValidator, capture, errors)) { 20836 var error = new Error('Cannot read PKCS#7 SignerInfo. ' + 20837 'ASN.1 object is not an PKCS#7 SignerInfo.'); 20838 error.errors = errors; 20839 throw error; 20840 } 20841 20842 var rval = { 20843 version: capture.version.charCodeAt(0), 20844 issuer: forge.pki.RDNAttributesAsArray(capture.issuer), 20845 serialNumber: forge.util.createBuffer(capture.serial).toHex(), 20846 digestAlgorithm: asn1.derToOid(capture.digestAlgorithm), 20847 signatureAlgorithm: asn1.derToOid(capture.signatureAlgorithm), 20848 signature: capture.signature, 20849 authenticatedAttributes: [], 20850 unauthenticatedAttributes: [] 20851 }; 20852 20853 // TODO: convert attributes 20854 var authenticatedAttributes = capture.authenticatedAttributes || []; 20855 var unauthenticatedAttributes = capture.unauthenticatedAttributes || []; 20856 20857 return rval; 20858} 20859 20860/** 20861 * Converts a single signerInfo object to an ASN.1 object. 20862 * 20863 * @param obj the signerInfo object. 20864 * 20865 * @return the ASN.1 representation of a SignerInfo. 20866 */ 20867function _signerToAsn1(obj) { 20868 // SignerInfo 20869 var rval = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20870 // version 20871 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 20872 asn1.integerToDer(obj.version).getBytes()), 20873 // issuerAndSerialNumber 20874 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20875 // name 20876 forge.pki.distinguishedNameToAsn1({attributes: obj.issuer}), 20877 // serial 20878 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, 20879 forge.util.hexToBytes(obj.serialNumber)) 20880 ]), 20881 // digestAlgorithm 20882 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20883 // algorithm 20884 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20885 asn1.oidToDer(obj.digestAlgorithm).getBytes()), 20886 // parameters (null) 20887 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 20888 ]) 20889 ]); 20890 20891 // authenticatedAttributes (OPTIONAL) 20892 if(obj.authenticatedAttributesAsn1) { 20893 // add ASN.1 previously generated during signing 20894 rval.value.push(obj.authenticatedAttributesAsn1); 20895 } 20896 20897 // digestEncryptionAlgorithm 20898 rval.value.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 20899 // algorithm 20900 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20901 asn1.oidToDer(obj.signatureAlgorithm).getBytes()), 20902 // parameters (null) 20903 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') 20904 ])); 20905 20906 // encryptedDigest 20907 rval.value.push(asn1.create( 20908 asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, obj.signature)); 20909 20910 // unauthenticatedAttributes (OPTIONAL) 20911 if(obj.unauthenticatedAttributes.length > 0) { 20912 // [1] IMPLICIT 20913 var attrsAsn1 = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, []); 20914 for(var i = 0; i < obj.unauthenticatedAttributes.length; ++i) { 20915 var attr = obj.unauthenticatedAttributes[i]; 20916 attrsAsn1.values.push(_attributeToAsn1(attr)); 20917 } 20918 rval.value.push(attrsAsn1); 20919 } 20920 20921 return rval; 20922} 20923 20924/** 20925 * Map a set of SignerInfo ASN.1 objects to an array of signer objects. 20926 * 20927 * @param signerInfoAsn1s an array of ASN.1 SignerInfos (i.e. SET OF). 20928 * 20929 * @return an array of signers objects. 20930 */ 20931function _signersFromAsn1(signerInfoAsn1s) { 20932 var ret = []; 20933 for(var i = 0; i < signerInfoAsn1s.length; ++i) {
20934 ret.push(_signerFromAsn1(signerInfoAsn1s[i])); 20935 } 20936 return ret; 20937} 20938 20939/** 20940 * Map an array of signer objects to ASN.1 objects. 20941 * 20942 * @param signers an array of signer objects. 20943 * 20944 * @return an array of ASN.1 SignerInfos. 20945 */ 20946function _signersToAsn1(signers) { 20947 var ret = []; 20948 for(var i = 0; i < signers.length; ++i) { 20949 ret.push(_signerToAsn1(signers[i])); 20950 } 20951 return ret; 20952} 20953 20954/** 20955 * Convert an attribute object to an ASN.1 Attribute. 20956 * 20957 * @param attr the attribute object. 20958 * 20959 * @return the ASN.1 Attribute. 20960 */ 20961function _attributeToAsn1(attr) { 20962 var value; 20963 20964 // TODO: generalize to support more attributes 20965 if(attr.type === forge.pki.oids.contentType) { 20966 value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 20967 asn1.oidToDer(attr.value).getBytes()); 20968 } else if(attr.type === forge.pki.oids.messageDigest) { 20969 value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 20970 attr.value.bytes()); 20971 } else if(attr.type === forge.pki.oids.signingTime) { 20972 /* Note per RFC 2985: Dates between 1 January 1950 and 31 December 2049 20973 (inclusive) MUST be encoded as UTCTime. Any dates with year values 20974 before 1950 or after 2049 MUST be encoded as GeneralizedTime. [Further,] 20975 UTCTime values MUST be expressed in Greenwich Mean Time (Zulu) and MUST 20976 include seconds (i.e., times are YYMMDDHHMMSSZ), even where the 20977 number of seconds is zero. Midnight (GMT) must be represented as 20978 "YYMMDD000000Z". */ 20979 // TODO: make these module-level constants 20980 var jan_1_1950 = new Date('1950-01-01T00:00:00Z'); 20981 var jan_1_2050 = new Date('2050-01-01T00:00:00Z'); 20982 var date = attr.value; 20983 if(typeof date === 'string') { 20984 // try to parse date 20985 var timestamp = Date.parse(date); 20986 if(!isNaN(timestamp)) { 20987 date = new Date(timestamp); 20988 } else if(date.length === 13) { 20989 // YYMMDDHHMMSSZ (13 chars for UTCTime) 20990 date = asn1.utcTimeToDate(date); 20991 } else { 20992 // assume generalized time 20993 date = asn1.generalizedTimeToDate(date); 20994 } 20995 } 20996 20997 if(date >= jan_1_1950 && date < jan_1_2050) { 20998 value = asn1.create( 20999 asn1.Class.UNIVERSAL, asn1.Type.UTCTIME, false, 21000 asn1.dateToUtcTime(date)); 21001 } else { 21002 value = asn1.create( 21003 asn1.Class.UNIVERSAL, asn1.Type.GENERALIZEDTIME, false, 21004 asn1.dateToGeneralizedTime(date)); 21005 } 21006 } 21007 21008 // TODO: expose as common API call 21009 // create a RelativeDistinguishedName set 21010 // each value in the set is an AttributeTypeAndValue first 21011 // containing the type (an OID) and second the value 21012 return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 21013 // AttributeType 21014 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 21015 asn1.oidToDer(attr.type).getBytes()), 21016 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [ 21017 // AttributeValue 21018 value 21019 ]) 21020 ]); 21021} 21022 21023/** 21024 * Map messages encrypted content to ASN.1 objects. 21025 * 21026 * @param ec The encryptedContent object of the message. 21027 * 21028 * @return ASN.1 representation of the encryptedContent object (SEQUENCE). 21029 */ 21030function _encryptedContentToAsn1(ec) { 21031 return [ 21032 // ContentType, always Data for the moment 21033 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 21034 asn1.oidToDer(forge.pki.oids.data).getBytes()), 21035 // ContentEncryptionAlgorithmIdentifier 21036 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ 21037 // Algorithm 21038 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, 21039 asn1.oidToDer(ec.algorithm).getBytes()), 21040 // Parameters (IV) 21041 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 21042 ec.parameter.getBytes()) 21043 ]), 21044 // [0] EncryptedContent 21045 asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ 21046 asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, 21047 ec.content.getBytes()) 21048 ]) 21049 ]; 21050} 21051 21052/** 21053 * Reads the "common part" of an PKCS#7 content block (in ASN.1 format) 21054 * 21055 * This function reads the "common part" of the PKCS#7 content blocks 21056 * EncryptedData and EnvelopedData, i.e. version number and symmetrically 21057 * encrypted content block. 21058 * 21059 * The result of the ASN.1 validate and capture process is returned 21060 * to allow the caller to extract further data, e.g. the list of recipients 21061 * in case of a EnvelopedData object. 21062 * 21063 * @param msg the PKCS#7 object to read the data to. 21064 * @param obj the ASN.1 representation of the content block. 21065 * @param validator the ASN.1 structure validator object to use. 21066 * 21067 * @return the value map captured by validator object. 21068 */ 21069function _fromAsn1(msg, obj, validator) { 21070 var capture = {}; 21071 var errors = []; 21072 if(!asn1.validate(obj, validator, capture, errors)) { 21073 var error = new Error('Cannot read PKCS#7 message. ' + 21074 'ASN.1 object is not a supported PKCS#7 message.'); 21075 error.errors = error; 21076 throw error; 21077 } 21078 21079 // Check contentType, so far we only support (raw) Data. 21080 var contentType = asn1.derToOid(capture.contentType); 21081 if(contentType !== forge.pki.oids.data) { 21082 throw new Error('Unsupported PKCS#7 message. ' + 21083 'Only wrapped ContentType Data supported.'); 21084 } 21085 21086 if(capture.encryptedContent) { 21087 var content = ''; 21088 if(forge.util.isArray(capture.encryptedContent)) { 21089 for(var i = 0; i < capture.encryptedContent.length; ++i) { 21090 if(capture.encryptedContent[i].type !== asn1.Type.OCTETSTRING) { 21091 throw new Error('Malformed PKCS#7 message, expecting encrypted ' + 21092 'content constructed of only OCTET STRING objects.'); 21093 } 21094 content += capture.encryptedContent[i].value; 21095 } 21096 } else { 21097 content = capture.encryptedContent; 21098 } 21099 msg.encryptedContent = { 21100 algorithm: asn1.derToOid(capture.encAlgorithm), 21101 parameter: forge.util.createBuffer(capture.encParameter.value), 21102 content: forge.util.createBuffer(content) 21103 }; 21104 } 21105 21106 if(capture.content) { 21107 var content = ''; 21108 if(forge.util.isArray(capture.content)) { 21109 for(var i = 0; i < capture.content.length; ++i) { 21110 if(capture.content[i].type !== asn1.Type.OCTETSTRING) { 21111 throw new Error('Malformed PKCS#7 message, expecting ' + 21112 'content constructed of only OCTET STRING objects.'); 21113 } 21114 content += capture.content[i].value; 21115 } 21116 } else { 21117 content = capture.content; 21118 } 21119 msg.content = forge.util.createBuffer(content); 21120 } 21121 21122 msg.version = capture.version.charCodeAt(0); 21123 msg.rawCapture = capture; 21124 21125 return capture; 21126} 21127
21128/** 21129 * Decrypt the symmetrically encrypted content block of the PKCS#7 message. 21130 * 21131 * Decryption is skipped in case the PKCS#7 message object already has a 21132 * (decrypted) content attribute. The algorithm, key and cipher parameters 21133 * (probably the iv) are taken from the encryptedContent attribute of the 21134 * message object. 21135 * 21136 * @param The PKCS#7 message object. 21137 */ 21138function _decryptContent(msg) { 21139 if(msg.encryptedContent.key === undefined) { 21140 throw new Error('Symmetric key not available.'); 21141 } 21142 21143 if(msg.content === undefined) { 21144 var ciph; 21145 21146 switch(msg.encryptedContent.algorithm) { 21147 case forge.pki.oids['aes128-CBC']: 21148 case forge.pki.oids['aes192-CBC']: 21149 case forge.pki.oids['aes256-CBC']: 21150 ciph = forge.aes.createDecryptionCipher(msg.encryptedContent.key); 21151 break; 21152 21153 case forge.pki.oids['desCBC']: 21154 case forge.pki.oids['des-EDE3-CBC']: 21155 ciph = forge.des.createDecryptionCipher(msg.encryptedContent.key); 21156 break; 21157 21158 default: 21159 throw new Error('Unsupported symmetric cipher, OID ' + 21160 msg.encryptedContent.algorithm); 21161 } 21162 ciph.start(msg.encryptedContent.parameter); 21163 ciph.update(msg.encryptedContent.content); 21164 21165 if(!ciph.finish()) { 21166 throw new Error('Symmetric decryption failed.'); 21167 } 21168 21169 msg.content = ciph.output; 21170 } 21171} 21172 21173} // end module implementation 21174 21175/* ########## Begin module wrapper ########## */ 21176var name = 'pkcs7'; 21177if(typeof define !== 'function') { 21178 // NodeJS -> AMD 21179 if(typeof module === 'object' && module.exports) { 21180 var nodeJS = true; 21181 define = function(ids, factory) { 21182 factory(require, module); 21183 }; 21184 } else { 21185 // <script> 21186 if(typeof forge === 'undefined') { 21187 forge = {}; 21188 } 21189 return initModule(forge); 21190 } 21191} 21192// AMD 21193var deps; 21194var defineFunc = function(require, module) { 21195 module.exports = function(forge) { 21196 var mods = deps.map(function(dep) { 21197 return require(dep); 21198 }).concat(initModule); 21199 // handle circular dependencies 21200 forge = forge || {}; 21201 forge.defined = forge.defined || {}; 21202 if(forge.defined[name]) { 21203 return forge[name]; 21204 } 21205 forge.defined[name] = true; 21206 for(var i = 0; i < mods.length; ++i) { 21207 mods[i](forge); 21208 } 21209 return forge[name]; 21210 }; 21211}; 21212var tmpDefine = define; 21213define = function(ids, factory) { 21214 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 21215 if(nodeJS) { 21216 delete define; 21217 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 21218 } 21219 define = tmpDefine; 21220 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 21221}; 21222define([ 21223 'require', 21224 'module', 21225 './aes', 21226 './asn1', 21227 './des', 21228 './oids', 21229 './pem', 21230 './pkcs7asn1', 21231 './random', 21232 './util', 21233 './x509' 21234], function() { 21235 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 21236}); 21237})(); 21238 21239/** 21240 * Prime number generation API. 21241 * 21242 * @author Dave Longley 21243 * 21244 * Copyright (c) 2014 Digital Bazaar, Inc. 21245 */ 21246(function() { 21247/* ########## Begin module implementation ########## */ 21248function initModule(forge) { 21249 21250// forge.prime already defined 21251if(forge.prime) { 21252 return; 21253} 21254 21255/* PRIME API */ 21256var prime = forge.prime = forge.prime || {}; 21257 21258var BigInteger = forge.jsbn.BigInteger; 21259 21260// primes are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29 21261var GCD_30_DELTA = [6, 4, 2, 4, 2, 4, 6, 2]; 21262var THIRTY = new BigInteger(null); 21263THIRTY.fromInt(30); 21264var op_or = function(x, y) {return x|y;}; 21265 21266/** 21267 * Generates a random probable prime with the given number of bits. 21268 * 21269 * Alternative algorithms can be specified by name as a string or as an 21270 * object with custom options like so: 21271 * 21272 * { 21273 * name: 'PRIMEINC', 21274 * options: { 21275 * maxBlockTime: <the maximum amount of time to block the main 21276 * thread before allowing I/O other JS to run>, 21277 * millerRabinTests: <the number of miller-rabin tests to run>, 21278 * workerScript: <the worker script URL>, 21279 * workers: <the number of web workers (if supported) to use, 21280 * -1 to use estimated cores minus one>. 21281 * workLoad: the size of the work load, ie: number of possible prime 21282 * numbers for each web worker to check per work assignment, 21283 * (default: 100). 21284 * } 21285 * } 21286 * 21287 * @param bits the number of bits for the prime number. 21288 * @param options the options to use. 21289 * [algorithm] the algorithm to use (default: 'PRIMEINC'). 21290 * [prng] a custom crypto-secure pseudo-random number generator to use, 21291 * that must define "getBytesSync". 21292 * 21293 * @return callback(err, num) called once the operation completes. 21294 */ 21295prime.generateProbablePrime = function(bits, options, callback) { 21296 if(typeof options === 'function') { 21297 callback = options; 21298 options = {}; 21299 } 21300 options = options || {}; 21301 21302 // default to PRIMEINC algorithm 21303 var algorithm = options.algorithm || 'PRIMEINC'; 21304 if(typeof algorithm === 'string') { 21305 algorithm = {name: algorithm}; 21306 } 21307 algorithm.options = algorithm.options || {}; 21308 21309 // create prng with api that matches BigInteger secure random 21310 var prng = options.prng || forge.random; 21311 var rng = { 21312 // x is an array to fill with bytes 21313 nextBytes: function(x) { 21314 var b = prng.getBytesSync(x.length); 21315 for(var i = 0; i < x.length; ++i) { 21316 x[i] = b.charCodeAt(i); 21317 } 21318 } 21319 }; 21320 21321 if(algorithm.name === 'PRIMEINC') { 21322 return primeincFindPrime(bits, rng, algorithm.options, callback); 21323 } 21324 21325 throw new Error('Invalid prime generation algorithm: ' + algorithm.name); 21326}; 21327 21328function primeincFindPrime(bits, rng, options, callback) { 21329 if('workers' in options) { 21330 return primeincFindPrimeWithWorkers(bits, rng, options, callback); 21331 } 21332 return primeincFindPrimeWithoutWorkers(bits, rng, options, callback); 21333} 21334 21335function primeincFindPrimeWithoutWorkers(bits, rng, options, callback) { 21336 // initialize random number 21337 var num = generateRandom(bits, rng); 21338 21339 /* Note: All primes are of the form 30k+i for i < 30 and gcd(30, i)=1. The 21340 number we are given is always aligned at 30k + 1. Each time the number is 21341 determined not to be prime we add to get to the next 'i', eg: if the number 21342 was at 30k + 1 we add 6. */ 21343 var deltaIdx = 0; 21344 21345 // get required number of MR tests 21346 var mrTests = getMillerRabinTests(num.bitLength());
21347 if('millerRabinTests' in options) { 21348 mrTests = options.millerRabinTests; 21349 } 21350 21351 // find prime nearest to 'num' for maxBlockTime ms 21352 // 10 ms gives 5ms of leeway for other calculations before dropping 21353 // below 60fps (1000/60 == 16.67), but in reality, the number will 21354 // likely be higher due to an 'atomic' big int modPow 21355 var maxBlockTime = 10; 21356 if('maxBlockTime' in options) { 21357 maxBlockTime = options.maxBlockTime; 21358 } 21359 var start = +new Date(); 21360 do { 21361 // overflow, regenerate random number 21362 if(num.bitLength() > bits) { 21363 num = generateRandom(bits, rng); 21364 } 21365 // do primality test 21366 if(num.isProbablePrime(mrTests)) { 21367 return callback(null, num); 21368 } 21369 // get next potential prime 21370 num.dAddOffset(GCD_30_DELTA[deltaIdx++ % 8], 0); 21371 } while(maxBlockTime < 0 || (+new Date() - start < maxBlockTime)); 21372 21373 // keep trying (setImmediate would be better here) 21374 forge.util.setImmediate(function() { 21375 primeincFindPrimeWithoutWorkers(bits, rng, options, callback); 21376 }); 21377} 21378 21379function primeincFindPrimeWithWorkers(bits, rng, options, callback) { 21380 // web workers unavailable 21381 if(typeof Worker === 'undefined') { 21382 return primeincFindPrimeWithoutWorkers(bits, rng, options, callback); 21383 } 21384 21385 // initialize random number 21386 var num = generateRandom(bits, rng); 21387 21388 // use web workers to generate keys 21389 var numWorkers = options.workers; 21390 var workLoad = options.workLoad || 100; 21391 var range = workLoad * 30 / 8; 21392 var workerScript = options.workerScript || 'forge/prime.worker.js'; 21393 if(numWorkers === -1) { 21394 return forge.util.estimateCores(function(err, cores) { 21395 if(err) { 21396 // default to 2 21397 cores = 2; 21398 } 21399 numWorkers = cores - 1; 21400 generate(); 21401 }); 21402 } 21403 generate(); 21404 21405 function generate() { 21406 // require at least 1 worker 21407 numWorkers = Math.max(1, numWorkers); 21408 21409 // TODO: consider optimizing by starting workers outside getPrime() ... 21410 // note that in order to clean up they will have to be made internally 21411 // asynchronous which may actually be slower 21412 21413 // start workers immediately 21414 var workers = []; 21415 for(var i = 0; i < numWorkers; ++i) { 21416 // FIXME: fix path or use blob URLs 21417 workers[i] = new Worker(workerScript); 21418 } 21419 var running = numWorkers; 21420 21421 // listen for requests from workers and assign ranges to find prime 21422 for(var i = 0; i < numWorkers; ++i) { 21423 workers[i].addEventListener('message', workerMessage); 21424 } 21425 21426 /* Note: The distribution of random numbers is unknown. Therefore, each 21427 web worker is continuously allocated a range of numbers to check for a 21428 random number until one is found. 21429 21430 Every 30 numbers will be checked just 8 times, because prime numbers 21431 have the form: 21432 21433 30k+i, for i < 30 and gcd(30, i)=1 (there are 8 values of i for this) 21434 21435 Therefore, if we want a web worker to run N checks before asking for 21436 a new range of numbers, each range must contain N*30/8 numbers. 21437 21438 For 100 checks (workLoad), this is a range of 375. */ 21439 21440 var found = false; 21441 function workerMessage(e) { 21442 // ignore message, prime already found 21443 if(found) { 21444 return; 21445 } 21446 21447 --running; 21448 var data = e.data; 21449 if(data.found) { 21450 // terminate all workers 21451 for(var i = 0; i < workers.length; ++i) { 21452 workers[i].terminate(); 21453 } 21454 found = true; 21455 return callback(null, new BigInteger(data.prime, 16)); 21456 } 21457 21458 // overflow, regenerate random number 21459 if(num.bitLength() > bits) { 21460 num = generateRandom(bits, rng); 21461 } 21462 21463 // assign new range to check 21464 var hex = num.toString(16); 21465 21466 // start prime search 21467 e.target.postMessage({ 21468 hex: hex, 21469 workLoad: workLoad 21470 }); 21471 21472 num.dAddOffset(range, 0); 21473 } 21474 } 21475} 21476 21477/** 21478 * Generates a random number using the given number of bits and RNG. 21479 * 21480 * @param bits the number of bits for the number. 21481 * @param rng the random number generator to use. 21482 * 21483 * @return the random number. 21484 */ 21485function generateRandom(bits, rng) { 21486 var num = new BigInteger(bits, rng); 21487 // force MSB set 21488 var bits1 = bits - 1; 21489 if(!num.testBit(bits1)) { 21490 num.bitwiseTo(BigInteger.ONE.shiftLeft(bits1), op_or, num); 21491 } 21492 // align number on 30k+1 boundary 21493 num.dAddOffset(31 - num.mod(THIRTY).byteValue(), 0); 21494 return num; 21495} 21496
21497/** 21498 * Returns the required number of Miller-Rabin tests to generate a 21499 * prime with an error probability of (1/2)^80. 21500 * 21501 * See Handbook of Applied Cryptography Chapter 4, Table 4.4. 21502 * 21503 * @param bits the bit size. 21504 * 21505 * @return the required number of iterations. 21506 */ 21507function getMillerRabinTests(bits) { 21508 if(bits <= 100) return 27; 21509 if(bits <= 150) return 18; 21510 if(bits <= 200) return 15; 21511 if(bits <= 250) return 12; 21512 if(bits <= 300) return 9; 21513 if(bits <= 350) return 8; 21514 if(bits <= 400) return 7; 21515 if(bits <= 500) return 6; 21516 if(bits <= 600) return 5; 21517 if(bits <= 800) return 4; 21518 if(bits <= 1250) return 3; 21519 return 2; 21520} 21521 21522} // end module implementation 21523 21524/* ########## Begin module wrapper ########## */ 21525var name = 'prime'; 21526if(typeof define !== 'function') { 21527 // NodeJS -> AMD 21528 if(typeof module === 'object' && module.exports) { 21529 var nodeJS = true; 21530 define = function(ids, factory) { 21531 factory(require, module); 21532 }; 21533 } else { 21534 // <script> 21535 if(typeof forge === 'undefined') { 21536 forge = {}; 21537 } 21538 return initModule(forge); 21539 } 21540} 21541// AMD 21542var deps; 21543var defineFunc = function(require, module) { 21544 module.exports = function(forge) { 21545 var mods = deps.map(function(dep) { 21546 return require(dep); 21547 }).concat(initModule); 21548 // handle circular dependencies 21549 forge = forge || {}; 21550 forge.defined = forge.defined || {}; 21551 if(forge.defined[name]) { 21552 return forge[name]; 21553 } 21554 forge.defined[name] = true; 21555 for(var i = 0; i < mods.length; ++i) { 21556 mods[i](forge); 21557 } 21558 return forge[name]; 21559 }; 21560}; 21561var tmpDefine = define; 21562define = function(ids, factory) { 21563 deps = (typeof ids === 'string') ? factory.slice(2) : ids.slice(2); 21564 if(nodeJS) { 21565 delete define; 21566 return tmpDefine.apply(null, Array.prototype.slice.call(arguments, 0)); 21567 } 21568 define = tmpDefine; 21569 return define.apply(null, Array.prototype.slice.call(arguments, 0)); 21570}; 21571define(['require', 'module', './util', './jsbn', './random'], function() { 21572 defineFunc.apply(null, Array.prototype.slice.call(arguments, 0)); 21573}); 21574 21575})(); 21576 21577/*----------------------------------------------------------------------------*/ 21578 /* 21579 * CGJSCrypt v1.0.17.223 21580 */ 21581/*----------------------------------------------------------------------------*/ 21582 21583var PKI = forge.pki; 21584var UTIL = forge.util; 21585var RANDOM = forge.random; 21586var MD = forge.md; 21587var PKCS12 = forge.pkcs12; 21588var ASN1 = forge.asn1; 21589var PBKDF2 = forge.pbkdf2; 21590var AES = forge.aes; 21591var HMAC = forge.hmac; 21592var DES = forge.des; 21593var BigInteger = forge.jsbn.BigInteger; 21594var PKCS7 = forge.pkcs7; 21595 21596function CGJSCrypt(){} 21597 21598function E(privateKey,prikeypwd) { 21599 var p = privateKey.p.toString(16); 21600 var q = privateKey.q.toString(16); 21601 21602 var m = UTIL.hexToBytes(p+q); 21603 21604 var salt = RANDOM.getBytes(20); 21605 var dk = PBKDF2(prikeypwd,salt,1000,48); 21606 21607 var k = dk.substring(0,32); 21608 var iv = dk.substring(32,48); 21609 var input = UTIL.createBuffer(m); 21610 21611 var c = AES.createEncryptionCipher(k, 'CBC'); 21612 c.start(iv); 21613 c.update(input); 21614 c.finish(); 21615 21616 var pq = UTIL.hexToBytes(c.output.toHex()+UTIL.bytesToHex(salt)); 21617 21618 return pq; 21619} 21620 21621function D(pq,prikeypwd) { 21622 var salt = pq.substring(pq.length-pq.length%128+16); 21623 var m = pq.substring(0,(pq.length-salt.length)); 21624 21625 var dk = PBKDF2(prikeypwd,salt,1000,48); 21626 21627 var k = dk.substring(0,32); 21628 var iv = dk.substring(32,48); 21629 var input = UTIL.createBuffer(m); 21630 21631 var c = AES.createDecryptionCipher(k, 'CBC'); 21632 c.start(iv); 21633 c.update(input); 21634 if(!c.finish()) 21635 throw new Error('Unable to decrypt PrivateKey, wrong password?'); 21636 21637 var t = UTIL.hexToBytes(c.output.toHex()); 21638 21639 if(t.length%128!=0) 21640 throw new Error('Invalid PrivateKey, wrong data?'); 21641 21642 var p = new BigInteger(UTIL.bytesToHex(t.substring(0,t.length/2)),16); 21643 var q = new BigInteger(UTIL.bytesToHex(t.substring(t.length/2)),16); 21644 21645 var p1 = p.subtract(BigInteger.ONE); 21646 var q1 = q.subtract(BigInteger.ONE); 21647 var phi = p1.multiply(q1); 21648 var e = new BigInteger(null); 21649 e.fromInt(0x10001); 21650 var d = e.modInverse(phi); 21651 var n = p.multiply(q); 21652 var dP = d.mod(p1); 21653 var dQ = d.mod(q1); 21654 var qInv = q.modInverse(p); 21655 21656 var privateKey = PKI.rsa.setPrivateKey(n, e, d, p, q, dP, dQ, qInv); 21657 21658 return privateKey; 21659} 21660 21661var ErrorCode = 0; 21662var ErrorMsg = ""; 21663 21664function R() 21665{ 21666 ErrorCode = 0; 21667 ErrorMsg = ""; 21668} 21669 21670CGJSCrypt.GetErrorCode = function(){return ErrorCode;} 21671CGJSCrypt.GetErrorMsg = function(){return ErrorMsg;} 21672 21673CGJSCrypt.CertEncrypt = function(public_key, input, iflags) { return CGJSCrypt.PublicEncrypt(public_key, input, iflags); } 21674CGJSCrypt.PEMCertEncrypt = function(pem_cert, input, iflags) { return CGJSCrypt.CertPublicEncrypt(pem_cert, input, iflags); } 21675 21676CGJSCrypt.PublicEncrypt = function(public_key, input, iflags) { 21677 var publicKey = PKI.publicKeyFromPem(public_key);
21678 var cipher = publicKey.encrypt(input); 21679 return UTIL.encode64(cipher); 21680} 21681 21682CGJSCrypt.CertPublicEncrypt = function(pem_cert, input, iflags) { 21683 var publicKey = PKI.certificateFromPem(pem_cert).publicKey; 21684 var cipher = publicKey.encrypt(input); 21685 return UTIL.encode64(cipher); 21686} 21687 21688function S(o) { 21689 var s = ''; 21690 for(var i = 0; i < o.attributes.length; ++i) { 21691 if(i>0) s += ", "; 21692 var a = o.attributes[i]; 21693 s += a.shortName+"="+a.value; 21694 } 21695 return s; 21696} 21697 21698function S_Getcn(o) { 21699 var s = ''; 21700 for(var i = 0; i < o.attributes.length; ++i) { 21701 var a = o.attributes[i]; 21702 if(a == "CN" || a.shortName == "CN"){ 21703 s = a.value; 21704 break; 21705 } 21706 } 21707 return s; 21708} 21709 21710CGJSCrypt.CertGetSubject = function(pem_cert, iflags) { 21711 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21712 if(index == -1) 21713 { 21714 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21715 } 21716 var c = PKI.certificateFromPem(pem_cert); 21717 return S(c.subject); 21718} 21719 21720CGJSCrypt.CertGetCN = function(pem_cert, iflags) { 21721 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21722 if(index == -1) 21723 { 21724 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21725 } 21726 var c = PKI.certificateFromPem(pem_cert); 21727 return S_Getcn(c.subject); 21728} 21729 21730CGJSCrypt.CertGetIssuer = function(pem_cert, iflags) { 21731 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21732 if(index == -1) 21733 { 21734 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21735 } 21736 var c = PKI.certificateFromPem(pem_cert); 21737 return S(c.issuer); 21738} 21739 21740function F(o) { 21741 var y = o.getFullYear(); 21742 var m = o.getMonth()+1; 21743 if(m.toString().length==1) m = '0'+m; 21744 var d = o.getDate(); 21745 if(d.toString().length==1) d = '0'+d; 21746 var h = o.getHours(); 21747 if(h.toString().length==1) h = '0'+h; 21748 var mm = o.getMinutes(); 21749 if(mm.toString().length==1) mm = '0'+mm; 21750 var s = o.getSeconds(); 21751 if(s.toString().length==1) s = '0'+s; 21752 21753 var ss = ''+y+"-"+m+"-"+d+' '+h+':'+mm+':'+s; 21754 return ss; 21755} 21756 21757CGJSCrypt.CertGetNotBefore = function(pem_cert, iflags) { 21758 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21759 if(index == -1) 21760 { 21761 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21762 } 21763 var c = PKI.certificateFromPem(pem_cert); 21764 return F(c.validity.notBefore); 21765} 21766 21767CGJSCrypt.CertGetNotAfter = function(pem_cert, iflags) { 21768 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21769 if(index == -1) 21770 { 21771 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21772 } 21773 var c = PKI.certificateFromPem(pem_cert); 21774 return F(c.validity.notAfter); 21775} 21776 21777CGJSCrypt.CertGetSerialNumber = function(pem_cert, iflags) { 21778 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21779 if(index == -1) 21780 { 21781 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21782 } 21783 return PKI.certificateFromPem(pem_cert).serialNumber; 21784} 21785 21786CGJSCrypt.CertGetDigest = function(pem_cert, iflags) { 21787 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21788 if(index == -1) 21789 { 21790 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21791 } 21792 var c = PKI.certificateFromPem(pem_cert); 21793 var m = ASN1.toDer(PKI.certificateToAsn1(c)).getBytes(); 21794 var md = MD.sha1.create(); 21795 md.start(); 21796 md.update(m); 21797 var d = md.digest(); 21798 return d.toHex(); 21799} 21800 21801CGJSCrypt.CertGetKeySize = function(pem_cert, iflags) { 21802 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21803 if(index == -1) 21804 { 21805 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21806 } 21807 return PKI.certificateFromPem(pem_cert).publicKey.n.bitLength(); 21808} 21809 21810CGJSCrypt.CertGetSignAlgorithm = function(pem_cert, iflags) { 21811 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 21812 if(index == -1) 21813 { 21814 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 21815 } 21816 var c = PKI.certificateFromPem(pem_cert); 21817 return PKI.oids[c.siginfo.algorithmOid]; 21818} 21819 21820CGJSCrypt.EncodePriKey = function(prikey,prikeypwd,prikeyencalgo) { 21821 var privateKey = D(prikey,prikeypwd); 21822 return PKI.encryptRsaPrivateKey(privateKey, prikeypwd, {algorithm:prikeyencalgo,legacy:'1'}); 21823} 21824 21825CGJSCrypt.ParsePKCS12 = function(b64pfx, pfxpwd, prikeypwd, iflags) { 21826 var p12Der = UTIL.decode64(b64pfx); 21827 var p12Asn1 = ASN1.fromDer(p12Der); 21828 21829 var p12 = PKCS12.pkcs12FromAsn1(p12Asn1,pfxpwd); 21830 21831 for(var sci = 0; sci < p12.safeContents.length; ++sci) { 21832 var safeContents = p12.safeContents[sci]; 21833 21834 for(var sbi = 0; sbi < safeContents.safeBags.length; ++sbi) { 21835 var safeBag = safeContents.safeBags[sbi]; 21836 21837 if(!safeBag.attributes.localKeyId) { 21838 continue; 21839 } 21840 21841 if(safeBag.type === PKI.oids.pkcs8ShroudedKeyBag) { 21842 CGJSCrypt.privateKey = E(safeBag.key, prikeypwd); //PKI.encryptRsaPrivateKey(safeBag.key, prikeypwd, {algorithm:prikeyencalgo,legacy:'1'}); 21843 } else if(safeBag.type === PKI.oids.certBag) { 21844 CGJSCrypt.publicKey = PKI.publicKeyToRSAPublicKeyPem(safeBag.cert.publicKey); 21845 CGJSCrypt.cert = PKI.certificateToPem(safeBag.cert); 21846 } 21847 } 21848 } 21849} 21850 21851function C(obj, password, options) { 21852 // set default options 21853 options = options || {}; 21854 options.saltSize = options.saltSize || 8; 21855 options.count = options.count || 2048; 21856 21857 // generate PBE params 21858 var salt = RANDOM.getBytesSync(options.saltSize); 21859 var count = options.count; 21860 var countBytes = ASN1.integerToDer(count); 21861 var dkLen; 21862 var encryptionAlgorithm; 21863 var encryptedData; 21864 21865 // Do PKCS12 PBE 21866 dkLen = 24; 21867 21868 var saltBytes = new UTIL.ByteBuffer(salt); 21869 var dk = PKI.pbe.generatePkcs12Key(password, saltBytes, 1, count, dkLen); 21870 var iv = PKI.pbe.generatePkcs12Key(password, saltBytes, 2, count, dkLen); 21871 var cipher = DES.createEncryptionCipher(dk); 21872 cipher.start(iv); 21873 cipher.update(ASN1.toDer(obj)); 21874 cipher.finish(); 21875 encryptedData = cipher.output.getBytes(); 21876 21877 encryptionAlgorithm = ASN1.create( 21878 ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 21879 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 21880 ASN1.oidToDer(PKI.oids['pbeWithSHAAnd3-KeyTripleDES-CBC']).getBytes()),
21881 // pkcs-12PbeParams 21882 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 21883 // salt 21884 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, salt), 21885 // iteration count 21886 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.INTEGER, false, 21887 countBytes.getBytes()) 21888 ]) 21889 ]); 21890 21891 var rval = 21892 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 21893 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false,ASN1.oidToDer(PKI.oids.data).getBytes()), 21894 encryptionAlgorithm, 21895 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, false, encryptedData)]); 21896 return rval; 21897}; 21898 21899function P(key, cert, password, options) { 21900 // set default options 21901 options = options || {}; 21902 options.saltSize = options.saltSize || 8; 21903 options.count = options.count || 2048; 21904 options.algorithm = options.algorithm || options.encAlgorithm || 'aes128'; 21905 if(!('useMac' in options)) { 21906 options.useMac = true; 21907 } 21908 if(!('localKeyId' in options)) { 21909 options.localKeyId = null; 21910 } 21911 if(!('generateLocalKeyId' in options)) { 21912 options.generateLocalKeyId = true; 21913 } 21914 21915 var localKeyId = options.localKeyId; 21916 var keyAttrs, certAttrs; 21917 if(localKeyId !== null) { 21918 localKeyId = UTIL.hexToBytes(localKeyId); 21919 } else if(options.generateLocalKeyId) { 21920 // use SHA-1 of paired cert, if available 21921 if(cert) { 21922 var pairedCert = UTIL.isArray(cert) ? cert[0] : cert; 21923 if(typeof pairedCert === 'string') { 21924 pairedCert = PKI.certificateFromPem(pairedCert); 21925 } 21926 var sha1 = MD.sha1.create(); 21927 sha1.update(ASN1.toDer(PKI.certificateToAsn1(pairedCert)).getBytes()); 21928 localKeyId = sha1.digest().getBytes(); 21929 } else { 21930 // FIXME: consider using SHA-1 of public key (which can be generated 21931 // from private key components), see: cert.generateSubjectKeyIdentifier 21932 // generate random bytes 21933 localKeyId = RANDOM.getBytes(20); 21934 } 21935 } 21936 21937 var attrs = [], certattrs = []; 21938 if(localKeyId !== null) { 21939 attrs.push( 21940 // localKeyID 21941 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 21942 // attrId 21943 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 21944 ASN1.oidToDer(PKI.oids.localKeyId).getBytes()), 21945 // attrValues 21946 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SET, true, [ 21947 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 21948 localKeyId) 21949 ]) 21950 ])); 21951 certattrs.push( 21952 // localKeyID 21953 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 21954 // attrId 21955 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 21956 ASN1.oidToDer(PKI.oids.localKeyId).getBytes()), 21957 // attrValues 21958 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SET, true, [ 21959 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 21960 localKeyId) 21961 ]) 21962 ])); 21963 } 21964 21965 if(attrs.length > 0) { 21966 keyAttrs = ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SET, true, attrs); 21967 certAttrs = ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SET, true, certattrs); 21968 } 21969 21970 // collect contents for AuthenticatedSafe 21971 var contents = []; 21972 21973 // create safe contents for private key 21974 var keyBag = null; 21975 if(key !== null) { 21976 // SafeBag 21977 var pkAsn1 = PKI.wrapRsaPrivateKey(PKI.privateKeyToAsn1(key)); 21978 if(password === null) { 21979 // no encryption 21980 keyBag = ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 21981 // bagId 21982 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 21983 ASN1.oidToDer(PKI.oids.keyBag).getBytes()), 21984 // bagValue 21985 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 21986 // PrivateKeyInfo 21987 pkAsn1 21988 ]), 21989 // bagAttributes (OPTIONAL) 21990 bagAttrs 21991 ]); 21992 } else { 21993 // encrypted PrivateKeyInfo 21994 keyBag = ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 21995 // bagId 21996 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 21997 ASN1.oidToDer(PKI.oids.pkcs8ShroudedKeyBag).getBytes()), 21998 // bagValue 21999 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 22000 // EncryptedPrivateKeyInfo 22001 PKI.encryptPrivateKeyInfo(pkAsn1, password, options) 22002 ]), 22003 // bagAttributes (OPTIONAL) 22004 keyAttrs 22005 ]); 22006 } 22007 22008 // SafeContents 22009 var keySafeContents = 22010 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [keyBag]); 22011 22012 // ContentInfo 22013 var keyCI = 22014 // PKCS#7 ContentInfo 22015 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22016 // contentType 22017 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 22018 // OID for the content type is 'data' 22019 ASN1.oidToDer(PKI.oids.data).getBytes()), 22020 // content 22021 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 22022 ASN1.create( 22023 ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 22024 ASN1.toDer(keySafeContents).getBytes()) 22025 ]) 22026 ]); 22027 contents.push(keyCI); 22028 } 22029 22030 // create safe bag(s) for certificate chain 22031 var chain = []; 22032 if(cert !== null) { 22033 if(UTIL.isArray(cert)) { 22034 chain = cert; 22035 } else { 22036 chain = [cert]; 22037 } 22038 } 22039 22040 var certSafeBags = []; 22041 for(var i = 0; i < chain.length; ++i) { 22042 // convert cert from PEM as necessary 22043 cert = chain[i]; 22044 if(typeof cert === 'string') { 22045 cert = PKI.certificateFromPem(cert); 22046 } 22047 22048 // SafeBag 22049 var certBagAttrs = (i === 0) ? certAttrs : undefined; 22050 var certAsn1 = PKI.certificateToAsn1(cert); 22051 var certSafeBag = 22052 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22053 // bagId 22054 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 22055 ASN1.oidToDer(PKI.oids.certBag).getBytes()), 22056 // bagValue 22057 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 22058 // CertBag 22059 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22060 // certId 22061 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 22062 ASN1.oidToDer(PKI.oids.x509Certificate).getBytes()), 22063 // certValue (x509Certificate) 22064 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 22065 ASN1.create( 22066 ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 22067 ASN1.toDer(certAsn1).getBytes()) 22068 ])])]), 22069 // bagAttributes (OPTIONAL) 22070 certBagAttrs 22071 ]); 22072 certSafeBags.push(certSafeBag); 22073 } 22074
22075 if(certSafeBags.length > 0) { 22076 22077 // SafeContents 22078 var certSafeContents = ASN1.create( 22079 ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, certSafeBags); 22080 22081 var certBag = C(certSafeContents, password, options); 22082 22083 // ContentInfo 22084 var certCI = 22085 // PKCS#7 ContentInfo 22086 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22087 // contentType 22088 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 22089 ASN1.oidToDer(PKI.oids.encryptedData).getBytes()), 22090 // content 22091 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 22092 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22093 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.INTEGER, false, ASN1.integerToDer(0).getBytes()), 22094 certBag]) 22095 ]) 22096 ]); 22097 contents.push(certCI); 22098 } 22099 22100 // create AuthenticatedSafe by stringing together the contents 22101 var safe = ASN1.create( 22102 ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, contents); 22103 22104 var macData; 22105 if(options.useMac) { 22106 // MacData 22107 var sha1 = MD.sha1.create(); 22108 var macSalt = new UTIL.ByteBuffer( 22109 RANDOM.getBytes(options.saltSize)); 22110 var count = options.count; 22111 // 160-bit key 22112 var key = PKCS12.generateKey(password, macSalt, 3, count, 20); 22113 var mac = HMAC.create(); 22114 mac.start(sha1, key); 22115 mac.update(ASN1.toDer(safe).getBytes()); 22116 var macValue = mac.getMac(); 22117 macData = ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22118 // mac DigestInfo 22119 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22120 // digestAlgorithm 22121 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22122 // algorithm = SHA-1 22123 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 22124 ASN1.oidToDer(PKI.oids.sha1).getBytes()), 22125 // parameters = Null 22126 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.NULL, false, '') 22127 ]), 22128 // digest 22129 ASN1.create( 22130 ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, 22131 false, macValue.getBytes()) 22132 ]), 22133 // macSalt OCTET STRING 22134 ASN1.create( 22135 ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, macSalt.getBytes()), 22136 // iterations INTEGER (XXX: Only support count < 65536) 22137 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.INTEGER, false, 22138 ASN1.integerToDer(count).getBytes() 22139 ) 22140 ]); 22141 } 22142 22143 // PFX 22144 return ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22145 // version (3) 22146 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.INTEGER, false, 22147 ASN1.integerToDer(3).getBytes()), 22148 // PKCS#7 ContentInfo 22149 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 22150 // contentType 22151 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 22152 // OID for the content type is 'data' 22153 ASN1.oidToDer(PKI.oids.data).getBytes()), 22154 // content 22155 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 22156 ASN1.create( 22157 ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 22158 ASN1.toDer(safe).getBytes()) 22159 ]) 22160 ]), 22161 macData 22162 ]); 22163}; 22164 22165CGJSCrypt.ComposePKCS12 = function(prikey,prikeypwd,cert,pfxpwd,iflags) { 22166 var privateKey = D(prikey,prikeypwd); 22167 var newPkcs12Asn1 = P(privateKey, [cert], pfxpwd, {algorithm:'3des'}); 22168 return ASN1.toDer(newPkcs12Asn1).getBytes(); 22169} 22170 22171CGJSCrypt.GenerateKeyPair = function(keyLength, prikeypwd) { 22172 var keypair = PKI.rsa.generateKeyPair(keyLength); 22173 22174 CGJSCrypt.privateKey = E(keypair.privateKey, prikeypwd); 22175 CGJSCrypt.publicKey = PKI.publicKeyToRSAPublicKeyPem(keypair.publicKey); 22176} 22177 22178CGJSCrypt.CreatePKCS10 = function(keyLength, prikeypwd, hashalgo, strSubject, attrs, callbackFun) { 22179 22180 if (typeof callbackFun === 'function') { 22181 if(location.protocol != 'https:') 22182 forge.disableNativeCode=true; 22183 PKI.rsa.generateKeyPair( {bits: keyLength, workerScript: "../cgjscrypt/prime.worker.js"}, function(err, keypair) { 22184 CGJSCrypt.privateKey = E(keypair.privateKey, prikeypwd); //PKI.encryptRsaPrivateKey(keypair.privateKey, prikeypwd, {algorithm:prikeyencalgo,legacy:'1'}); 22185 CGJSCrypt.publicKey = PKI.publicKeyToRSAPublicKeyPem(keypair.publicKey); 22186 var csr = PKI.createCertificationRequest(); 22187 csr.publicKey = keypair.publicKey; 22188 22189 if(strSubject) { 22190 var a = strSubject.split(","); 22191 var subject = new Array(a.length); 22192 for(var i=0;i<a.length;i++) { 22193 var b = a[i].split("="); 22194 subject[i] = {shortName: b[0],value: b[1]}; 22195 } 22196 csr.setSubject(subject); 22197 } 22198 if(attrs) csr.setAttributes(attrs); 22199 22200 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 22201 22202 var md = MD[hashalgo].create(); 22203 csr.sign(keypair.privateKey,md); 22204 callbackFun(PKI.certificationRequestToPem(csr)); 22205 22206 }); 22207 } 22208 22209 else{ 22210 var keypair = PKI.rsa.generateKeyPair(keyLength); 22211 CGJSCrypt.privateKey = E(keypair.privateKey, prikeypwd); //PKI.encryptRsaPrivateKey(keypair.privateKey, prikeypwd, {algorithm:prikeyencalgo,legacy:'1'}); 22212 CGJSCrypt.publicKey = PKI.publicKeyToRSAPublicKeyPem(keypair.publicKey); 22213 22214 var csr = PKI.createCertificationRequest(); 22215 csr.publicKey = keypair.publicKey; 22216 22217 if(strSubject) { 22218 var a = strSubject.split(","); 22219 var subject = new Array(a.length); 22220 for(var i=0;i<a.length;i++) { 22221 var b = a[i].split("="); 22222 subject[i] = {shortName: b[0],value: b[1]}; 22223 } 22224 csr.setSubject(subject); 22225 } 22226 if(attrs) csr.setAttributes(attrs); 22227 22228 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 22229 22230 var md = MD[hashalgo].create(); 22231 csr.sign(keypair.privateKey,md); 22232 22233 return PKI.certificationRequestToPem(csr); 22234 } 22235 22236} 22237 22238CGJSCrypt.PrivateDecrypt = function(prikey,prikeypwd,cipher) { 22239 var privateKey = D(prikey,prikeypwd); 22240 return privateKey.decrypt(UTIL.decode64(cipher)); 22241} 22242 22243/* 22244CGJSCrypt.PrivateSign = function(prikey,prikeypwd,data,encoding,hashalgo) { 22245 if( (typeof hashalgo === "undefined") ) 22246 return PrivateSign2(prikey,prikeypwd,data,encoding); 22247 22248 try{ 22249 R(); 22250 var privateKey = D(prikey,prikeypwd); 22251 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 22252 var md = MD[hashalgo].create(); 22253 md.update(data, encoding); 22254 var signature = privateKey.sign(md); 22255 return UTIL.encode64(signature); 22256 }catch(e){ 22257 ErrorMsg=e.message; 22258 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22259 } 22260 return ""; 22261} 22262*/ 22263 22264CGJSCrypt.PrivateSign = function(prikey,prikeypwd,data,encoding,hashalgo,ext1,ext2) { 22265 if( (typeof hashalgo === "undefined") ) 22266 return PrivateSign2(prikey,prikeypwd,data,encoding); 22267 else if( (typeof hashalgo === "function") ) 22268 return PrivateSign2(prikey,prikeypwd,data,encoding,hashalgo,ext1,ext2); 22269 22270 try{ 22271 R(); 22272 var privateKey = D(prikey,prikeypwd); 22273 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 22274 var md = MD[hashalgo].create(); 22275 md.update(data, encoding); 22276 var signature = privateKey.sign(md); 22277 return UTIL.encode64(signature); 22278 }catch(e){ 22279 ErrorMsg=e.message; 22280 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22281 } 22282 return ""; 22283} 22284 22285/* 22286CGJSCrypt.ComposePKCS7 = function(prikey,prikeypwd,cert,data,encoding,hashalgo) { 22287 if( (typeof encoding === "undefined") || (typeof hashalgo === "undefined") ) 22288 return ComposePKCS72(prikey,prikeypwd,cert,data); 22289 22290 try{ 22291 var pem_privatekey = D(prikey,prikeypwd); 22292 var oidhash = PKI.oids.sha1; 22293 22294 if(!hashalgo || hashalgo=="") 22295 oidhash = PKI.oids.sha1; 22296 else{ 22297 switch (hashalgo) { 22298 case "sha1": 22299 oidhash = PKI.oids.sha1; 22300 break; 22301 case "sha256": 22302 oidhash = PKI.oids.sha256; 22303 break; 22304 case "md5": 22305 oidhash = PKI.oids.md5; 22306 break; 22307 default: 22308 oidhash = PKI.oids.sha1; 22309 } 22310 22311 } 22312 22313 var p7 = PKCS7.createSignedData(); 22314 p7.content = UTIL.createBuffer(data, encoding); 22315 p7.addCertificate(cert); 22316 p7.addSigner({ 22317 key: pem_privatekey, 22318 certificate: cert, 22319 digestAlgorithm: oidhash 22320 }); 22321 p7.sign(); 22322 22323 var p7pem = PKCS7.messageToPem(p7); 22324 22325 return p7pem.substring(p7pem.indexOf("\r\n")+2, p7pem.indexOf("-----END")); 22326 }catch(e){ 22327 ErrorMsg=e.message; 22328 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22329 } 22330 return ""; 22331} 22332*/ 22333 22334CGJSCrypt.ComposePKCS7 = function(prikey,prikeypwd,cert,data,encoding,hashalgo,ext1) { 22335 22336 if( (typeof encoding === "undefined") ) 22337 return ComposePKCS72(prikey,prikeypwd,cert,data); 22338 else if( (typeof encoding === "function") ) 22339 return ComposePKCS72(prikey,prikeypwd,cert,data,encoding,hashalgo,ext1); 22340 22341 try{ 22342 var pem_privatekey = D(prikey,prikeypwd); 22343 var oidhash = PKI.oids.sha1; 22344 22345 if(!hashalgo || hashalgo=="") 22346 oidhash = PKI.oids.sha1; 22347 else{ 22348 switch (hashalgo) { 22349 case "sha1": 22350 oidhash = PKI.oids.sha1; 22351 break; 22352 case "sha256": 22353 oidhash = PKI.oids.sha256; 22354 break; 22355 case "md5": 22356 oidhash = PKI.oids.md5; 22357 break; 22358 default: 22359 oidhash = PKI.oids.sha1; 22360 } 22361 22362 } 22363 22364 var p7 = PKCS7.createSignedData(); 22365 p7.content = UTIL.createBuffer(data, encoding); 22366 p7.addCertificate(cert); 22367 p7.addSigner({ 22368 key: pem_privatekey, 22369 certificate: cert, 22370 digestAlgorithm: oidhash 22371 }); 22372 p7.sign(); 22373 22374 var p7pem = PKCS7.messageToPem(p7); 22375 22376 return p7pem.substring(p7pem.indexOf("\r\n")+2, p7pem.indexOf("-----END")); 22377 }catch(e){ 22378 ErrorMsg=e.message; 22379 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22380 } 22381 return ""; 22382} 22383 22384 22385CGJSCrypt.EncodeBase64 = function(data) { 22386 try{ 22387 return UTIL.encode64(data); 22388 }catch(e){ErrorMsg=e.message;ErrorCode=5005;} 22389 return ""; 22390} 22391 22392CGJSCrypt.DecodeBase64 = function(data) { 22393 try{ 22394 return UTIL.decode64(data); 22395 }catch(e){ErrorMsg=e.message;ErrorCode=5005;} 22396 return ""; 22397} 22398 22399CGJSCrypt.SavePrivatekey = function(privateKey,cn,pid){ 22400 ErrorCode = -1; 22401 22402 if(privateKey == null || privateKey.length <= 0){ 22403 ErrorCode = 5005; 22404 } 22405 else{ 22406 if(typeof(Storage) !== "undefined") { 22407 if(typeof cn === "undefined" || cn===null) 22408 localStorage.setItem("Prikey_"+Company+"_"+pid, UTIL.encode64(privateKey)); 22409 else 22410 localStorage.setItem("Prikey_"+Company+"_"+pid, UTIL.encode64(privateKey) + ">_<" + cn); 22411 22412 ErrorCode = 0; 22413 } 22414 else 22415 ErrorCode = 5002; 22416 } 22417 //return ErrorCode; 22418} 22419 22420CGJSCrypt.SavePublickey = function(publicKey,pid){ 22421 ErrorCode = -1; 22422 22423 if(publicKey == null || publicKey.length <= 0){ 22424 ErrorCode = 5005; 22425 } 22426 else{ 22427 if(typeof(Storage) !== "undefined") { 22428 22429 localStorage.setItem("Pubkey_"+Company+"_"+pid, publicKey); 22430 ErrorCode = 0; 22431 } 22432 else 22433 ErrorCode = 5002; 22434 } 22435 //return ErrorCode; 22436} 22437 22438CGJSCrypt.DeleteWebstorage = function(pid){ 22439 ErrorCode = -1; 22440
22441 if(typeof(Storage) !== "undefined") { 22442 if(localStorage.getItem("Prikey_"+Company+"_"+pid)) 22443 localStorage.removeItem("Prikey_"+Company+"_"+pid); 22444 if(localStorage.getItem("Pubkey_"+Company+"_"+pid)) 22445 localStorage.removeItem("Pubkey_"+Company+"_"+pid); 22446 if(localStorage.getItem("Cert_"+Company+"_"+pid)) 22447 localStorage.removeItem("Cert_"+Company+"_"+pid); 22448 ErrorCode = 0; 22449 } 22450 else 22451 ErrorCode = 5002; 22452 22453 //return ErrorCode; 22454 22455} 22456 22457CGJSCrypt.ImportCert = function(cert,pid){ 22458 ErrorCode = -1; 22459 22460 if(cert == null || cert.length <= 0){ 22461 ErrorCode = 5005; 22462 } 22463 else{ 22464 22465 var index = cert.indexOf("-----BEGIN CERTIFICATE-----"); 22466 if(index == -1) 22467 { 22468 cert = "-----BEGIN CERTIFICATE-----\r\n"+cert.replace(/ /g,'')+"\r\n-----END CERTIFICATE-----"; 22469 } 22470 22471 if(typeof(Storage) !== "undefined") { 22472 localStorage.setItem("Cert_"+Company+"_"+pid, cert); 22473 ErrorCode = 0; 22474 } 22475 else 22476 ErrorCode = 5002; 22477 } 22478 //return ErrorCode; 22479} 22480 22481CGJSCrypt.GetCert = function(pid){ 22482 ErrorCode = -1; 22483 var certValue = ""; 22484 if(typeof(Storage) !== "undefined") { 22485 var cert = localStorage.getItem("Cert_"+Company+"_"+pid); 22486 if(cert == null) 22487 ErrorCode = 5003; 22488 else 22489 { 22490 certValue = cert; 22491 ErrorCode = 0; 22492 } 22493 } 22494 else 22495 ErrorCode = 5002; 22496 22497 return certValue; 22498 22499 //return ErrorCode; 22500} 22501 22502CGJSCrypt.GetPublicKey = function(pid){ 22503 ErrorCode = -1; 22504 var pubValue = ""; 22505 if(typeof(Storage) !== "undefined") { 22506 var pub = localStorage.getItem("Pubkey_"+Company+"_"+pid); 22507 if(pub == null) 22508 ErrorCode = 5003; 22509 else 22510 { 22511 pubValue = pub; 22512 ErrorCode = 0; 22513 } 22514 } 22515 else 22516 ErrorCode = 5002; 22517 22518 return pubValue; 22519 22520 //return ErrorCode; 22521} 22522 22523CGJSCrypt.GetPrivateKey = function(pid){ 22524 ErrorCode = -1; 22525 var priValue = ""; 22526 if(typeof(Storage) !== "undefined") { 22527 var pri = localStorage.getItem("Prikey_"+Company+"_"+pid); 22528 if(pri == null) 22529 ErrorCode = 5003; 22530 else 22531 { 22532 var valuecount = pri.indexOf(">_<"); 22533 if(valuecount > -1) { 22534 priValue = UTIL.decode64(pri.substring(0, valuecount)); 22535 } 22536 else { 22537 priValue = UTIL.decode64(pri); 22538 } 22539 ErrorCode = 0; 22540 } 22541 } 22542 else 22543 ErrorCode = 5002; 22544 22545 return priValue; 22546 22547 //return ErrorCode; 22548} 22549 22550CGJSCrypt.GetCN = function(pid){ 22551 ErrorCode = -1; 22552 var cnValue = ""; 22553 if(typeof(Storage) !== "undefined") { 22554 var cn = localStorage.getItem("Prikey_"+Company+"_"+pid); 22555 if(cn == null) 22556 ErrorCode = 5003; 22557 else 22558 { 22559 var valuecount = cn.indexOf(">_<"); 22560 if(valuecount > -1) { 22561 cnValue = cn.substring(valuecount+3); 22562 ErrorCode = 0; 22563 } 22564 else { 22565 ErrorCode = 5003; 22566 } 22567 22568 } 22569 } 22570 else 22571 ErrorCode = 5002; 22572 22573 return cnValue; 22574 22575 //return ErrorCode; 22576} 22577 22578/* 22579function PrivateSign2(data,encoding,hashalgo,pid) { 22580 try{ 22581 var prikey = CGJSCrypt.GetPrivateKey(pid); 22582 if(ErrorCode != 0) 22583 return ""; 22584 var prikeypwd = DecodePrikeyPass(pid); 22585 if(ErrorCode != 0) 22586 { 22587 var pass = prompt("???????"); 22588 if (pass == null) { 22589 return ""; 22590 } 22591 22592 prikeypwd = pass; 22593 } 22594 R(); 22595 var privateKey = D(prikey,prikeypwd); 22596 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 22597 var md = MD[hashalgo].create(); 22598 md.update(data, encoding); 22599 var signature = privateKey.sign(md); 22600 22601 if(typeof(pass) !== "undefined") 22602 SavePriKeyPass(pass,pid); 22603 22604 if(ErrorCode != 0) 22605 { 22606 ErrorMsg == "Unable to store password"; 22607 return ""; 22608 } 22609 return UTIL.encode64(signature); 22610 }catch(e){ 22611 ErrorMsg=e.message; 22612 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22613 } 22614 return ""; 22615} 22616*/ 22617 22618CGJSCrypt.PromptComputeCallback = function(pass){}; 22619CGJSCrypt.PromptCancelCallback = function() { 22620 CGJSCrypt.PromptComputeCallback = function(pass){}; 22621} 22622 22623function PrivateSign2(data,encoding,hashalgo,pid,open_modal_func,success_func,fail_func) { 22624 var usemodal = (typeof(open_modal_func) === "function"); 22625 22626 try{ 22627 var prikey = CGJSCrypt.GetPrivateKey(pid); 22628 if(ErrorCode != 0) 22629 return ""; 22630 var prikeypwd = DecodePrikeyPass(pid); 22631 if(ErrorCode != 0) 22632 { 22633 if(!usemodal) { 22634 var pass = prompt("???????"); 22635 if (pass == null) { 22636 return ""; 22637 } 22638 22639 prikeypwd = pass; 22640 } else { 22641 var f_openmodal = open_modal_func; 22642 var f_success = (typeof(success_func) === "function") ? success_func : function(result){}; 22643 var f_fail = (typeof(fail_func) === "function") ? fail_func : function(errorCode){}; 22644 22645 CGJSCrypt.PromptComputeCallback = function(pass){ 22646 //alert("prikey: " + prikey + ", pass: " + pass); 22647 if (pass == null || typeof pass === "undefined") { 22648 CGJSCrypt.PromptComputeCallback = function(pass){}; 22649 return; 22650 } 22651 22652 try { 22653 prikeypwd = pass; 22654 22655 R(); 22656 var privateKey = D(prikey,prikeypwd); 22657 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 22658 var md = MD[hashalgo].create(); 22659 md.update(data, encoding); 22660 var signature = privateKey.sign(md); 22661 22662 if(typeof(pass) !== "undefined") 22663 SavePriKeyPass(pass,pid); 22664 22665 if(ErrorCode != 0) 22666 { 22667 ErrorMsg == "Unable to store password"; 22668 CGJSCrypt.PromptComputeCallback = function(pass){}; 22669 f_fail(ErrorCode); 22670 return; 22671 } 22672 CGJSCrypt.PromptComputeCallback = function(pass){}; 22673 f_success(UTIL.encode64(signature)); 22674 }catch(e){ 22675 ErrorMsg=e.message; 22676 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22677 CGJSCrypt.PromptComputeCallback = function(pass){}; 22678 f_fail(ErrorCode); 22679 } 22680 } 22681 22682 f_openmodal(); 22683 22684 return "USE_MODAL"; 22685 } 22686 } 22687 R(); 22688 var privateKey = D(prikey,prikeypwd); 22689 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 22690 var md = MD[hashalgo].create(); 22691 md.update(data, encoding); 22692 var signature = privateKey.sign(md); 22693 22694 if(typeof(pass) !== "undefined") 22695 SavePriKeyPass(pass,pid); 22696 22697 if(ErrorCode != 0) 22698 { 22699 ErrorMsg == "Unable to store password"; 22700 return ""; 22701 } 22702 return UTIL.encode64(signature); 22703 }catch(e){ 22704 ErrorMsg=e.message; 22705 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22706 } 22707 return ""; 22708} 22709 22710/* 22711function ComposePKCS72(data,encoding,hashalgo,pid) { 22712 try{ 22713 var cert = CGJSCrypt.GetCert(pid); 22714 if(ErrorCode != 0) 22715 return ""; 22716 var prikey = CGJSCrypt.GetPrivateKey(pid); 22717 if(ErrorCode != 0) 22718 return ""; 22719 var prikeypwd = DecodePrikeyPass(pid); 22720 if(ErrorCode != 0) 22721 { 22722 var pass = prompt("???????"); 22723 if (pass == null) { 22724 return ""; 22725 } 22726 22727 prikeypwd = pass; 22728 } 22729 22730 var pem_privatekey = D(prikey,prikeypwd); 22731 var oidhash = PKI.oids.sha1; 22732 22733 if(!hashalgo || hashalgo=="") 22734 oidhash = PKI.oids.sha1; 22735 else{ 22736 switch (hashalgo) { 22737 case "sha1": 22738 oidhash = PKI.oids.sha1; 22739 break; 22740 case "sha256": 22741 oidhash = PKI.oids.sha256; 22742 break; 22743 case "md5": 22744 oidhash = PKI.oids.md5; 22745 break; 22746 default: 22747 oidhash = PKI.oids.sha1; 22748 } 22749 22750 } 22751 22752 var p7 = PKCS7.createSignedData(); 22753 p7.content = UTIL.createBuffer(data, encoding); 22754 p7.addCertificate(cert); 22755 p7.addSigner({ 22756 key: pem_privatekey, 22757 certificate: cert, 22758 digestAlgorithm: oidhash 22759 }); 22760 p7.sign(); 22761 22762 var p7pem = PKCS7.messageToPem(p7); 22763 22764 if(typeof(pass) !== "undefined") 22765 SavePriKeyPass(pass,pid); 22766 22767 if(ErrorCode != 0) 22768 { 22769 ErrorMsg == "Unable to store password"; 22770 return ""; 22771 } 22772 22773 return p7pem.substring(p7pem.indexOf("\r\n")+2, p7pem.indexOf("-----END")); 22774 }catch(e){ 22775 ErrorMsg=e.message; 22776 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22777 } 22778 return ""; 22779} 22780*/ 22781 22782function ComposePKCS72(data,encoding,hashalgo,pid,open_modal_func,success_func,fail_func) { 22783 var usemodal = (typeof(open_modal_func) === "function"); 22784 22785 try{ 22786 var cert = CGJSCrypt.GetCert(pid); 22787 if(ErrorCode != 0) 22788 return ""; 22789 var prikey = CGJSCrypt.GetPrivateKey(pid); 22790 if(ErrorCode != 0) 22791 return ""; 22792 var prikeypwd = DecodePrikeyPass(pid); 22793 if(ErrorCode != 0) 22794 { 22795 if(!usemodal) { 22796 var pass = prompt("???????"); 22797 if (pass == null) { 22798 return ""; 22799 } 22800 22801 prikeypwd = pass; 22802 } else { 22803 var f_openmodal = open_modal_func; 22804 var f_success = (typeof(success_func) === "function") ? success_func : function(result){}; 22805 var f_fail = (typeof(fail_func) === "function") ? fail_func : function(errorCode){}; 22806 22807 CGJSCrypt.PromptComputeCallback = function(pass){ 22808 //alert("cert: " + cert + ", prikey: " + prikey + ", pass: " + pass); 22809 if (pass == null || typeof pass === "undefined") { 22810 CGJSCrypt.PromptComputeCallback = function(pass){}; 22811 return; 22812 } 22813 22814 try { 22815 prikeypwd = pass; 22816 22817 var pem_privatekey = D(prikey,prikeypwd); 22818 var oidhash = PKI.oids.sha1; 22819 22820 if(!hashalgo || hashalgo=="") 22821 oidhash = PKI.oids.sha1; 22822 else{ 22823 switch (hashalgo) { 22824 case "sha1": 22825 oidhash = PKI.oids.sha1; 22826 break; 22827 case "sha256": 22828 oidhash = PKI.oids.sha256; 22829 break; 22830 case "md5": 22831 oidhash = PKI.oids.md5; 22832 break; 22833 default: 22834 oidhash = PKI.oids.sha1; 22835 } 22836 22837 } 22838 22839 var p7 = PKCS7.createSignedData(); 22840 p7.content = UTIL.createBuffer(data, encoding); 22841 p7.addCertificate(cert); 22842 p7.addSigner({ 22843 key: pem_privatekey, 22844 certificate: cert, 22845 digestAlgorithm: oidhash 22846 }); 22847 p7.sign(); 22848 22849 var p7pem = PKCS7.messageToPem(p7); 22850 22851 if(typeof(pass) !== "undefined") 22852 SavePriKeyPass(pass,pid); 22853 22854 if(ErrorCode != 0) 22855 { 22856 ErrorMsg == "Unable to store password"; 22857 CGJSCrypt.PromptComputeCallback = function(pass){}; 22858 f_fail(ErrorCode); 22859 return; 22860 } 22861 22862 CGJSCrypt.PromptComputeCallback = function(pass){}; 22863 f_success(p7pem.substring(p7pem.indexOf("\r\n")+2, p7pem.indexOf("-----END"))); 22864 }catch(e){ 22865 ErrorMsg=e.message; 22866 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22867 CGJSCrypt.PromptComputeCallback = function(pass){}; 22868 f_fail(ErrorCode); 22869 } 22870 } 22871 22872 f_openmodal(); 22873 22874 return "USE_MODAL"; 22875 } 22876 } 22877 22878 var pem_privatekey = D(prikey,prikeypwd); 22879 var oidhash = PKI.oids.sha1; 22880 22881 if(!hashalgo || hashalgo=="") 22882 oidhash = PKI.oids.sha1; 22883 else{ 22884 switch (hashalgo) { 22885 case "sha1": 22886 oidhash = PKI.oids.sha1; 22887 break; 22888 case "sha256": 22889 oidhash = PKI.oids.sha256; 22890 break; 22891 case "md5": 22892 oidhash = PKI.oids.md5; 22893 break; 22894 default: 22895 oidhash = PKI.oids.sha1; 22896 } 22897 22898 } 22899 22900 var p7 = PKCS7.createSignedData(); 22901 p7.content = UTIL.createBuffer(data, encoding); 22902 p7.addCertificate(cert); 22903 p7.addSigner({ 22904 key: pem_privatekey, 22905 certificate: cert, 22906 digestAlgorithm: oidhash 22907 }); 22908 p7.sign(); 22909 22910 var p7pem = PKCS7.messageToPem(p7); 22911 22912 if(typeof(pass) !== "undefined") 22913 SavePriKeyPass(pass,pid); 22914 22915 if(ErrorCode != 0) 22916 { 22917 ErrorMsg == "Unable to store password"; 22918 return ""; 22919 } 22920 22921 return p7pem.substring(p7pem.indexOf("\r\n")+2, p7pem.indexOf("-----END")); 22922 }catch(e){ 22923 ErrorMsg=e.message; 22924 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 22925 } 22926 return ""; 22927} 22928 22929 22930function SavePriKeyPass(prikeypwd,pid){ 22931 ErrorCode=0; 22932 var encryptedpwd = null; 22933 22934 if(typeof(Storage) !== "undefined") { 22935 var d = new Date(); 22936 var data_str = ""; 22937 data_str = d.getFullYear().toString(); 22938 data_str = ((d.getMonth()+1) < 10)?data_str.concat("0",d.getMonth()+1):data_str.concat(d.getMonth()+1); 22939 data_str = ((d.getDate()) < 10)?data_str.concat("0",d.getDate()):data_str.concat(d.getDate()); 22940 22941 var it = 1500; 22942 22943 var salt = RANDOM.getBytes(50); 22944 var dk = PBKDF2(data_str,salt,it,48); 22945 22946 var k = dk.substring(0,32); 22947 var iv = dk.substring(32,48); 22948 var input = UTIL.createBuffer(prikeypwd); 22949 22950 var c = AES.createEncryptionCipher(k, 'CBC'); 22951 c.start(iv); 22952 c.update(input); 22953 c.finish(); 22954 22955 encryptedpwd = UTIL.encode64(UTIL.hexToBytes(c.output.toHex()+UTIL.bytesToHex(salt)+it.toString())); 22956 22957 sessionStorage.setItem("PrikeyPass_"+Company+"_"+pid, encryptedpwd); 22958 22959 } 22960 else 22961 ErrorCode=5002; 22962} 22963 22964function DecodePrikeyPass(pid) 22965{ 22966 ErrorCode=0; 22967 var encryptdata = null; 22968 var t=""; 22969 22970 if(typeof(Storage) !== "undefined") { 22971 encryptdata = sessionStorage.getItem("PrikeyPass_"+Company+"_"+pid); 22972 if(encryptdata != null) 22973 { 22974 encryptdata = UTIL.decode64(encryptdata); 22975 var salt = encryptdata.substring(encryptdata.length-50-2,encryptdata.length-2); 22976 var m = encryptdata.substring(0,(encryptdata.length-salt.length-2)); 22977 var it = parseInt(UTIL.bytesToHex(encryptdata.substring(encryptdata.length-2))); 22978 22979 //alert(UTIL.bytesToHex(encryptdata.substring(encryptdata.length-2))); 22980 //ALL.SaltB.value=UTIL.bytesToHex(salt); 22981 //ALL.SaltB.value=ALL.SaltB.value+=it; 22982 22983 var d = new Date(); 22984 var data_str = ""; 22985 data_str = d.getFullYear().toString(); 22986 data_str = ((d.getMonth()+1) < 10)?data_str.concat("0",d.getMonth()+1):data_str.concat(d.getMonth()+1); 22987 data_str = ((d.getDate()) < 10)?data_str.concat("0",d.getDate()):data_str.concat(d.getDate()); 22988 22989 22990 var dk = PBKDF2(data_str,salt,it,48); 22991 22992 var k = dk.substring(0,32); 22993 var iv = dk.substring(32,48); 22994 var input = UTIL.createBuffer(m); 22995 22996 var c = AES.createDecryptionCipher(k, 'CBC'); 22997 c.start(iv); 22998 c.update(input); 22999 if(!c.finish()) 23000 ErrorCode = 5003; 23001 //throw new Error('Unable to decrypt PrivateKeypass'); 23002 else 23003 { 23004 t = c.output; 23005 } 23006 } 23007 else 23008 { 23009 ErrorCode=5003; 23010 } 23011 } 23012 else 23013 ErrorCode=5002; 23014 23015 return t; 23016} 23017 23018CGJSCrypt.ChangeCertPass = function(oldpass,newpass,pid) { 23019 ErrorCode=0; 23020 var cn = CGJSCrypt.GetCN(pid); 23021 var prikey = CGJSCrypt.GetPrivateKey(pid); 23022 23023 try{ 23024 R(); 23025 var o_prikey = D(prikey,oldpass); 23026 23027 var newprikey = E(o_prikey, newpass); 23028 23029 CGJSCrypt.SavePrivatekey(newprikey,cn,pid); 23030 23031 return true; 23032 23033 }catch(e){ 23034 ErrorMsg=e.message; 23035 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 23036 } 23037 23038 return false;
23039} 23040 23041 23042CGJSCrypt.CheckCert = function(pid){ 23043 23044 var cert = CGJSCrypt.GetCert(pid); 23045 if(CGJSCrypt.GetErrorCode()!=0){ 23046 23047 return 5010; 23048 }else{ 23049 var arr = CGJSCrypt.CertGetNotAfter(cert).split(/[- :]/); 23050 var noafter = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]); 23051 var today = new Date(); 23052 if(today<noafter){ 23053 return 0; 23054 }else{ 23055 CGJSCrypt.DeleteWebstorage(pid); 23056 23057 return 5010; 23058 } 23059 } 23060 23061} 23062 23063CGJSCrypt.GetPublicFromCert = function(pem_cert,iflags) { 23064 var index = pem_cert.indexOf("-----BEGIN CERTIFICATE-----"); 23065 if(index == -1) 23066 { 23067 pem_cert = "-----BEGIN CERTIFICATE-----\r\n"+pem_cert+"\r\n-----END CERTIFICATE-----"; 23068 } 23069 var publicKey = PKI.certificateFromPem(pem_cert).publicKey; 23070 23071 publicKey = PKI.publicKeyToRSAPublicKeyPem(publicKey); 23072 23073 return publicKey; 23074} 23075 23076CGJSCrypt.CertPassCheck = function(oldpass,prikey) { 23077 ErrorCode=0; 23078 23079 try{ 23080 R(); 23081 var o_prikey = D(prikey,oldpass); 23082 23083 return (o_prikey != null); 23084 23085 }catch(e){ 23086 ErrorMsg=e.message; 23087 (ErrorMsg == "Unable to decrypt PrivateKey, wrong password?")?ErrorCode=5003:ErrorCode=5005; 23088 } 23089 23090 return false; 23091} 23092 23093 23094p7addRH = function(msg,strPuKey){ 23095 msg.recipients.push({ 23096 version: 2, 23097 subjectKeyIdentifier: PKI.getPublicKeyFingerprint(strPuKey,{type: 'SubjectPublicKeyInfo', encoding: 'binary'}), 23098 encryptedContent: { 23099 // We simply assume rsaEncryption here, since forge.pki only 23100 // supports RSA so far. If the PKI module supports other 23101 // ciphers one day, we need to modify this one as well. 23102 algorithm: forge.pki.oids.rsaEncryption, 23103 key: strPuKey 23104 } 23105 }); 23106 return msg; 23107} 23108 23109CGJSCrypt.PKCS7PublicEncrypt = function(strPuKey,data,iFlags){ 23110 var p7 = PKCS7.createEnvelopedData(); 23111 p7.content = UTIL.createBuffer(data, "utf8"); 23112 var publickey = PKI.publicKeyFromPem(strPuKey); 23113 p7 = p7addRH(p7,publickey); 23114// p7.addRecipient2(publickey); 23115 p7.encrypt(); 23116 var p7pem = p7MtoP(p7); 23117 return p7pem.substring(p7pem.indexOf("\r\n")+2, p7pem.indexOf("-----END")); 23118} 23119 23120CGJSCrypt.PKCS7Encrypt = function(pem_cert,data,iFlags){ 23121 var p7 = PKCS7.createEnvelopedData(); 23122 p7.content = UTIL.createBuffer(data, "utf8"); 23123 var cert = PKI.certificateFromPem(pem_cert); 23124 p7.addRecipient(cert); 23125 p7.encrypt(); 23126 var p7pem = PKCS7.messageToPem(p7); 23127 return p7pem.substring(p7pem.indexOf("\r\n")+2, p7pem.indexOf("-----END")); 23128} 23129 23130p7RtoA = function(obj) { 23131 return ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 23132 // Version 23133 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.INTEGER, false, 23134 ASN1.integerToDer(obj.version).getBytes()), 23135 // SubjectKeyIdentifier 23136 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, false, obj.subjectKeyIdentifier 23137 ), 23138 // KeyEncryptionAlgorithmIdentifier 23139 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 23140 // Algorithm 23141 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 23142 ASN1.oidToDer(obj.encryptedContent.algorithm).getBytes()), 23143 // Parameter, force NULL, only RSA supported for now. 23144 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.NULL, false, '') 23145 ]), 23146 // EncryptedKey 23147 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 23148 obj.encryptedContent.content) 23149 ]); 23150 } 23151 23152p7MtoP = function(msg, maxline) { 23153 // convert to ASN.1, then DER, then PEM-encode 23154 var pemObj = { 23155 type: 'PKCS7', 23156 body: ASN1.toDer(p7toA(msg)).getBytes() 23157 }; 23158 return forge.pem.encode(pemObj, {maxline: maxline}); 23159 } 23160 23161p7toA = function(msg) { 23162 // ContentInfo 23163 return ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 23164 // ContentType 23165 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false,ASN1.oidToDer(msg.type).getBytes()), 23166 // [0] EnvelopedData 23167 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 23168 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 23169 // Version 23170 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.INTEGER, false, ASN1.integerToDer(msg.version).getBytes()), 23171 // RecipientInfos 23172 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SET, true,p7RstoA(msg.recipients)), 23173 // EncryptedContentInfo 23174 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, 23175 _encryptedContentToAsn1(msg.encryptedContent)) 23176 ]) 23177 ]) 23178 ]); 23179 } 23180 23181p7RstoA = function(recipients) { 23182 var ret = []; 23183 for(var i = 0; i < recipients.length; ++i) { 23184 ret.push(p7RtoA(recipients[i])); 23185 } 23186 return ret; 23187} 23188 23189function _encryptedContentToAsn1(ec) { 23190 return [ 23191 // ContentType, always Data for the moment 23192 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 23193 ASN1.oidToDer(forge.pki.oids.data).getBytes()), 23194 // ContentEncryptionAlgorithmIdentifier 23195 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.SEQUENCE, true, [ 23196 // Algorithm 23197 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OID, false, 23198 ASN1.oidToDer(ec.algorithm).getBytes()), 23199 // Parameters (IV) 23200 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 23201 ec.parameter.getBytes()) 23202 ]), 23203 // [0] EncryptedContent 23204 ASN1.create(ASN1.Class.CONTEXT_SPECIFIC, 0, true, [ 23205 ASN1.create(ASN1.Class.UNIVERSAL, ASN1.Type.OCTETSTRING, false, 23206 ec.content.getBytes()) 23207 ]) 23208 ]; 23209} 23210 23211CGJSCrypt.Hash = function(data, encoding, hashalgo, iflags) { 23212 try { 23213 if(!hashalgo || hashalgo=="") hashalgo = 'sha1'; 23214 var md = MD[hashalgo].create(); 23215 md.update(data, encoding); 23216 var d = md.digest(); 23217 return d.toHex(); 23218 } catch(e) { 23219 ErrorMsg=e.message; 23220 ErrorCode=5005; 23221 } 23222 return ""; 23223}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.