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