1 /*! crypto-1.1.12.js (c) 2013-2017 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * crypto.js - Cryptographic Algorithm Provider class 5 * 6 * Copyright (c) 2013-2017 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.12 (2017-Jan-31) 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.Cipher} - class for encrypting and decrypting data</li> 38 * <li>{@link KJUR.crypto.Util} - cryptographic utility functions and properties</li> 39 * </ul> 40 * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2. 41 * </p> 42 * @name KJUR.crypto 43 * @namespace 44 */ 45 if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {}; 46 47 /** 48 * static object for cryptographic function utilities 49 * @name KJUR.crypto.Util 50 * @class static object for cryptographic function utilities 51 * @property {Array} DIGESTINFOHEAD PKCS#1 DigestInfo heading hexadecimal bytes for each hash algorithms 52 * @property {Array} DEFAULTPROVIDER associative array of default provider name for each hash and signature algorithms 53 * @description 54 */ 55 KJUR.crypto.Util = new function() { 56 this.DIGESTINFOHEAD = { 57 'sha1': "3021300906052b0e03021a05000414", 58 'sha224': "302d300d06096086480165030402040500041c", 59 'sha256': "3031300d060960864801650304020105000420", 60 'sha384': "3041300d060960864801650304020205000430", 61 'sha512': "3051300d060960864801650304020305000440", 62 'md2': "3020300c06082a864886f70d020205000410", 63 'md5': "3020300c06082a864886f70d020505000410", 64 'ripemd160': "3021300906052b2403020105000414", 65 }; 66 67 /* 68 * @since crypto 1.1.1 69 */ 70 this.DEFAULTPROVIDER = { 71 'md5': 'cryptojs', 72 'sha1': 'cryptojs', 73 'sha224': 'cryptojs', 74 'sha256': 'cryptojs', 75 'sha384': 'cryptojs', 76 'sha512': 'cryptojs', 77 'ripemd160': 'cryptojs', 78 'hmacmd5': 'cryptojs', 79 'hmacsha1': 'cryptojs', 80 'hmacsha224': 'cryptojs', 81 'hmacsha256': 'cryptojs', 82 'hmacsha384': 'cryptojs', 83 'hmacsha512': 'cryptojs', 84 'hmacripemd160': 'cryptojs', 85 86 'MD5withRSA': 'cryptojs/jsrsa', 87 'SHA1withRSA': 'cryptojs/jsrsa', 88 'SHA224withRSA': 'cryptojs/jsrsa', 89 'SHA256withRSA': 'cryptojs/jsrsa', 90 'SHA384withRSA': 'cryptojs/jsrsa', 91 'SHA512withRSA': 'cryptojs/jsrsa', 92 'RIPEMD160withRSA': 'cryptojs/jsrsa', 93 94 'MD5withECDSA': 'cryptojs/jsrsa', 95 'SHA1withECDSA': 'cryptojs/jsrsa', 96 'SHA224withECDSA': 'cryptojs/jsrsa', 97 'SHA256withECDSA': 'cryptojs/jsrsa', 98 'SHA384withECDSA': 'cryptojs/jsrsa', 99 'SHA512withECDSA': 'cryptojs/jsrsa', 100 'RIPEMD160withECDSA': 'cryptojs/jsrsa', 101 102 'SHA1withDSA': 'cryptojs/jsrsa', 103 'SHA224withDSA': 'cryptojs/jsrsa', 104 'SHA256withDSA': 'cryptojs/jsrsa', 105 106 'MD5withRSAandMGF1': 'cryptojs/jsrsa', 107 'SHA1withRSAandMGF1': 'cryptojs/jsrsa', 108 'SHA224withRSAandMGF1': 'cryptojs/jsrsa', 109 'SHA256withRSAandMGF1': 'cryptojs/jsrsa', 110 'SHA384withRSAandMGF1': 'cryptojs/jsrsa', 111 'SHA512withRSAandMGF1': 'cryptojs/jsrsa', 112 'RIPEMD160withRSAandMGF1': 'cryptojs/jsrsa', 113 }; 114 115 /* 116 * @since crypto 1.1.2 117 */ 118 this.CRYPTOJSMESSAGEDIGESTNAME = { 119 'md5': CryptoJS.algo.MD5, 120 'sha1': CryptoJS.algo.SHA1, 121 'sha224': CryptoJS.algo.SHA224, 122 'sha256': CryptoJS.algo.SHA256, 123 'sha384': CryptoJS.algo.SHA384, 124 'sha512': CryptoJS.algo.SHA512, 125 'ripemd160': CryptoJS.algo.RIPEMD160 126 }; 127 128 /** 129 * get hexadecimal DigestInfo 130 * @name getDigestInfoHex 131 * @memberOf KJUR.crypto.Util 132 * @function 133 * @param {String} hHash hexadecimal hash value 134 * @param {String} alg hash algorithm name (ex. 'sha1') 135 * @return {String} hexadecimal string DigestInfo ASN.1 structure 136 */ 137 this.getDigestInfoHex = function(hHash, alg) { 138 if (typeof this.DIGESTINFOHEAD[alg] == "undefined") 139 throw "alg not supported in Util.DIGESTINFOHEAD: " + alg; 140 return this.DIGESTINFOHEAD[alg] + hHash; 141 }; 142 143 /** 144 * get PKCS#1 padded hexadecimal DigestInfo 145 * @name getPaddedDigestInfoHex 146 * @memberOf KJUR.crypto.Util 147 * @function 148 * @param {String} hHash hexadecimal hash value of message to be signed 149 * @param {String} alg hash algorithm name (ex. 'sha1') 150 * @param {Integer} keySize key bit length (ex. 1024) 151 * @return {String} hexadecimal string of PKCS#1 padded DigestInfo 152 */ 153 this.getPaddedDigestInfoHex = function(hHash, alg, keySize) { 154 var hDigestInfo = this.getDigestInfoHex(hHash, alg); 155 var pmStrLen = keySize / 4; // minimum PM length 156 157 if (hDigestInfo.length + 22 > pmStrLen) // len(0001+ff(*8)+00+hDigestInfo)=22 158 throw "key is too short for SigAlg: keylen=" + keySize + "," + alg; 159 160 var hHead = "0001"; 161 var hTail = "00" + hDigestInfo; 162 var hMid = ""; 163 var fLen = pmStrLen - hHead.length - hTail.length; 164 for (var i = 0; i < fLen; i += 2) { 165 hMid += "ff"; 166 } 167 var hPaddedMessage = hHead + hMid + hTail; 168 return hPaddedMessage; 169 }; 170 171 /** 172 * get hexadecimal hash of string with specified algorithm 173 * @name hashString 174 * @memberOf KJUR.crypto.Util 175 * @function 176 * @param {String} s input string to be hashed 177 * @param {String} alg hash algorithm name 178 * @return {String} hexadecimal string of hash value 179 * @since 1.1.1 180 */ 181 this.hashString = function(s, alg) { 182 var md = new KJUR.crypto.MessageDigest({'alg': alg}); 183 return md.digestString(s); 184 }; 185 186 /** 187 * get hexadecimal hash of hexadecimal string with specified algorithm 188 * @name hashHex 189 * @memberOf KJUR.crypto.Util 190 * @function 191 * @param {String} sHex input hexadecimal string to be hashed 192 * @param {String} alg hash algorithm name 193 * @return {String} hexadecimal string of hash value 194 * @since 1.1.1 195 */ 196 this.hashHex = function(sHex, alg) { 197 var md = new KJUR.crypto.MessageDigest({'alg': alg}); 198 return md.digestHex(sHex); 199 }; 200 201 /** 202 * get hexadecimal SHA1 hash of string 203 * @name sha1 204 * @memberOf KJUR.crypto.Util 205 * @function 206 * @param {String} s input string to be hashed 207 * @return {String} hexadecimal string of hash value 208 * @since 1.0.3 209 */ 210 this.sha1 = function(s) { 211 var md = new KJUR.crypto.MessageDigest({'alg':'sha1', 'prov':'cryptojs'}); 212 return md.digestString(s); 213 }; 214 215 /** 216 * get hexadecimal SHA256 hash of string 217 * @name sha256 218 * @memberOf KJUR.crypto.Util 219 * @function 220 * @param {String} s input string to be hashed 221 * @return {String} hexadecimal string of hash value 222 * @since 1.0.3 223 */ 224 this.sha256 = function(s) { 225 var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'}); 226 return md.digestString(s); 227 }; 228 229 this.sha256Hex = function(s) { 230 var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'}); 231 return md.digestHex(s); 232 }; 233 234 /** 235 * get hexadecimal SHA512 hash of string 236 * @name sha512 237 * @memberOf KJUR.crypto.Util 238 * @function 239 * @param {String} s input string to be hashed 240 * @return {String} hexadecimal string of hash value 241 * @since 1.0.3 242 */ 243 this.sha512 = function(s) { 244 var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'}); 245 return md.digestString(s); 246 }; 247 248 this.sha512Hex = function(s) { 249 var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'}); 250 return md.digestHex(s); 251 }; 252 253 }; 254 255 /** 256 * get hexadecimal MD5 hash of string 257 * @name md5 258 * @memberOf KJUR.crypto.Util 259 * @function 260 * @param {String} s input string to be hashed 261 * @return {String} hexadecimal string of hash value 262 * @since 1.0.3 263 * @example 264 * Util.md5('aaa') → 47bce5c74f589f4867dbd57e9ca9f808 265 */ 266 KJUR.crypto.Util.md5 = function(s) { 267 var md = new KJUR.crypto.MessageDigest({'alg':'md5', 'prov':'cryptojs'}); 268 return md.digestString(s); 269 }; 270 271 /** 272 * get hexadecimal RIPEMD160 hash of string 273 * @name ripemd160 274 * @memberOf KJUR.crypto.Util 275 * @function 276 * @param {String} s input string to be hashed 277 * @return {String} hexadecimal string of hash value 278 * @since 1.0.3 279 * @example 280 * KJUR.crypto.Util.ripemd160("aaa") → 08889bd7b151aa174c21f33f59147fa65381edea 281 */ 282 KJUR.crypto.Util.ripemd160 = function(s) { 283 var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'}); 284 return md.digestString(s); 285 }; 286 287 // @since jsrsasign 7.0.0 crypto 1.1.11 288 KJUR.crypto.Util.SECURERANDOMGEN = new SecureRandom(); 289 290 /** 291 * get hexadecimal string of random value from with specified byte length<br/> 292 * @name getRandomHexOfNbytes 293 * @memberOf KJUR.crypto.Util 294 * @function 295 * @param {Integer} n length of bytes of random 296 * @return {String} hexadecimal string of random 297 * @since jsrsasign 7.0.0 crypto 1.1.11 298 * @example 299 * KJUR.crypto.Util.getRandomHexOfNbytes(3) → "6314af", "000000" or "001fb4" 300 * KJUR.crypto.Util.getRandomHexOfNbytes(128) → "8fbc..." in 1024bits 301 */ 302 KJUR.crypto.Util.getRandomHexOfNbytes = function(n) { 303 var ba = new Array(n); 304 KJUR.crypto.Util.SECURERANDOMGEN.nextBytes(ba); 305 return BAtohex(ba); 306 }; 307 308 /** 309 * get BigInteger object of random value from with specified byte length<br/> 310 * @name getRandomBigIntegerOfNbytes 311 * @memberOf KJUR.crypto.Util 312 * @function 313 * @param {Integer} n length of bytes of random 314 * @return {BigInteger} BigInteger object of specified random value 315 * @since jsrsasign 7.0.0 crypto 1.1.11 316 * @example 317 * KJUR.crypto.Util.getRandomBigIntegerOfNbytes(3) → 6314af of BigInteger 318 * KJUR.crypto.Util.getRandomBigIntegerOfNbytes(128) → 8fbc... of BigInteger 319 */ 320 KJUR.crypto.Util.getRandomBigIntegerOfNbytes = function(n) { 321 return new BigInteger(KJUR.crypto.Util.getRandomHexOfNbytes(n), 16); 322 }; 323 324 /** 325 * get hexadecimal string of random value from with specified bit length<br/> 326 * @name getRandomHexOfNbits 327 * @memberOf KJUR.crypto.Util 328 * @function 329 * @param {Integer} n length of bits of random 330 * @return {String} hexadecimal string of random 331 * @since jsrsasign 7.0.0 crypto 1.1.11 332 * @example 333 * KJUR.crypto.Util.getRandomHexOfNbits(24) → "6314af", "000000" or "001fb4" 334 * KJUR.crypto.Util.getRandomHexOfNbits(1024) → "8fbc..." in 1024bits 335 */ 336 KJUR.crypto.Util.getRandomHexOfNbits = function(n) { 337 var n_remainder = n % 8; 338 var n_quotient = (n - n_remainder) / 8; 339 var ba = new Array(n_quotient + 1); 340 KJUR.crypto.Util.SECURERANDOMGEN.nextBytes(ba); 341 ba[0] = (((255 << n_remainder) & 255) ^ 255) & ba[0]; 342 return BAtohex(ba); 343 }; 344 345 /** 346 * get BigInteger object of random value from with specified bit length<br/> 347 * @name getRandomBigIntegerOfNbits 348 * @memberOf KJUR.crypto.Util 349 * @function 350 * @param {Integer} n length of bits of random 351 * @return {BigInteger} BigInteger object of specified random value 352 * @since jsrsasign 7.0.0 crypto 1.1.11 353 * @example 354 * KJUR.crypto.Util.getRandomBigIntegerOfNbits(24) → 6314af of BigInteger 355 * KJUR.crypto.Util.getRandomBigIntegerOfNbits(1024) → 8fbc... of BigInteger 356 */ 357 KJUR.crypto.Util.getRandomBigIntegerOfNbits = function(n) { 358 return new BigInteger(KJUR.crypto.Util.getRandomHexOfNbits(n), 16); 359 }; 360 361 /** 362 * get BigInteger object of random value from zero to max value<br/> 363 * @name getRandomBigIntegerZeroToMax 364 * @memberOf KJUR.crypto.Util 365 * @function 366 * @param {BigInteger} biMax max value of BigInteger object for random value 367 * @return {BigInteger} BigInteger object of specified random value 368 * @since jsrsasign 7.0.0 crypto 1.1.11 369 * @description 370 * This static method generates a BigInteger object with random value 371 * greater than or equal to zero and smaller than or equal to biMax 372 * (i.e. 0 ≤ result ≤ biMax). 373 * @example 374 * biMax = new BigInteger("3fa411...", 16); 375 * KJUR.crypto.Util.getRandomBigIntegerZeroToMax(biMax) → 8fbc... of BigInteger 376 */ 377 KJUR.crypto.Util.getRandomBigIntegerZeroToMax = function(biMax) { 378 var bitLenMax = biMax.bitLength(); 379 while (1) { 380 var biRand = KJUR.crypto.Util.getRandomBigIntegerOfNbits(bitLenMax); 381 if (biMax.compareTo(biRand) != -1) return biRand; 382 } 383 }; 384 385 /** 386 * get BigInteger object of random value from min value to max value<br/> 387 * @name getRandomBigIntegerMinToMax 388 * @memberOf KJUR.crypto.Util 389 * @function 390 * @param {BigInteger} biMin min value of BigInteger object for random value 391 * @param {BigInteger} biMax max value of BigInteger object for random value 392 * @return {BigInteger} BigInteger object of specified random value 393 * @since jsrsasign 7.0.0 crypto 1.1.11 394 * @description 395 * This static method generates a BigInteger object with random value 396 * greater than or equal to biMin and smaller than or equal to biMax 397 * (i.e. biMin ≤ result ≤ biMax). 398 * @example 399 * biMin = new BigInteger("2fa411...", 16); 400 * biMax = new BigInteger("3fa411...", 16); 401 * KJUR.crypto.Util.getRandomBigIntegerMinToMax(biMin, biMax) → 32f1... of BigInteger 402 */ 403 KJUR.crypto.Util.getRandomBigIntegerMinToMax = function(biMin, biMax) { 404 var flagCompare = biMin.compareTo(biMax); 405 if (flagCompare == 1) throw "biMin is greater than biMax"; 406 if (flagCompare == 0) return biMin; 407 408 var biDiff = biMax.subtract(biMin); 409 var biRand = KJUR.crypto.Util.getRandomBigIntegerZeroToMax(biDiff); 410 return biRand.add(biMin); 411 }; 412 413 // === Mac =============================================================== 414 415 /** 416 * MessageDigest class which is very similar to java.security.MessageDigest class<br/> 417 * @name KJUR.crypto.MessageDigest 418 * @class MessageDigest class which is very similar to java.security.MessageDigest class 419 * @param {Array} params parameters for constructor 420 * @property {Array} HASHLENGTH static Array of resulted byte length of hash (ex. HASHLENGTH["sha1"] == 20) 421 * @description 422 * <br/> 423 * Currently this supports following algorithm and providers combination: 424 * <ul> 425 * <li>md5 - cryptojs</li> 426 * <li>sha1 - cryptojs</li> 427 * <li>sha224 - cryptojs</li> 428 * <li>sha256 - cryptojs</li> 429 * <li>sha384 - cryptojs</li> 430 * <li>sha512 - cryptojs</li> 431 * <li>ripemd160 - cryptojs</li> 432 * <li>sha256 - sjcl (NEW from crypto.js 1.0.4)</li> 433 * </ul> 434 * @example 435 * // CryptoJS provider sample 436 * var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"}); 437 * md.updateString('aaa') 438 * var mdHex = md.digest() 439 * 440 * // SJCL(Stanford JavaScript Crypto Library) provider sample 441 * var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only 442 * md.updateString('aaa') 443 * var mdHex = md.digest() 444 * 445 * // HASHLENGTH property 446 * KJUR.crypto.MessageDigest.HASHLENGTH['sha1'] &rarr 20 447 * KJUR.crypto.MessageDigest.HASHLENGTH['sha512'] &rarr 64 448 */ 449 KJUR.crypto.MessageDigest = function(params) { 450 var md = null; 451 var algName = null; 452 var provName = null; 453 454 /** 455 * set hash algorithm and provider<br/> 456 * @name setAlgAndProvider 457 * @memberOf KJUR.crypto.MessageDigest# 458 * @function 459 * @param {String} alg hash algorithm name 460 * @param {String} prov provider name 461 * @description 462 * This methods set an algorithm and a cryptographic provider.<br/> 463 * Here is acceptable algorithm names ignoring cases and hyphens: 464 * <ul> 465 * <li>MD5</li> 466 * <li>SHA1</li> 467 * <li>SHA224</li> 468 * <li>SHA256</li> 469 * <li>SHA384</li> 470 * <li>SHA512</li> 471 * <li>RIPEMD160</li> 472 * </ul> 473 * NOTE: Since jsrsasign 6.2.0 crypto 1.1.10, this method ignores 474 * upper or lower cases. Also any hyphens (i.e. "-") will be ignored 475 * so that "SHA1" or "SHA-1" will be acceptable. 476 * @example 477 * // for SHA1 478 * md.setAlgAndProvider('sha1', 'cryptojs'); 479 * md.setAlgAndProvider('SHA1'); 480 * // for RIPEMD160 481 * md.setAlgAndProvider('ripemd160', 'cryptojs'); 482 */ 483 this.setAlgAndProvider = function(alg, prov) { 484 alg = KJUR.crypto.MessageDigest.getCanonicalAlgName(alg); 485 486 if (alg !== null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg]; 487 488 // for cryptojs 489 if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 && 490 prov == 'cryptojs') { 491 try { 492 this.md = KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[alg].create(); 493 } catch (ex) { 494 throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex; 495 } 496 this.updateString = function(str) { 497 this.md.update(str); 498 }; 499 this.updateHex = function(hex) { 500 var wHex = CryptoJS.enc.Hex.parse(hex); 501 this.md.update(wHex); 502 }; 503 this.digest = function() { 504 var hash = this.md.finalize(); 505 return hash.toString(CryptoJS.enc.Hex); 506 }; 507 this.digestString = function(str) { 508 this.updateString(str); 509 return this.digest(); 510 }; 511 this.digestHex = function(hex) { 512 this.updateHex(hex); 513 return this.digest(); 514 }; 515 } 516 if (':sha256:'.indexOf(alg) != -1 && 517 prov == 'sjcl') { 518 try { 519 this.md = new sjcl.hash.sha256(); 520 } catch (ex) { 521 throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex; 522 } 523 this.updateString = function(str) { 524 this.md.update(str); 525 }; 526 this.updateHex = function(hex) { 527 var baHex = sjcl.codec.hex.toBits(hex); 528 this.md.update(baHex); 529 }; 530 this.digest = function() { 531 var hash = this.md.finalize(); 532 return sjcl.codec.hex.fromBits(hash); 533 }; 534 this.digestString = function(str) { 535 this.updateString(str); 536 return this.digest(); 537 }; 538 this.digestHex = function(hex) { 539 this.updateHex(hex); 540 return this.digest(); 541 }; 542 } 543 }; 544 545 /** 546 * update digest by specified string 547 * @name updateString 548 * @memberOf KJUR.crypto.MessageDigest# 549 * @function 550 * @param {String} str string to update 551 * @description 552 * @example 553 * md.updateString('New York'); 554 */ 555 this.updateString = function(str) { 556 throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName; 557 }; 558 559 /** 560 * update digest by specified hexadecimal string 561 * @name updateHex 562 * @memberOf KJUR.crypto.MessageDigest# 563 * @function 564 * @param {String} hex hexadecimal string to update 565 * @description 566 * @example 567 * md.updateHex('0afe36'); 568 */ 569 this.updateHex = function(hex) { 570 throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName; 571 }; 572 573 /** 574 * completes hash calculation and returns hash result 575 * @name digest 576 * @memberOf KJUR.crypto.MessageDigest# 577 * @function 578 * @description 579 * @example 580 * md.digest() 581 */ 582 this.digest = function() { 583 throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName; 584 }; 585 586 /** 587 * performs final update on the digest using string, then completes the digest computation 588 * @name digestString 589 * @memberOf KJUR.crypto.MessageDigest# 590 * @function 591 * @param {String} str string to final update 592 * @description 593 * @example 594 * md.digestString('aaa') 595 */ 596 this.digestString = function(str) { 597 throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName; 598 }; 599 600 /** 601 * performs final update on the digest using hexadecimal string, then completes the digest computation 602 * @name digestHex 603 * @memberOf KJUR.crypto.MessageDigest# 604 * @function 605 * @param {String} hex hexadecimal string to final update 606 * @description 607 * @example 608 * md.digestHex('0f2abd') 609 */ 610 this.digestHex = function(hex) { 611 throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName; 612 }; 613 614 if (params !== undefined) { 615 if (params['alg'] !== undefined) { 616 this.algName = params['alg']; 617 if (params['prov'] === undefined) 618 this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]; 619 this.setAlgAndProvider(this.algName, this.provName); 620 } 621 } 622 }; 623 624 /** 625 * get canonical hash algorithm name<br/> 626 * @name getCanonicalAlgName 627 * @memberOf KJUR.crypto.MessageDigest 628 * @function 629 * @param {String} alg hash algorithm name (ex. MD5, SHA-1, SHA1, SHA512 et.al.) 630 * @return {String} canonical hash algorithm name 631 * @since jsrsasign 6.2.0 crypto 1.1.10 632 * @description 633 * This static method normalizes from any hash algorithm name such as 634 * "SHA-1", "SHA1", "MD5", "sha512" to lower case name without hyphens 635 * such as "sha1". 636 * @example 637 * KJUR.crypto.MessageDigest.getCanonicalAlgName("SHA-1") &rarr "sha1" 638 * KJUR.crypto.MessageDigest.getCanonicalAlgName("MD5") &rarr "md5" 639 */ 640 KJUR.crypto.MessageDigest.getCanonicalAlgName = function(alg) { 641 if (typeof alg === "string") { 642 alg = alg.toLowerCase(); 643 alg = alg.replace(/-/, ''); 644 } 645 return alg; 646 }; 647 648 /** 649 * get resulted hash byte length for specified algorithm name<br/> 650 * @name getHashLength 651 * @memberOf KJUR.crypto.MessageDigest 652 * @function 653 * @param {String} alg non-canonicalized hash algorithm name (ex. MD5, SHA-1, SHA1, SHA512 et.al.) 654 * @return {Integer} resulted hash byte length 655 * @since jsrsasign 6.2.0 crypto 1.1.10 656 * @description 657 * This static method returns resulted byte length for specified algorithm name such as "SHA-1". 658 * @example 659 * KJUR.crypto.MessageDigest.getHashLength("SHA-1") &rarr 20 660 * KJUR.crypto.MessageDigest.getHashLength("sha1") &rarr 20 661 */ 662 KJUR.crypto.MessageDigest.getHashLength = function(alg) { 663 var MD = KJUR.crypto.MessageDigest 664 var alg2 = MD.getCanonicalAlgName(alg); 665 if (MD.HASHLENGTH[alg2] === undefined) 666 throw "not supported algorithm: " + alg; 667 return MD.HASHLENGTH[alg2]; 668 }; 669 670 // described in KJUR.crypto.MessageDigest class (since jsrsasign 6.2.0 crypto 1.1.10) 671 KJUR.crypto.MessageDigest.HASHLENGTH = { 672 'md5': 16, 673 'sha1': 20, 674 'sha224': 28, 675 'sha256': 32, 676 'sha384': 48, 677 'sha512': 64, 678 'ripemd160': 20 679 }; 680 681 // === Mac =============================================================== 682 683 /** 684 * Mac(Message Authentication Code) class which is very similar to java.security.Mac class 685 * @name KJUR.crypto.Mac 686 * @class Mac class which is very similar to java.security.Mac class 687 * @param {Array} params parameters for constructor 688 * @description 689 * <br/> 690 * Currently this supports following algorithm and providers combination: 691 * <ul> 692 * <li>hmacmd5 - cryptojs</li> 693 * <li>hmacsha1 - cryptojs</li> 694 * <li>hmacsha224 - cryptojs</li> 695 * <li>hmacsha256 - cryptojs</li> 696 * <li>hmacsha384 - cryptojs</li> 697 * <li>hmacsha512 - cryptojs</li> 698 * </ul> 699 * NOTE: HmacSHA224 and HmacSHA384 issue was fixed since jsrsasign 4.1.4. 700 * Please use 'ext/cryptojs-312-core-fix*.js' instead of 'core.js' of original CryptoJS 701 * to avoid those issue. 702 * <br/> 703 * NOTE2: Hmac signature bug was fixed in jsrsasign 4.9.0 by providing CryptoJS 704 * bug workaround. 705 * <br/> 706 * Please see {@link KJUR.crypto.Mac.setPassword}, how to provide password 707 * in various ways in detail. 708 * @example 709 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", "pass": "pass"}); 710 * mac.updateString('aaa') 711 * var macHex = md.doFinal() 712 * 713 * // other password representation 714 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"hex": "6161"}}); 715 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"utf8": "aa"}}); 716 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"rstr": "\x61\x61"}}); 717 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64": "Mi02/+...a=="}}); 718 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64u": "Mi02_-...a"}}); 719 */ 720 KJUR.crypto.Mac = function(params) { 721 var mac = null; 722 var pass = null; 723 var algName = null; 724 var provName = null; 725 var algProv = null; 726 727 this.setAlgAndProvider = function(alg, prov) { 728 alg = alg.toLowerCase(); 729 730 if (alg == null) alg = "hmacsha1"; 731 732 alg = alg.toLowerCase(); 733 if (alg.substr(0, 4) != "hmac") { 734 throw "setAlgAndProvider unsupported HMAC alg: " + alg; 735 } 736 737 if (prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg]; 738 this.algProv = alg + "/" + prov; 739 740 var hashAlg = alg.substr(4); 741 742 // for cryptojs 743 if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(hashAlg) != -1 && 744 prov == 'cryptojs') { 745 try { 746 var mdObj = KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[hashAlg]; 747 this.mac = CryptoJS.algo.HMAC.create(mdObj, this.pass); 748 } catch (ex) { 749 throw "setAlgAndProvider hash alg set fail hashAlg=" + hashAlg + "/" + ex; 750 } 751 this.updateString = function(str) { 752 this.mac.update(str); 753 }; 754 this.updateHex = function(hex) { 755 var wHex = CryptoJS.enc.Hex.parse(hex); 756 this.mac.update(wHex); 757 }; 758 this.doFinal = function() { 759 var hash = this.mac.finalize(); 760 return hash.toString(CryptoJS.enc.Hex); 761 }; 762 this.doFinalString = function(str) { 763 this.updateString(str); 764 return this.doFinal(); 765 }; 766 this.doFinalHex = function(hex) { 767 this.updateHex(hex); 768 return this.doFinal(); 769 }; 770 } 771 }; 772 773 /** 774 * update digest by specified string 775 * @name updateString 776 * @memberOf KJUR.crypto.Mac# 777 * @function 778 * @param {String} str string to update 779 * @description 780 * @example 781 * md.updateString('New York'); 782 */ 783 this.updateString = function(str) { 784 throw "updateString(str) not supported for this alg/prov: " + this.algProv; 785 }; 786 787 /** 788 * update digest by specified hexadecimal string 789 * @name updateHex 790 * @memberOf KJUR.crypto.Mac# 791 * @function 792 * @param {String} hex hexadecimal string to update 793 * @description 794 * @example 795 * md.updateHex('0afe36'); 796 */ 797 this.updateHex = function(hex) { 798 throw "updateHex(hex) not supported for this alg/prov: " + this.algProv; 799 }; 800 801 /** 802 * completes hash calculation and returns hash result 803 * @name doFinal 804 * @memberOf KJUR.crypto.Mac# 805 * @function 806 * @description 807 * @example 808 * md.digest() 809 */ 810 this.doFinal = function() { 811 throw "digest() not supported for this alg/prov: " + this.algProv; 812 }; 813 814 /** 815 * performs final update on the digest using string, then completes the digest computation 816 * @name doFinalString 817 * @memberOf KJUR.crypto.Mac# 818 * @function 819 * @param {String} str string to final update 820 * @description 821 * @example 822 * md.digestString('aaa') 823 */ 824 this.doFinalString = function(str) { 825 throw "digestString(str) not supported for this alg/prov: " + this.algProv; 826 }; 827 828 /** 829 * performs final update on the digest using hexadecimal string, 830 * then completes the digest computation 831 * @name doFinalHex 832 * @memberOf KJUR.crypto.Mac# 833 * @function 834 * @param {String} hex hexadecimal string to final update 835 * @description 836 * @example 837 * md.digestHex('0f2abd') 838 */ 839 this.doFinalHex = function(hex) { 840 throw "digestHex(hex) not supported for this alg/prov: " + this.algProv; 841 }; 842 843 /** 844 * set password for Mac 845 * @name setPassword 846 * @memberOf KJUR.crypto.Mac# 847 * @function 848 * @param {Object} pass password for Mac 849 * @since crypto 1.1.7 jsrsasign 4.9.0 850 * @description 851 * This method will set password for (H)Mac internally. 852 * Argument 'pass' can be specified as following: 853 * <ul> 854 * <li>even length string of 0..9, a..f or A-F: implicitly specified as hexadecimal string</li> 855 * <li>not above string: implicitly specified as raw string</li> 856 * <li>{rstr: "\x65\x70"}: explicitly specified as raw string</li> 857 * <li>{hex: "6570"}: explicitly specified as hexacedimal string</li> 858 * <li>{utf8: "秘密"}: explicitly specified as UTF8 string</li> 859 * <li>{b64: "Mi78..=="}: explicitly specified as Base64 string</li> 860 * <li>{b64u: "Mi7-_"}: explicitly specified as Base64URL string</li> 861 * </ul> 862 * It is *STRONGLY RECOMMENDED* that explicit representation of password argument 863 * to avoid ambiguity. For example string "6161" can mean a string "6161" or 864 * a hexadecimal string of "aa" (i.e. \x61\x61). 865 * @example 866 * mac = KJUR.crypto.Mac({'alg': 'hmacsha256'}); 867 * // set password by implicit raw string 868 * mac.setPassword("\x65\x70\xb9\x0b"); 869 * mac.setPassword("password"); 870 * // set password by implicit hexadecimal string 871 * mac.setPassword("6570b90b"); 872 * mac.setPassword("6570B90B"); 873 * // set password by explicit raw string 874 * mac.setPassword({"rstr": "\x65\x70\xb9\x0b"}); 875 * // set password by explicit hexadecimal string 876 * mac.setPassword({"hex": "6570b90b"}); 877 * // set password by explicit utf8 string 878 * mac.setPassword({"utf8": "passwordパスワード"); 879 * // set password by explicit Base64 string 880 * mac.setPassword({"b64": "Mb+c3f/=="}); 881 * // set password by explicit Base64URL string 882 * mac.setPassword({"b64u": "Mb-c3f_"}); 883 */ 884 this.setPassword = function(pass) { 885 // internal this.pass shall be CryptoJS DWord Object for CryptoJS bug 886 // work around. CrytoJS HMac password can be passed by 887 // raw string as described in the manual however it doesn't 888 // work properly in some case. If password was passed 889 // by CryptoJS DWord which is not described in the manual 890 // it seems to work. (fixed since crypto 1.1.7) 891 892 if (typeof pass == 'string') { 893 var hPass = pass; 894 if (pass.length % 2 == 1 || ! pass.match(/^[0-9A-Fa-f]+$/)) { // raw str 895 hPass = rstrtohex(pass); 896 } 897 this.pass = CryptoJS.enc.Hex.parse(hPass); 898 return; 899 } 900 901 if (typeof pass != 'object') 902 throw "KJUR.crypto.Mac unsupported password type: " + pass; 903 904 var hPass = null; 905 if (pass.hex !== undefined) { 906 if (pass.hex.length % 2 != 0 || ! pass.hex.match(/^[0-9A-Fa-f]+$/)) 907 throw "Mac: wrong hex password: " + pass.hex; 908 hPass = pass.hex; 909 } 910 if (pass.utf8 !== undefined) hPass = utf8tohex(pass.utf8); 911 if (pass.rstr !== undefined) hPass = rstrtohex(pass.rstr); 912 if (pass.b64 !== undefined) hPass = b64tohex(pass.b64); 913 if (pass.b64u !== undefined) hPass = b64utohex(pass.b64u); 914 915 if (hPass == null) 916 throw "KJUR.crypto.Mac unsupported password type: " + pass; 917 918 this.pass = CryptoJS.enc.Hex.parse(hPass); 919 }; 920 921 if (params !== undefined) { 922 if (params.pass !== undefined) { 923 this.setPassword(params.pass); 924 } 925 if (params.alg !== undefined) { 926 this.algName = params.alg; 927 if (params['prov'] === undefined) 928 this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]; 929 this.setAlgAndProvider(this.algName, this.provName); 930 } 931 } 932 }; 933 934 // ====== Signature class ========================================================= 935 /** 936 * Signature class which is very similar to java.security.Signature class 937 * @name KJUR.crypto.Signature 938 * @class Signature class which is very similar to java.security.Signature class 939 * @param {Array} params parameters for constructor 940 * @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null 941 * @description 942 * <br/> 943 * As for params of constructor's argument, it can be specify following attributes: 944 * <ul> 945 * <li>alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}with{RSA,ECDSA,DSA})</li> 946 * <li>provider - currently 'cryptojs/jsrsa' only</li> 947 * </ul> 948 * <h4>SUPPORTED ALGORITHMS AND PROVIDERS</h4> 949 * This Signature class supports following signature algorithm and provider names: 950 * <ul> 951 * <li>MD5withRSA - cryptojs/jsrsa</li> 952 * <li>SHA1withRSA - cryptojs/jsrsa</li> 953 * <li>SHA224withRSA - cryptojs/jsrsa</li> 954 * <li>SHA256withRSA - cryptojs/jsrsa</li> 955 * <li>SHA384withRSA - cryptojs/jsrsa</li> 956 * <li>SHA512withRSA - cryptojs/jsrsa</li> 957 * <li>RIPEMD160withRSA - cryptojs/jsrsa</li> 958 * <li>MD5withECDSA - cryptojs/jsrsa</li> 959 * <li>SHA1withECDSA - cryptojs/jsrsa</li> 960 * <li>SHA224withECDSA - cryptojs/jsrsa</li> 961 * <li>SHA256withECDSA - cryptojs/jsrsa</li> 962 * <li>SHA384withECDSA - cryptojs/jsrsa</li> 963 * <li>SHA512withECDSA - cryptojs/jsrsa</li> 964 * <li>RIPEMD160withECDSA - cryptojs/jsrsa</li> 965 * <li>MD5withRSAandMGF1 - cryptojs/jsrsa</li> 966 * <li>SHA1withRSAandMGF1 - cryptojs/jsrsa</li> 967 * <li>SHA224withRSAandMGF1 - cryptojs/jsrsa</li> 968 * <li>SHA256withRSAandMGF1 - cryptojs/jsrsa</li> 969 * <li>SHA384withRSAandMGF1 - cryptojs/jsrsa</li> 970 * <li>SHA512withRSAandMGF1 - cryptojs/jsrsa</li> 971 * <li>RIPEMD160withRSAandMGF1 - cryptojs/jsrsa</li> 972 * <li>SHA1withDSA - cryptojs/jsrsa</li> 973 * <li>SHA224withDSA - cryptojs/jsrsa</li> 974 * <li>SHA256withDSA - cryptojs/jsrsa</li> 975 * </ul> 976 * Here are supported elliptic cryptographic curve names and their aliases for ECDSA: 977 * <ul> 978 * <li>secp256k1</li> 979 * <li>secp256r1, NIST P-256, P-256, prime256v1</li> 980 * <li>secp384r1, NIST P-384, P-384</li> 981 * </ul> 982 * NOTE1: DSA signing algorithm is also supported since crypto 1.1.5. 983 * <h4>EXAMPLES</h4> 984 * @example 985 * // RSA signature generation 986 * var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"}); 987 * sig.init(prvKeyPEM); 988 * sig.updateString('aaa'); 989 * var hSigVal = sig.sign(); 990 * 991 * // DSA signature validation 992 * var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"}); 993 * sig2.init(certPEM); 994 * sig.updateString('aaa'); 995 * var isValid = sig2.verify(hSigVal); 996 * 997 * // ECDSA signing 998 * var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'}); 999 * sig.init(prvKeyPEM); 1000 * sig.updateString('aaa'); 1001 * var sigValueHex = sig.sign(); 1002 * 1003 * // ECDSA verifying 1004 * var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'}); 1005 * sig.init(certPEM); 1006 * sig.updateString('aaa'); 1007 * var isValid = sig.verify(sigValueHex); 1008 */ 1009 KJUR.crypto.Signature = function(params) { 1010 var prvKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for signing 1011 var pubKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for verifying 1012 1013 var md = null; // KJUR.crypto.MessageDigest object 1014 var sig = null; 1015 var algName = null; 1016 var provName = null; 1017 var algProvName = null; 1018 var mdAlgName = null; 1019 var pubkeyAlgName = null; // rsa,ecdsa,rsaandmgf1(=rsapss) 1020 var state = null; 1021 var pssSaltLen = -1; 1022 var initParams = null; 1023 1024 var sHashHex = null; // hex hash value for hex 1025 var hDigestInfo = null; 1026 var hPaddedDigestInfo = null; 1027 var hSign = null; 1028 1029 this._setAlgNames = function() { 1030 var matchResult = this.algName.match(/^(.+)with(.+)$/); 1031 if (matchResult) { 1032 this.mdAlgName = matchResult[1].toLowerCase(); 1033 this.pubkeyAlgName = matchResult[2].toLowerCase(); 1034 } 1035 }; 1036 1037 this._zeroPaddingOfSignature = function(hex, bitLength) { 1038 var s = ""; 1039 var nZero = bitLength / 4 - hex.length; 1040 for (var i = 0; i < nZero; i++) { 1041 s = s + "0"; 1042 } 1043 return s + hex; 1044 }; 1045 1046 /** 1047 * set signature algorithm and provider 1048 * @name setAlgAndProvider 1049 * @memberOf KJUR.crypto.Signature# 1050 * @function 1051 * @param {String} alg signature algorithm name 1052 * @param {String} prov provider name 1053 * @description 1054 * @example 1055 * md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa'); 1056 */ 1057 this.setAlgAndProvider = function(alg, prov) { 1058 this._setAlgNames(); 1059 if (prov != 'cryptojs/jsrsa') 1060 throw "provider not supported: " + prov; 1061 1062 if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) { 1063 try { 1064 this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName}); 1065 } catch (ex) { 1066 throw "setAlgAndProvider hash alg set fail alg=" + 1067 this.mdAlgName + "/" + ex; 1068 } 1069 1070 this.init = function(keyparam, pass) { 1071 var keyObj = null; 1072 try { 1073 if (pass === undefined) { 1074 keyObj = KEYUTIL.getKey(keyparam); 1075 } else { 1076 keyObj = KEYUTIL.getKey(keyparam, pass); 1077 } 1078 } catch (ex) { 1079 throw "init failed:" + ex; 1080 } 1081 1082 if (keyObj.isPrivate === true) { 1083 this.prvKey = keyObj; 1084 this.state = "SIGN"; 1085 } else if (keyObj.isPublic === true) { 1086 this.pubKey = keyObj; 1087 this.state = "VERIFY"; 1088 } else { 1089 throw "init failed.:" + keyObj; 1090 } 1091 }; 1092 1093 this.initSign = function(params) { 1094 if (typeof params['ecprvhex'] == 'string' && 1095 typeof params['eccurvename'] == 'string') { 1096 this.ecprvhex = params['ecprvhex']; 1097 this.eccurvename = params['eccurvename']; 1098 } else { 1099 this.prvKey = params; 1100 } 1101 this.state = "SIGN"; 1102 }; 1103 1104 this.initVerifyByPublicKey = function(params) { 1105 if (typeof params['ecpubhex'] == 'string' && 1106 typeof params['eccurvename'] == 'string') { 1107 this.ecpubhex = params['ecpubhex']; 1108 this.eccurvename = params['eccurvename']; 1109 } else if (params instanceof KJUR.crypto.ECDSA) { 1110 this.pubKey = params; 1111 } else if (params instanceof RSAKey) { 1112 this.pubKey = params; 1113 } 1114 this.state = "VERIFY"; 1115 }; 1116 1117 this.initVerifyByCertificatePEM = function(certPEM) { 1118 var x509 = new X509(); 1119 x509.readCertPEM(certPEM); 1120 this.pubKey = x509.subjectPublicKeyRSA; 1121 this.state = "VERIFY"; 1122 }; 1123 1124 this.updateString = function(str) { 1125 this.md.updateString(str); 1126 }; 1127 1128 this.updateHex = function(hex) { 1129 this.md.updateHex(hex); 1130 }; 1131 1132 this.sign = function() { 1133 this.sHashHex = this.md.digest(); 1134 if (typeof this.ecprvhex != "undefined" && 1135 typeof this.eccurvename != "undefined") { 1136 var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename}); 1137 this.hSign = ec.signHex(this.sHashHex, this.ecprvhex); 1138 } else if (this.prvKey instanceof RSAKey && 1139 this.pubkeyAlgName == "rsaandmgf1") { 1140 this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex, 1141 this.mdAlgName, 1142 this.pssSaltLen); 1143 } else if (this.prvKey instanceof RSAKey && 1144 this.pubkeyAlgName == "rsa") { 1145 this.hSign = this.prvKey.signWithMessageHash(this.sHashHex, 1146 this.mdAlgName); 1147 } else if (this.prvKey instanceof KJUR.crypto.ECDSA) { 1148 this.hSign = this.prvKey.signWithMessageHash(this.sHashHex); 1149 } else if (this.prvKey instanceof KJUR.crypto.DSA) { 1150 this.hSign = this.prvKey.signWithMessageHash(this.sHashHex); 1151 } else { 1152 throw "Signature: unsupported public key alg: " + this.pubkeyAlgName; 1153 } 1154 return this.hSign; 1155 }; 1156 this.signString = function(str) { 1157 this.updateString(str); 1158 return this.sign(); 1159 }; 1160 this.signHex = function(hex) { 1161 this.updateHex(hex); 1162 return this.sign(); 1163 }; 1164 this.verify = function(hSigVal) { 1165 this.sHashHex = this.md.digest(); 1166 if (typeof this.ecpubhex != "undefined" && 1167 typeof this.eccurvename != "undefined") { 1168 var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename}); 1169 return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex); 1170 } else if (this.pubKey instanceof RSAKey && 1171 this.pubkeyAlgName == "rsaandmgf1") { 1172 return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal, 1173 this.mdAlgName, 1174 this.pssSaltLen); 1175 } else if (this.pubKey instanceof RSAKey && 1176 this.pubkeyAlgName == "rsa") { 1177 return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal); 1178 } else if (this.pubKey instanceof KJUR.crypto.ECDSA) { 1179 return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal); 1180 } else if (this.pubKey instanceof KJUR.crypto.DSA) { 1181 return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal); 1182 } else { 1183 throw "Signature: unsupported public key alg: " + this.pubkeyAlgName; 1184 } 1185 }; 1186 } 1187 }; 1188 1189 /** 1190 * Initialize this object for signing or verifying depends on key 1191 * @name init 1192 * @memberOf KJUR.crypto.Signature# 1193 * @function 1194 * @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 1195 * @param {String} pass (OPTION) passcode for encrypted private key 1196 * @since crypto 1.1.3 1197 * @description 1198 * This method is very useful initialize method for Signature class since 1199 * you just specify key then this method will automatically initialize it 1200 * using {@link KEYUTIL.getKey} method. 1201 * As for 'key', following argument type are supported: 1202 * <h5>signing</h5> 1203 * <ul> 1204 * <li>PEM formatted PKCS#8 encrypted RSA/ECDSA private key concluding "BEGIN ENCRYPTED PRIVATE KEY"</li> 1205 * <li>PEM formatted PKCS#5 encrypted RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" and ",ENCRYPTED"</li> 1206 * <li>PEM formatted PKCS#8 plain RSA/ECDSA private key concluding "BEGIN PRIVATE KEY"</li> 1207 * <li>PEM formatted PKCS#5 plain RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" without ",ENCRYPTED"</li> 1208 * <li>RSAKey object of private key</li> 1209 * <li>KJUR.crypto.ECDSA object of private key</li> 1210 * <li>KJUR.crypto.DSA object of private key</li> 1211 * </ul> 1212 * <h5>verification</h5> 1213 * <ul> 1214 * <li>PEM formatted PKCS#8 RSA/EC/DSA public key concluding "BEGIN PUBLIC KEY"</li> 1215 * <li>PEM formatted X.509 certificate with RSA/EC/DSA public key concluding 1216 * "BEGIN CERTIFICATE", "BEGIN X509 CERTIFICATE" or "BEGIN TRUSTED CERTIFICATE".</li> 1217 * <li>RSAKey object of public key</li> 1218 * <li>KJUR.crypto.ECDSA object of public key</li> 1219 * <li>KJUR.crypto.DSA object of public key</li> 1220 * </ul> 1221 * @example 1222 * sig.init(sCertPEM) 1223 */ 1224 this.init = function(key, pass) { 1225 throw "init(key, pass) not supported for this alg:prov=" + 1226 this.algProvName; 1227 }; 1228 1229 /** 1230 * (DEPRECATED) Initialize this object for verifying with a public key 1231 * @name initVerifyByPublicKey 1232 * @memberOf KJUR.crypto.Signature# 1233 * @function 1234 * @param {Object} param RSAKey object of public key or associative array for ECDSA 1235 * @since 1.0.2 1236 * @deprecated from crypto 1.1.5. please use init() method instead. 1237 * @description 1238 * Public key information will be provided as 'param' parameter and the value will be 1239 * following: 1240 * <ul> 1241 * <li>{@link RSAKey} object for RSA verification</li> 1242 * <li>associative array for ECDSA verification 1243 * (ex. <code>{'ecpubhex': '041f..', 'eccurvename': 'secp256r1'}</code>) 1244 * </li> 1245 * </ul> 1246 * @example 1247 * sig.initVerifyByPublicKey(rsaPrvKey) 1248 */ 1249 this.initVerifyByPublicKey = function(rsaPubKey) { 1250 throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" + 1251 this.algProvName; 1252 }; 1253 1254 /** 1255 * (DEPRECATED) Initialize this object for verifying with a certficate 1256 * @name initVerifyByCertificatePEM 1257 * @memberOf KJUR.crypto.Signature# 1258 * @function 1259 * @param {String} certPEM PEM formatted string of certificate 1260 * @since 1.0.2 1261 * @deprecated from crypto 1.1.5. please use init() method instead. 1262 * @description 1263 * @example 1264 * sig.initVerifyByCertificatePEM(certPEM) 1265 */ 1266 this.initVerifyByCertificatePEM = function(certPEM) { 1267 throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" + 1268 this.algProvName; 1269 }; 1270 1271 /** 1272 * (DEPRECATED) Initialize this object for signing 1273 * @name initSign 1274 * @memberOf KJUR.crypto.Signature# 1275 * @function 1276 * @param {Object} param RSAKey object of public key or associative array for ECDSA 1277 * @deprecated from crypto 1.1.5. please use init() method instead. 1278 * @description 1279 * Private key information will be provided as 'param' parameter and the value will be 1280 * following: 1281 * <ul> 1282 * <li>{@link RSAKey} object for RSA signing</li> 1283 * <li>associative array for ECDSA signing 1284 * (ex. <code>{'ecprvhex': '1d3f..', 'eccurvename': 'secp256r1'}</code>)</li> 1285 * </ul> 1286 * @example 1287 * sig.initSign(prvKey) 1288 */ 1289 this.initSign = function(prvKey) { 1290 throw "initSign(prvKey) not supported for this alg:prov=" + this.algProvName; 1291 }; 1292 1293 /** 1294 * Updates the data to be signed or verified by a string 1295 * @name updateString 1296 * @memberOf KJUR.crypto.Signature# 1297 * @function 1298 * @param {String} str string to use for the update 1299 * @description 1300 * @example 1301 * sig.updateString('aaa') 1302 */ 1303 this.updateString = function(str) { 1304 throw "updateString(str) not supported for this alg:prov=" + this.algProvName; 1305 }; 1306 1307 /** 1308 * Updates the data to be signed or verified by a hexadecimal string 1309 * @name updateHex 1310 * @memberOf KJUR.crypto.Signature# 1311 * @function 1312 * @param {String} hex hexadecimal string to use for the update 1313 * @description 1314 * @example 1315 * sig.updateHex('1f2f3f') 1316 */ 1317 this.updateHex = function(hex) { 1318 throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName; 1319 }; 1320 1321 /** 1322 * Returns the signature bytes of all data updates as a hexadecimal string 1323 * @name sign 1324 * @memberOf KJUR.crypto.Signature# 1325 * @function 1326 * @return the signature bytes as a hexadecimal string 1327 * @description 1328 * @example 1329 * var hSigValue = sig.sign() 1330 */ 1331 this.sign = function() { 1332 throw "sign() not supported for this alg:prov=" + this.algProvName; 1333 }; 1334 1335 /** 1336 * performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string 1337 * @name signString 1338 * @memberOf KJUR.crypto.Signature# 1339 * @function 1340 * @param {String} str string to final update 1341 * @return the signature bytes of a hexadecimal string 1342 * @description 1343 * @example 1344 * var hSigValue = sig.signString('aaa') 1345 */ 1346 this.signString = function(str) { 1347 throw "digestString(str) not supported for this alg:prov=" + this.algProvName; 1348 }; 1349 1350 /** 1351 * performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string 1352 * @name signHex 1353 * @memberOf KJUR.crypto.Signature# 1354 * @function 1355 * @param {String} hex hexadecimal string to final update 1356 * @return the signature bytes of a hexadecimal string 1357 * @description 1358 * @example 1359 * var hSigValue = sig.signHex('1fdc33') 1360 */ 1361 this.signHex = function(hex) { 1362 throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName; 1363 }; 1364 1365 /** 1366 * verifies the passed-in signature. 1367 * @name verify 1368 * @memberOf KJUR.crypto.Signature# 1369 * @function 1370 * @param {String} str string to final update 1371 * @return {Boolean} true if the signature was verified, otherwise false 1372 * @description 1373 * @example 1374 * var isValid = sig.verify('1fbcefdca4823a7(snip)') 1375 */ 1376 this.verify = function(hSigVal) { 1377 throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName; 1378 }; 1379 1380 this.initParams = params; 1381 1382 if (params !== undefined) { 1383 if (params['alg'] !== undefined) { 1384 this.algName = params['alg']; 1385 if (params['prov'] === undefined) { 1386 this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName]; 1387 } else { 1388 this.provName = params['prov']; 1389 } 1390 this.algProvName = this.algName + ":" + this.provName; 1391 this.setAlgAndProvider(this.algName, this.provName); 1392 this._setAlgNames(); 1393 } 1394 1395 if (params['psssaltlen'] !== undefined) this.pssSaltLen = params['psssaltlen']; 1396 1397 if (params['prvkeypem'] !== undefined) { 1398 if (params['prvkeypas'] !== undefined) { 1399 throw "both prvkeypem and prvkeypas parameters not supported"; 1400 } else { 1401 try { 1402 var prvKey = new RSAKey(); 1403 prvKey.readPrivateKeyFromPEMString(params['prvkeypem']); 1404 this.initSign(prvKey); 1405 } catch (ex) { 1406 throw "fatal error to load pem private key: " + ex; 1407 } 1408 } 1409 } 1410 } 1411 }; 1412 1413 // ====== Cipher class ============================================================ 1414 /** 1415 * Cipher class to encrypt and decrypt data<br/> 1416 * @name KJUR.crypto.Cipher 1417 * @class Cipher class to encrypt and decrypt data<br/> 1418 * @param {Array} params parameters for constructor 1419 * @since jsrsasign 6.2.0 crypto 1.1.10 1420 * @description 1421 * Here is supported canonicalized cipher algorithm names and its standard names: 1422 * <ul> 1423 * <li>RSA - RSA/ECB/PKCS1Padding (default for RSAKey)</li> 1424 * <li>RSAOAEP - RSA/ECB/OAEPWithSHA-1AndMGF1Padding</li> 1425 * <li>RSAOAEP224 - RSA/ECB/OAEPWithSHA-224AndMGF1Padding(*)</li> 1426 * <li>RSAOAEP256 - RSA/ECB/OAEPWithSHA-256AndMGF1Padding</li> 1427 * <li>RSAOAEP384 - RSA/ECB/OAEPWithSHA-384AndMGF1Padding(*)</li> 1428 * <li>RSAOAEP512 - RSA/ECB/OAEPWithSHA-512AndMGF1Padding(*)</li> 1429 * </ul> 1430 * NOTE: (*) is not supported in Java JCE.<br/> 1431 * Currently this class supports only RSA encryption and decryption. 1432 * However it is planning to implement also symmetric ciphers near in the future. 1433 * @example 1434 */ 1435 KJUR.crypto.Cipher = function(params) { 1436 }; 1437 1438 /** 1439 * encrypt raw string by specified key and algorithm<br/> 1440 * @name encrypt 1441 * @memberOf KJUR.crypto.Cipher 1442 * @function 1443 * @param {String} s input string to encrypt 1444 * @param {Object} keyObj RSAKey object or hexadecimal string of symmetric cipher key 1445 * @param {String} algName short/long algorithm name for encryption/decryption 1446 * @return {String} hexadecimal encrypted string 1447 * @since jsrsasign 6.2.0 crypto 1.1.10 1448 * @description 1449 * This static method encrypts raw string with specified key and algorithm. 1450 * @example 1451 * KJUR.crypto.Cipher.encrypt("aaa", pubRSAKeyObj) → "1abc2d..." 1452 * KJUR.crypto.Cipher.encrypt("aaa", pubRSAKeyObj, "RSAOAEP") → "23ab02..." 1453 */ 1454 KJUR.crypto.Cipher.encrypt = function(s, keyObj, algName) { 1455 if (keyObj instanceof RSAKey && keyObj.isPublic) { 1456 var algName2 = KJUR.crypto.Cipher.getAlgByKeyAndName(keyObj, algName); 1457 if (algName2 === "RSA") return keyObj.encrypt(s); 1458 if (algName2 === "RSAOAEP") return keyObj.encryptOAEP(s, "sha1"); 1459 1460 var a = algName2.match(/^RSAOAEP(\d+)$/); 1461 if (a !== null) return keyObj.encryptOAEP(s, "sha" + a[1]); 1462 1463 throw "Cipher.encrypt: unsupported algorithm for RSAKey: " + algName; 1464 } else { 1465 throw "Cipher.encrypt: unsupported key or algorithm"; 1466 } 1467 }; 1468 1469 /** 1470 * decrypt encrypted hexadecimal string with specified key and algorithm<br/> 1471 * @name decrypt 1472 * @memberOf KJUR.crypto.Cipher 1473 * @function 1474 * @param {String} hex hexadecial string of encrypted message 1475 * @param {Object} keyObj RSAKey object or hexadecimal string of symmetric cipher key 1476 * @param {String} algName short/long algorithm name for encryption/decryption 1477 * @return {String} hexadecimal encrypted string 1478 * @since jsrsasign 6.2.0 crypto 1.1.10 1479 * @description 1480 * This static method decrypts encrypted hexadecimal string with specified key and algorithm. 1481 * @example 1482 * KJUR.crypto.Cipher.decrypt("aaa", prvRSAKeyObj) → "1abc2d..." 1483 * KJUR.crypto.Cipher.decrypt("aaa", prvRSAKeyObj, "RSAOAEP) → "23ab02..." 1484 */ 1485 KJUR.crypto.Cipher.decrypt = function(hex, keyObj, algName) { 1486 if (keyObj instanceof RSAKey && keyObj.isPrivate) { 1487 var algName2 = KJUR.crypto.Cipher.getAlgByKeyAndName(keyObj, algName); 1488 if (algName2 === "RSA") return keyObj.decrypt(hex); 1489 if (algName2 === "RSAOAEP") return keyObj.decryptOAEP(hex, "sha1"); 1490 1491 var a = algName2.match(/^RSAOAEP(\d+)$/); 1492 if (a !== null) return keyObj.decryptOAEP(hex, "sha" + a[1]); 1493 1494 throw "Cipher.decrypt: unsupported algorithm for RSAKey: " + algName; 1495 } else { 1496 throw "Cipher.decrypt: unsupported key or algorithm"; 1497 } 1498 }; 1499 1500 /** 1501 * get canonicalized encrypt/decrypt algorithm name by key and short/long algorithm name<br/> 1502 * @name getAlgByKeyAndName 1503 * @memberOf KJUR.crypto.Cipher 1504 * @function 1505 * @param {Object} keyObj RSAKey object or hexadecimal string of symmetric cipher key 1506 * @param {String} algName short/long algorithm name for encryption/decryption 1507 * @return {String} canonicalized algorithm name for encryption/decryption 1508 * @since jsrsasign 6.2.0 crypto 1.1.10 1509 * @description 1510 * Here is supported canonicalized cipher algorithm names and its standard names: 1511 * <ul> 1512 * <li>RSA - RSA/ECB/PKCS1Padding (default for RSAKey)</li> 1513 * <li>RSAOAEP - RSA/ECB/OAEPWithSHA-1AndMGF1Padding</li> 1514 * <li>RSAOAEP224 - RSA/ECB/OAEPWithSHA-224AndMGF1Padding(*)</li> 1515 * <li>RSAOAEP256 - RSA/ECB/OAEPWithSHA-256AndMGF1Padding</li> 1516 * <li>RSAOAEP384 - RSA/ECB/OAEPWithSHA-384AndMGF1Padding(*)</li> 1517 * <li>RSAOAEP512 - RSA/ECB/OAEPWithSHA-512AndMGF1Padding(*)</li> 1518 * </ul> 1519 * NOTE: (*) is not supported in Java JCE. 1520 * @example 1521 * KJUR.crypto.Cipher.getAlgByKeyAndName(objRSAKey) → "RSA" 1522 * KJUR.crypto.Cipher.getAlgByKeyAndName(objRSAKey, "RSAOAEP") → "RSAOAEP" 1523 */ 1524 KJUR.crypto.Cipher.getAlgByKeyAndName = function(keyObj, algName) { 1525 if (keyObj instanceof RSAKey) { 1526 if (":RSA:RSAOAEP:RSAOAEP224:RSAOAEP256:RSAOAEP384:RSAOAEP512:".indexOf(algName) != -1) 1527 return algName; 1528 if (algName === null || algName === undefined) return "RSA"; 1529 throw "getAlgByKeyAndName: not supported algorithm name for RSAKey: " + algName; 1530 } 1531 throw "getAlgByKeyAndName: not supported algorithm name: " + algName; 1532 } 1533 1534 // ====== Other Utility class ===================================================== 1535 1536 /** 1537 * static object for cryptographic function utilities 1538 * @name KJUR.crypto.OID 1539 * @class static object for cryptography related OIDs 1540 * @property {Array} oidhex2name key value of hexadecimal OID and its name 1541 * (ex. '2a8648ce3d030107' and 'secp256r1') 1542 * @since crypto 1.1.3 1543 * @description 1544 */ 1545 KJUR.crypto.OID = new function() { 1546 this.oidhex2name = { 1547 '2a864886f70d010101': 'rsaEncryption', 1548 '2a8648ce3d0201': 'ecPublicKey', 1549 '2a8648ce380401': 'dsa', 1550 '2a8648ce3d030107': 'secp256r1', 1551 '2b8104001f': 'secp192k1', 1552 '2b81040021': 'secp224r1', 1553 '2b8104000a': 'secp256k1', 1554 '2b81040023': 'secp521r1', 1555 '2b81040022': 'secp384r1', 1556 '2a8648ce380403': 'SHA1withDSA', // 1.2.840.10040.4.3 1557 '608648016503040301': 'SHA224withDSA', // 2.16.840.1.101.3.4.3.1 1558 '608648016503040302': 'SHA256withDSA', // 2.16.840.1.101.3.4.3.2 1559 }; 1560 }; 1561