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