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