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