1 /*! crypto-1.1.5.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * crypto.js - Cryptographic Algorithm Provider class 5 * 6 * Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * http://kjur.github.com/jsrsasign/license 10 * 11 * The above copyright and license notice shall be 12 * included in all copies or substantial portions of the Software. 13 */ 14 15 /** 16 * @fileOverview 17 * @name crypto-1.1.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version 1.1.5 (2013-Oct-06) 20 * @since jsrsasign 2.2 21 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a> 22 */ 23 24 /** 25 * kjur's class library name space 26 * @name KJUR 27 * @namespace kjur's class library name space 28 */ 29 if (typeof KJUR == "undefined" || !KJUR) KJUR = {}; 30 /** 31 * kjur's cryptographic algorithm provider library name space 32 * <p> 33 * This namespace privides following crytpgrahic classes. 34 * <ul> 35 * <li>{@link KJUR.crypto.MessageDigest} - Java JCE(cryptograhic extension) style MessageDigest class</li> 36 * <li>{@link KJUR.crypto.Signature} - Java JCE(cryptograhic extension) style Signature class</li> 37 * <li>{@link KJUR.crypto.Util} - cryptographic utility functions and properties</li> 38 * </ul> 39 * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2. 40 * </p> 41 * @name KJUR.crypto 42 * @namespace 43 */ 44 if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {}; 45 46 /** 47 * static object for cryptographic function utilities 48 * @name KJUR.crypto.Util 49 * @class static object for cryptographic function utilities 50 * @property {Array} DIGESTINFOHEAD PKCS#1 DigestInfo heading hexadecimal bytes for each hash algorithms 51 * @property {Array} DEFAULTPROVIDER associative array of default provider name for each hash and signature algorithms 52 * @description 53 */ 54 KJUR.crypto.Util = new function() { 55 this.DIGESTINFOHEAD = { 56 'sha1': "3021300906052b0e03021a05000414", 57 'sha224': "302d300d06096086480165030402040500041c", 58 'sha256': "3031300d060960864801650304020105000420", 59 'sha384': "3041300d060960864801650304020205000430", 60 'sha512': "3051300d060960864801650304020305000440", 61 'md2': "3020300c06082a864886f70d020205000410", 62 'md5': "3020300c06082a864886f70d020505000410", 63 'ripemd160': "3021300906052b2403020105000414", 64 }; 65 66 /* 67 * @since crypto 1.1.1 68 */ 69 this.DEFAULTPROVIDER = { 70 'md5': 'cryptojs', 71 'sha1': 'cryptojs', 72 'sha224': 'cryptojs', 73 'sha256': 'cryptojs', 74 'sha384': 'cryptojs', 75 'sha512': 'cryptojs', 76 'ripemd160': 'cryptojs', 77 'hmacmd5': 'cryptojs', 78 'hmacsha1': 'cryptojs', 79 'hmacsha224': 'cryptojs', 80 'hmacsha256': 'cryptojs', 81 'hmacsha384': 'cryptojs', 82 'hmacsha512': 'cryptojs', 83 'hmacripemd160': 'cryptojs', 84 85 'MD5withRSA': 'cryptojs/jsrsa', 86 'SHA1withRSA': 'cryptojs/jsrsa', 87 'SHA224withRSA': 'cryptojs/jsrsa', 88 'SHA256withRSA': 'cryptojs/jsrsa', 89 'SHA384withRSA': 'cryptojs/jsrsa', 90 'SHA512withRSA': 'cryptojs/jsrsa', 91 'RIPEMD160withRSA': 'cryptojs/jsrsa', 92 93 'MD5withECDSA': 'cryptojs/jsrsa', 94 'SHA1withECDSA': 'cryptojs/jsrsa', 95 'SHA224withECDSA': 'cryptojs/jsrsa', 96 'SHA256withECDSA': 'cryptojs/jsrsa', 97 'SHA384withECDSA': 'cryptojs/jsrsa', 98 'SHA512withECDSA': 'cryptojs/jsrsa', 99 'RIPEMD160withECDSA': 'cryptojs/jsrsa', 100 101 'SHA1withDSA': 'cryptojs/jsrsa', 102 'SHA224withDSA': 'cryptojs/jsrsa', 103 'SHA256withDSA': 'cryptojs/jsrsa', 104 105 'MD5withRSAandMGF1': 'cryptojs/jsrsa', 106 'SHA1withRSAandMGF1': 'cryptojs/jsrsa', 107 'SHA224withRSAandMGF1': 'cryptojs/jsrsa', 108 'SHA256withRSAandMGF1': 'cryptojs/jsrsa', 109 'SHA384withRSAandMGF1': 'cryptojs/jsrsa', 110 'SHA512withRSAandMGF1': 'cryptojs/jsrsa', 111 'RIPEMD160withRSAandMGF1': 'cryptojs/jsrsa', 112 }; 113 114 /* 115 * @since crypto 1.1.2 116 */ 117 this.CRYPTOJSMESSAGEDIGESTNAME = { 118 'md5': 'CryptoJS.algo.MD5', 119 'sha1': 'CryptoJS.algo.SHA1', 120 'sha224': 'CryptoJS.algo.SHA224', 121 'sha256': 'CryptoJS.algo.SHA256', 122 'sha384': 'CryptoJS.algo.SHA384', 123 'sha512': 'CryptoJS.algo.SHA512', 124 'ripemd160': 'CryptoJS.algo.RIPEMD160' 125 }; 126 127 /** 128 * get hexadecimal DigestInfo 129 * @name getDigestInfoHex 130 * @memberOf KJUR.crypto.Util 131 * @function 132 * @param {String} hHash hexadecimal hash value 133 * @param {String} alg hash algorithm name (ex. 'sha1') 134 * @return {String} hexadecimal string DigestInfo ASN.1 structure 135 */ 136 this.getDigestInfoHex = function(hHash, alg) { 137 if (typeof this.DIGESTINFOHEAD[alg] == "undefined") 138 throw "alg not supported in Util.DIGESTINFOHEAD: " + alg; 139 return this.DIGESTINFOHEAD[alg] + hHash; 140 }; 141 142 /** 143 * get PKCS#1 padded hexadecimal DigestInfo 144 * @name getPaddedDigestInfoHex 145 * @memberOf KJUR.crypto.Util 146 * @function 147 * @param {String} hHash hexadecimal hash value of message to be signed 148 * @param {String} alg hash algorithm name (ex. 'sha1') 149 * @param {Integer} keySize key bit length (ex. 1024) 150 * @return {String} hexadecimal string of PKCS#1 padded DigestInfo 151 */ 152 this.getPaddedDigestInfoHex = function(hHash, alg, keySize) { 153 var hDigestInfo = this.getDigestInfoHex(hHash, alg); 154 var pmStrLen = keySize / 4; // minimum PM length 155 156 if (hDigestInfo.length + 22 > pmStrLen) // len(0001+ff(*8)+00+hDigestInfo)=22 157 throw "key is too short for SigAlg: keylen=" + keySize + "," + alg; 158 159 var hHead = "0001"; 160 var hTail = "00" + hDigestInfo; 161 var hMid = ""; 162 var fLen = pmStrLen - hHead.length - hTail.length; 163 for (var i = 0; i < fLen; i += 2) { 164 hMid += "ff"; 165 } 166 var hPaddedMessage = hHead + hMid + hTail; 167 return hPaddedMessage; 168 }; 169 170 /** 171 * get hexadecimal hash of string with specified algorithm 172 * @name hashString 173 * @memberOf KJUR.crypto.Util 174 * @function 175 * @param {String} s input string to be hashed 176 * @param {String} alg hash algorithm name 177 * @return {String} hexadecimal string of hash value 178 * @since 1.1.1 179 */ 180 this.hashString = function(s, alg) { 181 var md = new KJUR.crypto.MessageDigest({'alg': alg}); 182 return md.digestString(s); 183 }; 184 185 /** 186 * get hexadecimal hash of hexadecimal string with specified algorithm 187 * @name hashHex 188 * @memberOf KJUR.crypto.Util 189 * @function 190 * @param {String} sHex input hexadecimal string to be hashed 191 * @param {String} alg hash algorithm name 192 * @return {String} hexadecimal string of hash value 193 * @since 1.1.1 194 */ 195 this.hashHex = function(sHex, alg) { 196 var md = new KJUR.crypto.MessageDigest({'alg': alg}); 197 return md.digestHex(sHex); 198 }; 199 200 /** 201 * get hexadecimal SHA1 hash of string 202 * @name sha1 203 * @memberOf KJUR.crypto.Util 204 * @function 205 * @param {String} s input string to be hashed 206 * @return {String} hexadecimal string of hash value 207 * @since 1.0.3 208 */ 209 this.sha1 = function(s) { 210 var md = new KJUR.crypto.MessageDigest({'alg':'sha1', 'prov':'cryptojs'}); 211 return md.digestString(s); 212 }; 213 214 /** 215 * get hexadecimal SHA256 hash of string 216 * @name sha256 217 * @memberOf KJUR.crypto.Util 218 * @function 219 * @param {String} s input string to be hashed 220 * @return {String} hexadecimal string of hash value 221 * @since 1.0.3 222 */ 223 this.sha256 = function(s) { 224 var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'}); 225 return md.digestString(s); 226 }; 227 228 this.sha256Hex = function(s) { 229 var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'}); 230 return md.digestHex(s); 231 }; 232 233 /** 234 * get hexadecimal SHA512 hash of string 235 * @name sha512 236 * @memberOf KJUR.crypto.Util 237 * @function 238 * @param {String} s input string to be hashed 239 * @return {String} hexadecimal string of hash value 240 * @since 1.0.3 241 */ 242 this.sha512 = function(s) { 243 var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'}); 244 return md.digestString(s); 245 }; 246 247 this.sha512Hex = function(s) { 248 var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'}); 249 return md.digestHex(s); 250 }; 251 252 /** 253 * get hexadecimal MD5 hash of string 254 * @name md5 255 * @memberOf KJUR.crypto.Util 256 * @function 257 * @param {String} s input string to be hashed 258 * @return {String} hexadecimal string of hash value 259 * @since 1.0.3 260 */ 261 this.md5 = function(s) { 262 var md = new KJUR.crypto.MessageDigest({'alg':'md5', 'prov':'cryptojs'}); 263 return md.digestString(s); 264 }; 265 266 /** 267 * get hexadecimal RIPEMD160 hash of string 268 * @name ripemd160 269 * @memberOf KJUR.crypto.Util 270 * @function 271 * @param {String} s input string to be hashed 272 * @return {String} hexadecimal string of hash value 273 * @since 1.0.3 274 */ 275 this.ripemd160 = function(s) { 276 var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'}); 277 return md.digestString(s); 278 }; 279 280 /* 281 * @since 1.1.2 282 */ 283 this.getCryptoJSMDByName = function(s) { 284 285 }; 286 }; 287 288 /** 289 * MessageDigest class which is very similar to java.security.MessageDigest class 290 * @name KJUR.crypto.MessageDigest 291 * @class MessageDigest class which is very similar to java.security.MessageDigest class 292 * @param {Array} params parameters for constructor 293 * @description 294 * <br/> 295 * Currently this supports following algorithm and providers combination: 296 * <ul> 297 * <li>md5 - cryptojs</li> 298 * <li>sha1 - cryptojs</li> 299 * <li>sha224 - cryptojs</li> 300 * <li>sha256 - cryptojs</li> 301 * <li>sha384 - cryptojs</li> 302 * <li>sha512 - cryptojs</li> 303 * <li>ripemd160 - cryptojs</li> 304 * <li>sha256 - sjcl (NEW from crypto.js 1.0.4)</li> 305 * </ul> 306 * @example 307 * // CryptoJS provider sample 308 * <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/core.js"></script> 309 * <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/sha1.js"></script> 310 * <script src="crypto-1.0.js"></script> 311 * var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"}); 312 * md.updateString('aaa') 313 * var mdHex = md.digest() 314 * 315 * // SJCL(Stanford JavaScript Crypto Library) provider sample 316 * <script src="http://bitwiseshiftleft.github.io/sjcl/sjcl.js"></script> 317 * <script src="crypto-1.0.js"></script> 318 * var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only 319 * md.updateString('aaa') 320 * var mdHex = md.digest() 321 */ 322 KJUR.crypto.MessageDigest = function(params) { 323 var md = null; 324 var algName = null; 325 var provName = null; 326 327 /** 328 * set hash algorithm and provider 329 * @name setAlgAndProvider 330 * @memberOf KJUR.crypto.MessageDigest 331 * @function 332 * @param {String} alg hash algorithm name 333 * @param {String} prov provider name 334 * @description 335 * @example 336 * // for SHA1 337 * md.setAlgAndProvider('sha1', 'cryptojs'); 338 * // for RIPEMD160 339 * md.setAlgAndProvider('ripemd160', 'cryptojs'); 340 */ 341 this.setAlgAndProvider = function(alg, prov) { 342 if (alg != null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg]; 343 344 // for cryptojs 345 if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 && 346 prov == 'cryptojs') { 347 try { 348 this.md = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[alg]).create(); 349 } catch (ex) { 350 throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex; 351 } 352 this.updateString = function(str) { 353 this.md.update(str); 354 }; 355 this.updateHex = function(hex) { 356 var wHex = CryptoJS.enc.Hex.parse(hex); 357 this.md.update(wHex); 358 }; 359 this.digest = function() { 360 var hash = this.md.finalize(); 361 return hash.toString(CryptoJS.enc.Hex); 362 }; 363 this.digestString = function(str) { 364 this.updateString(str); 365 return this.digest(); 366 }; 367 this.digestHex = function(hex) { 368 this.updateHex(hex); 369 return this.digest(); 370 }; 371 } 372 if (':sha256:'.indexOf(alg) != -1 && 373 prov == 'sjcl') { 374 try { 375 this.md = new sjcl.hash.sha256(); 376 } catch (ex) { 377 throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex; 378 } 379 this.updateString = function(str) { 380 this.md.update(str); 381 }; 382 this.updateHex = function(hex) { 383 var baHex = sjcl.codec.hex.toBits(hex); 384 this.md.update(baHex); 385 }; 386 this.digest = function() { 387 var hash = this.md.finalize(); 388 return sjcl.codec.hex.fromBits(hash); 389 }; 390 this.digestString = function(str) { 391 this.updateString(str); 392 return this.digest(); 393 }; 394 this.digestHex = function(hex) { 395 this.updateHex(hex); 396 return this.digest(); 397 }; 398 } 399 }; 400 401 /** 402 * update digest by specified string 403 * @name updateString 404 * @memberOf KJUR.crypto.MessageDigest 405 * @function 406 * @param {String} str string to update 407 * @description 408 * @example 409 * md.updateString('New York'); 410 */ 411 this.updateString = function(str) { 412 throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName; 413 }; 414 415 /** 416 * update digest by specified hexadecimal string 417 * @name updateHex 418 * @memberOf KJUR.crypto.MessageDigest 419 * @function 420 * @param {String} hex hexadecimal string to update 421 * @description 422 * @example 423 * md.updateHex('0afe36'); 424 */ 425 this.updateHex = function(hex) { 426 throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName; 427 }; 428 429 /** 430 * completes hash calculation and returns hash result 431 * @name digest 432 * @memberOf KJUR.crypto.MessageDigest 433 * @function 434 * @description 435 * @example 436 * md.digest() 437 */ 438 this.digest = function() { 439 throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName; 440 }; 441 442 /** 443 * performs final update on the digest using string, then completes the digest computation 444 * @name digestString 445 * @memberOf KJUR.crypto.MessageDigest 446 * @function 447 * @param {String} str string to final update 448 * @description 449 * @example 450 * md.digestString('aaa') 451 */ 452 this.digestString = function(str) { 453 throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName; 454 }; 455 456 /** 457 * performs final update on the digest using hexadecimal string, then completes the digest computation 458 * @name digestHex 459 * @memberOf KJUR.crypto.MessageDigest 460 * @function 461 * @param {String} hex hexadecimal string to final update 462 * @description 463 * @example 464 * md.digestHex('0f2abd') 465 */ 466 this.digestHex = function(hex) { 467 throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName; 468 }; 469 470 if (params !== undefined) { 471 if (params['alg'] !== undefined) { 472 this.algName = params['alg']; 473 if (params['prov'] === undefined) 474 this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]; 475 this.setAlgAndProvider(this.algName, this.provName); 476 } 477 } 478 }; 479 480 /** 481 * Mac(Message Authentication Code) class which is very similar to java.security.Mac class 482 * @name KJUR.crypto.Mac 483 * @class Mac class which is very similar to java.security.Mac class 484 * @param {Array} params parameters for constructor 485 * @description 486 * <br/> 487 * Currently this supports following algorithm and providers combination: 488 * <ul> 489 * <li>hmacmd5 - cryptojs</li> 490 * <li>hmacsha1 - cryptojs</li> 491 * <li>hmacsha224 - cryptojs</li> 492 * <li>hmacsha256 - cryptojs</li> 493 * <li>hmacsha384 - cryptojs</li> 494 * <li>hmacsha512 - cryptojs</li> 495 * </ul> 496 * NOTE: HmacSHA224 and HmacSHA384 issue was fixed since jsrsasign 4.1.4. 497 * Please use 'ext/cryptojs-312-core-fix*.js' instead of 'core.js' of original CryptoJS 498 * to avoid those issue. 499 * @example 500 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", prov: "cryptojs", "pass": "pass"}); 501 * mac.updateString('aaa') 502 * var macHex = md.doFinal() 503 */ 504 KJUR.crypto.Mac = function(params) { 505 var mac = null; 506 var pass = null; 507 var algName = null; 508 var provName = null; 509 var algProv = null; 510 511 this.setAlgAndProvider = function(alg, prov) { 512 if (alg == null) alg = "hmacsha1"; 513 514 alg = alg.toLowerCase(); 515 if (alg.substr(0, 4) != "hmac") { 516 throw "setAlgAndProvider unsupported HMAC alg: " + alg; 517 } 518 519 if (prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg]; 520 this.algProv = alg + "/" + prov; 521 522 var hashAlg = alg.substr(4); 523 524 // for cryptojs 525 if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(hashAlg) != -1 && 526 prov == 'cryptojs') { 527 try { 528 var mdObj = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[hashAlg]); 529 this.mac = CryptoJS.algo.HMAC.create(mdObj, this.pass); 530 } catch (ex) { 531 throw "setAlgAndProvider hash alg set fail hashAlg=" + hashAlg + "/" + ex; 532 } 533 this.updateString = function(str) { 534 this.mac.update(str); 535 }; 536 this.updateHex = function(hex) { 537 var wHex = CryptoJS.enc.Hex.parse(hex); 538 this.mac.update(wHex); 539 }; 540 this.doFinal = function() { 541 var hash = this.mac.finalize(); 542 return hash.toString(CryptoJS.enc.Hex); 543 }; 544 this.doFinalString = function(str) { 545 this.updateString(str); 546 return this.doFinal(); 547 }; 548 this.doFinalHex = function(hex) { 549 this.updateHex(hex); 550 return this.doFinal(); 551 }; 552 } 553 }; 554 555 /** 556 * update digest by specified string 557 * @name updateString 558 * @memberOf KJUR.crypto.Mac 559 * @function 560 * @param {String} str string to update 561 * @description 562 * @example 563 * md.updateString('New York'); 564 */ 565 this.updateString = function(str) { 566 throw "updateString(str) not supported for this alg/prov: " + this.algProv; 567 }; 568 569 /** 570 * update digest by specified hexadecimal string 571 * @name updateHex 572 * @memberOf KJUR.crypto.Mac 573 * @function 574 * @param {String} hex hexadecimal string to update 575 * @description 576 * @example 577 * md.updateHex('0afe36'); 578 */ 579 this.updateHex = function(hex) { 580 throw "updateHex(hex) not supported for this alg/prov: " + this.algProv; 581 }; 582 583 /** 584 * completes hash calculation and returns hash result 585 * @name doFinal 586 * @memberOf KJUR.crypto.Mac 587 * @function 588 * @description 589 * @example 590 * md.digest() 591 */ 592 this.doFinal = function() { 593 throw "digest() not supported for this alg/prov: " + this.algProv; 594 }; 595 596 /** 597 * performs final update on the digest using string, then completes the digest computation 598 * @name doFinalString 599 * @memberOf KJUR.crypto.Mac 600 * @function 601 * @param {String} str string to final update 602 * @description 603 * @example 604 * md.digestString('aaa') 605 */ 606 this.doFinalString = function(str) { 607 throw "digestString(str) not supported for this alg/prov: " + this.algProv; 608 }; 609 610 /** 611 * performs final update on the digest using hexadecimal string, 612 * then completes the digest computation 613 * @name doFinalHex 614 * @memberOf KJUR.crypto.Mac 615 * @function 616 * @param {String} hex hexadecimal string to final update 617 * @description 618 * @example 619 * md.digestHex('0f2abd') 620 */ 621 this.doFinalHex = function(hex) { 622 throw "digestHex(hex) not supported for this alg/prov: " + this.algProv; 623 }; 624 625 if (params !== undefined) { 626 if (params['pass'] !== undefined) { 627 this.pass = params['pass']; 628 } 629 if (params['alg'] !== undefined) { 630 this.algName = params['alg']; 631 if (params['prov'] === undefined) 632 this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]; 633 this.setAlgAndProvider(this.algName, this.provName); 634 } 635 } 636 }; 637 638 /** 639 * Signature class which is very similar to java.security.Signature class 640 * @name KJUR.crypto.Signature 641 * @class Signature class which is very similar to java.security.Signature class 642 * @param {Array} params parameters for constructor 643 * @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null 644 * @description 645 * <br/> 646 * As for params of constructor's argument, it can be specify following attributes: 647 * <ul> 648 * <li>alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}with{RSA,ECDSA,DSA})</li> 649 * <li>provider - currently 'cryptojs/jsrsa' only</li> 650 * </ul> 651 * <h4>SUPPORTED ALGORITHMS AND PROVIDERS</h4> 652 * This Signature class supports following signature algorithm and provider names: 653 * <ul> 654 * <li>MD5withRSA - cryptojs/jsrsa</li> 655 * <li>SHA1withRSA - cryptojs/jsrsa</li> 656 * <li>SHA224withRSA - cryptojs/jsrsa</li> 657 * <li>SHA256withRSA - cryptojs/jsrsa</li> 658 * <li>SHA384withRSA - cryptojs/jsrsa</li> 659 * <li>SHA512withRSA - cryptojs/jsrsa</li> 660 * <li>RIPEMD160withRSA - cryptojs/jsrsa</li> 661 * <li>MD5withECDSA - cryptojs/jsrsa</li> 662 * <li>SHA1withECDSA - cryptojs/jsrsa</li> 663 * <li>SHA224withECDSA - cryptojs/jsrsa</li> 664 * <li>SHA256withECDSA - cryptojs/jsrsa</li> 665 * <li>SHA384withECDSA - cryptojs/jsrsa</li> 666 * <li>SHA512withECDSA - cryptojs/jsrsa</li> 667 * <li>RIPEMD160withECDSA - cryptojs/jsrsa</li> 668 * <li>MD5withRSAandMGF1 - cryptojs/jsrsa</li> 669 * <li>SHA1withRSAandMGF1 - cryptojs/jsrsa</li> 670 * <li>SHA224withRSAandMGF1 - cryptojs/jsrsa</li> 671 * <li>SHA256withRSAandMGF1 - cryptojs/jsrsa</li> 672 * <li>SHA384withRSAandMGF1 - cryptojs/jsrsa</li> 673 * <li>SHA512withRSAandMGF1 - cryptojs/jsrsa</li> 674 * <li>RIPEMD160withRSAandMGF1 - cryptojs/jsrsa</li> 675 * <li>SHA1withDSA - cryptojs/jsrsa</li> 676 * <li>SHA224withDSA - cryptojs/jsrsa</li> 677 * <li>SHA256withDSA - cryptojs/jsrsa</li> 678 * </ul> 679 * Here are supported elliptic cryptographic curve names and their aliases for ECDSA: 680 * <ul> 681 * <li>secp256k1</li> 682 * <li>secp256r1, NIST P-256, P-256, prime256v1</li> 683 * <li>secp384r1, NIST P-384, P-384</li> 684 * </ul> 685 * NOTE1: DSA signing algorithm is also supported since crypto 1.1.5. 686 * <h4>EXAMPLES</h4> 687 * @example 688 * // RSA signature generation 689 * var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"}); 690 * sig.init(prvKeyPEM); 691 * sig.updateString('aaa'); 692 * var hSigVal = sig.sign(); 693 * 694 * // DSA signature validation 695 * var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"}); 696 * sig2.init(certPEM); 697 * sig.updateString('aaa'); 698 * var isValid = sig2.verify(hSigVal); 699 * 700 * // ECDSA signing 701 * var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'}); 702 * sig.init(prvKeyPEM); 703 * sig.updateString('aaa'); 704 * var sigValueHex = sig.sign(); 705 * 706 * // ECDSA verifying 707 * var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'}); 708 * sig.init(certPEM); 709 * sig.updateString('aaa'); 710 * var isValid = sig.verify(sigValueHex); 711 */ 712 KJUR.crypto.Signature = function(params) { 713 var prvKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for signing 714 var pubKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for verifying 715 716 var md = null; // KJUR.crypto.MessageDigest object 717 var sig = null; 718 var algName = null; 719 var provName = null; 720 var algProvName = null; 721 var mdAlgName = null; 722 var pubkeyAlgName = null; // rsa,ecdsa,rsaandmgf1(=rsapss) 723 var state = null; 724 var pssSaltLen = -1; 725 var initParams = null; 726 727 var sHashHex = null; // hex hash value for hex 728 var hDigestInfo = null; 729 var hPaddedDigestInfo = null; 730 var hSign = null; 731 732 this._setAlgNames = function() { 733 if (this.algName.match(/^(.+)with(.+)$/)) { 734 this.mdAlgName = RegExp.$1.toLowerCase(); 735 this.pubkeyAlgName = RegExp.$2.toLowerCase(); 736 } 737 }; 738 739 this._zeroPaddingOfSignature = function(hex, bitLength) { 740 var s = ""; 741 var nZero = bitLength / 4 - hex.length; 742 for (var i = 0; i < nZero; i++) { 743 s = s + "0"; 744 } 745 return s + hex; 746 }; 747 748 /** 749 * set signature algorithm and provider 750 * @name setAlgAndProvider 751 * @memberOf KJUR.crypto.Signature 752 * @function 753 * @param {String} alg signature algorithm name 754 * @param {String} prov provider name 755 * @description 756 * @example 757 * md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa'); 758 */ 759 this.setAlgAndProvider = function(alg, prov) { 760 this._setAlgNames(); 761 if (prov != 'cryptojs/jsrsa') 762 throw "provider not supported: " + prov; 763 764 if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) { 765 try { 766 this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName}); 767 } catch (ex) { 768 throw "setAlgAndProvider hash alg set fail alg=" + 769 this.mdAlgName + "/" + ex; 770 } 771 772 this.init = function(keyparam, pass) { 773 var keyObj = null; 774 try { 775 if (pass === undefined) { 776 keyObj = KEYUTIL.getKey(keyparam); 777 } else { 778 keyObj = KEYUTIL.getKey(keyparam, pass); 779 } 780 } catch (ex) { 781 throw "init failed:" + ex; 782 } 783 784 if (keyObj.isPrivate === true) { 785 this.prvKey = keyObj; 786 this.state = "SIGN"; 787 } else if (keyObj.isPublic === true) { 788 this.pubKey = keyObj; 789 this.state = "VERIFY"; 790 } else { 791 throw "init failed.:" + keyObj; 792 } 793 }; 794 795 this.initSign = function(params) { 796 if (typeof params['ecprvhex'] == 'string' && 797 typeof params['eccurvename'] == 'string') { 798 this.ecprvhex = params['ecprvhex']; 799 this.eccurvename = params['eccurvename']; 800 } else { 801 this.prvKey = params; 802 } 803 this.state = "SIGN"; 804 }; 805 806 this.initVerifyByPublicKey = function(params) { 807 if (typeof params['ecpubhex'] == 'string' && 808 typeof params['eccurvename'] == 'string') { 809 this.ecpubhex = params['ecpubhex']; 810 this.eccurvename = params['eccurvename']; 811 } else if (params instanceof KJUR.crypto.ECDSA) { 812 this.pubKey = params; 813 } else if (params instanceof RSAKey) { 814 this.pubKey = params; 815 } 816 this.state = "VERIFY"; 817 }; 818 819 this.initVerifyByCertificatePEM = function(certPEM) { 820 var x509 = new X509(); 821 x509.readCertPEM(certPEM); 822 this.pubKey = x509.subjectPublicKeyRSA; 823 this.state = "VERIFY"; 824 }; 825 826 this.updateString = function(str) { 827 this.md.updateString(str); 828 }; 829 this.updateHex = function(hex) { 830 this.md.updateHex(hex); 831 }; 832 833 this.sign = function() { 834 this.sHashHex = this.md.digest(); 835 if (typeof this.ecprvhex != "undefined" && 836 typeof this.eccurvename != "undefined") { 837 var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename}); 838 this.hSign = ec.signHex(this.sHashHex, this.ecprvhex); 839 } else if (this.pubkeyAlgName == "rsaandmgf1") { 840 this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex, 841 this.mdAlgName, 842 this.pssSaltLen); 843 } else if (this.pubkeyAlgName == "rsa") { 844 this.hSign = this.prvKey.signWithMessageHash(this.sHashHex, 845 this.mdAlgName); 846 } else if (this.prvKey instanceof KJUR.crypto.ECDSA) { 847 this.hSign = this.prvKey.signWithMessageHash(this.sHashHex); 848 } else if (this.prvKey instanceof KJUR.crypto.DSA) { 849 this.hSign = this.prvKey.signWithMessageHash(this.sHashHex); 850 } else { 851 throw "Signature: unsupported public key alg: " + this.pubkeyAlgName; 852 } 853 return this.hSign; 854 }; 855 this.signString = function(str) { 856 this.updateString(str); 857 return this.sign(); 858 }; 859 this.signHex = function(hex) { 860 this.updateHex(hex); 861 return this.sign(); 862 }; 863 this.verify = function(hSigVal) { 864 this.sHashHex = this.md.digest(); 865 if (typeof this.ecpubhex != "undefined" && 866 typeof this.eccurvename != "undefined") { 867 var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename}); 868 return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex); 869 } else if (this.pubkeyAlgName == "rsaandmgf1") { 870 return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal, 871 this.mdAlgName, 872 this.pssSaltLen); 873 } else if (this.pubkeyAlgName == "rsa") { 874 return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal); 875 } else if (this.pubKey instanceof KJUR.crypto.ECDSA) { 876 return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal); 877 } else if (this.pubKey instanceof KJUR.crypto.DSA) { 878 return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal); 879 } else { 880 throw "Signature: unsupported public key alg: " + this.pubkeyAlgName; 881 } 882 }; 883 } 884 }; 885 886 /** 887 * Initialize this object for signing or verifying depends on key 888 * @name init 889 * @memberOf KJUR.crypto.Signature 890 * @function 891 * @param {Object} key specifying public or private key as plain/encrypted PKCS#5/8 PEM file, certificate PEM or {@link RSAKey}, {@link KJUR.crypto.DSA} or {@link KJUR.crypto.ECDSA} object 892 * @param {String} pass (OPTION) passcode for encrypted private key 893 * @since crypto 1.1.3 894 * @description 895 * This method is very useful initialize method for Signature class since 896 * you just specify key then this method will automatically initialize it 897 * using {@link KEYUTIL.getKey} method. 898 * As for 'key', following argument type are supported: 899 * <h5>signing</h5> 900 * <ul> 901 * <li>PEM formatted PKCS#8 encrypted RSA/ECDSA private key concluding "BEGIN ENCRYPTED PRIVATE KEY"</li> 902 * <li>PEM formatted PKCS#5 encrypted RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" and ",ENCRYPTED"</li> 903 * <li>PEM formatted PKCS#8 plain RSA/ECDSA private key concluding "BEGIN PRIVATE KEY"</li> 904 * <li>PEM formatted PKCS#5 plain RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" without ",ENCRYPTED"</li> 905 * <li>RSAKey object of private key</li> 906 * <li>KJUR.crypto.ECDSA object of private key</li> 907 * <li>KJUR.crypto.DSA object of private key</li> 908 * </ul> 909 * <h5>verification</h5> 910 * <ul> 911 * <li>PEM formatted PKCS#8 RSA/EC/DSA public key concluding "BEGIN PUBLIC KEY"</li> 912 * <li>PEM formatted X.509 certificate with RSA/EC/DSA public key concluding 913 * "BEGIN CERTIFICATE", "BEGIN X509 CERTIFICATE" or "BEGIN TRUSTED CERTIFICATE".</li> 914 * <li>RSAKey object of public key</li> 915 * <li>KJUR.crypto.ECDSA object of public key</li> 916 * <li>KJUR.crypto.DSA object of public key</li> 917 * </ul> 918 * @example 919 * sig.init(sCertPEM) 920 */ 921 this.init = function(key, pass) { 922 throw "init(key, pass) not supported for this alg:prov=" + 923 this.algProvName; 924 }; 925 926 /** 927 * Initialize this object for verifying with a public key 928 * @name initVerifyByPublicKey 929 * @memberOf KJUR.crypto.Signature 930 * @function 931 * @param {Object} param RSAKey object of public key or associative array for ECDSA 932 * @since 1.0.2 933 * @deprecated from crypto 1.1.5. please use init() method instead. 934 * @description 935 * Public key information will be provided as 'param' parameter and the value will be 936 * following: 937 * <ul> 938 * <li>{@link RSAKey} object for RSA verification</li> 939 * <li>associative array for ECDSA verification 940 * (ex. <code>{'ecpubhex': '041f..', 'eccurvename': 'secp256r1'}</code>) 941 * </li> 942 * </ul> 943 * @example 944 * sig.initVerifyByPublicKey(rsaPrvKey) 945 */ 946 this.initVerifyByPublicKey = function(rsaPubKey) { 947 throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" + 948 this.algProvName; 949 }; 950 951 /** 952 * Initialize this object for verifying with a certficate 953 * @name initVerifyByCertificatePEM 954 * @memberOf KJUR.crypto.Signature 955 * @function 956 * @param {String} certPEM PEM formatted string of certificate 957 * @since 1.0.2 958 * @deprecated from crypto 1.1.5. please use init() method instead. 959 * @description 960 * @example 961 * sig.initVerifyByCertificatePEM(certPEM) 962 */ 963 this.initVerifyByCertificatePEM = function(certPEM) { 964 throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" + 965 this.algProvName; 966 }; 967 968 /** 969 * Initialize this object for signing 970 * @name initSign 971 * @memberOf KJUR.crypto.Signature 972 * @function 973 * @param {Object} param RSAKey object of public key or associative array for ECDSA 974 * @deprecated from crypto 1.1.5. please use init() method instead. 975 * @description 976 * Private key information will be provided as 'param' parameter and the value will be 977 * following: 978 * <ul> 979 * <li>{@link RSAKey} object for RSA signing</li> 980 * <li>associative array for ECDSA signing 981 * (ex. <code>{'ecprvhex': '1d3f..', 'eccurvename': 'secp256r1'}</code>)</li> 982 * </ul> 983 * @example 984 * sig.initSign(prvKey) 985 */ 986 this.initSign = function(prvKey) { 987 throw "initSign(prvKey) not supported for this alg:prov=" + this.algProvName; 988 }; 989 990 /** 991 * Updates the data to be signed or verified by a string 992 * @name updateString 993 * @memberOf KJUR.crypto.Signature 994 * @function 995 * @param {String} str string to use for the update 996 * @description 997 * @example 998 * sig.updateString('aaa') 999 */ 1000 this.updateString = function(str) { 1001 throw "updateString(str) not supported for this alg:prov=" + this.algProvName; 1002 }; 1003 1004 /** 1005 * Updates the data to be signed or verified by a hexadecimal string 1006 * @name updateHex 1007 * @memberOf KJUR.crypto.Signature 1008 * @function 1009 * @param {String} hex hexadecimal string to use for the update 1010 * @description 1011 * @example 1012 * sig.updateHex('1f2f3f') 1013 */ 1014 this.updateHex = function(hex) { 1015 throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName; 1016 }; 1017 1018 /** 1019 * Returns the signature bytes of all data updates as a hexadecimal string 1020 * @name sign 1021 * @memberOf KJUR.crypto.Signature 1022 * @function 1023 * @return the signature bytes as a hexadecimal string 1024 * @description 1025 * @example 1026 * var hSigValue = sig.sign() 1027 */ 1028 this.sign = function() { 1029 throw "sign() not supported for this alg:prov=" + this.algProvName; 1030 }; 1031 1032 /** 1033 * performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string 1034 * @name signString 1035 * @memberOf KJUR.crypto.Signature 1036 * @function 1037 * @param {String} str string to final update 1038 * @return the signature bytes of a hexadecimal string 1039 * @description 1040 * @example 1041 * var hSigValue = sig.signString('aaa') 1042 */ 1043 this.signString = function(str) { 1044 throw "digestString(str) not supported for this alg:prov=" + this.algProvName; 1045 }; 1046 1047 /** 1048 * performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string 1049 * @name signHex 1050 * @memberOf KJUR.crypto.Signature 1051 * @function 1052 * @param {String} hex hexadecimal string to final update 1053 * @return the signature bytes of a hexadecimal string 1054 * @description 1055 * @example 1056 * var hSigValue = sig.signHex('1fdc33') 1057 */ 1058 this.signHex = function(hex) { 1059 throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName; 1060 }; 1061 1062 /** 1063 * verifies the passed-in signature. 1064 * @name verify 1065 * @memberOf KJUR.crypto.Signature 1066 * @function 1067 * @param {String} str string to final update 1068 * @return {Boolean} true if the signature was verified, otherwise false 1069 * @description 1070 * @example 1071 * var isValid = sig.verify('1fbcefdca4823a7(snip)') 1072 */ 1073 this.verify = function(hSigVal) { 1074 throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName; 1075 }; 1076 1077 this.initParams = params; 1078 1079 if (params !== undefined) { 1080 if (params['alg'] !== undefined) { 1081 this.algName = params['alg']; 1082 if (params['prov'] === undefined) { 1083 this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]; 1084 } else { 1085 this.provName = params['prov']; 1086 } 1087 this.algProvName = this.algName + ":" + this.provName; 1088 this.setAlgAndProvider(this.algName, this.provName); 1089 this._setAlgNames(); 1090 } 1091 1092 if (params['psssaltlen'] !== undefined) this.pssSaltLen = params['psssaltlen']; 1093 1094 if (params['prvkeypem'] !== undefined) { 1095 if (params['prvkeypas'] !== undefined) { 1096 throw "both prvkeypem and prvkeypas parameters not supported"; 1097 } else { 1098 try { 1099 var prvKey = new RSAKey(); 1100 prvKey.readPrivateKeyFromPEMString(params['prvkeypem']); 1101 this.initSign(prvKey); 1102 } catch (ex) { 1103 throw "fatal error to load pem private key: " + ex; 1104 } 1105 } 1106 } 1107 } 1108 }; 1109 1110 /** 1111 * static object for cryptographic function utilities 1112 * @name KJUR.crypto.OID 1113 * @class static object for cryptography related OIDs 1114 * @property {Array} oidhex2name key value of hexadecimal OID and its name 1115 * (ex. '2a8648ce3d030107' and 'secp256r1') 1116 * @since crypto 1.1.3 1117 * @description 1118 */ 1119 1120 1121 KJUR.crypto.OID = new function() { 1122 this.oidhex2name = { 1123 '2a864886f70d010101': 'rsaEncryption', 1124 '2a8648ce3d0201': 'ecPublicKey', 1125 '2a8648ce380401': 'dsa', 1126 '2a8648ce3d030107': 'secp256r1', 1127 '2b8104001f': 'secp192k1', 1128 '2b81040021': 'secp224r1', 1129 '2b8104000a': 'secp256k1', 1130 '2b81040023': 'secp521r1', 1131 '2b81040022': 'secp384r1', 1132 '2a8648ce380403': 'SHA1withDSA', // 1.2.840.10040.4.3 1133 '608648016503040301': 'SHA224withDSA', // 2.16.840.1.101.3.4.3.1 1134 '608648016503040302': 'SHA256withDSA', // 2.16.840.1.101.3.4.3.2 1135 }; 1136 }; 1137