1 /*! asn1-1.0.4.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
  2  */
  3 /*
  4  * asn1.js - ASN.1 DER encoder classes
  5  *
  6  * Copyright (c) 2013 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 asn1-1.0.js
 18  * @author Kenji Urushima kenji.urushima@gmail.com
 19  * @version asn1 1.0.4 (2013-Oct-02)
 20  * @since jsrsasign 2.1
 21  * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 22  */
 23 
 24 /** 
 25  * kjur's class library name space
 26  * <p>
 27  * This name space provides following name spaces:
 28  * <ul>
 29  * <li>{@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder</li>
 30  * <li>{@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL</li>
 31  * <li>{@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature 
 32  * class and utilities</li>
 33  * </ul>
 34  * </p> 
 35  * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
 36   * @name KJUR
 37  * @namespace kjur's class library name space
 38  */
 39 if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
 40 
 41 /**
 42  * kjur's ASN.1 class library name space
 43  * <p>
 44  * This is ITU-T X.690 ASN.1 DER encoder class library and
 45  * class structure and methods is very similar to 
 46  * org.bouncycastle.asn1 package of 
 47  * well known BouncyCaslte Cryptography Library.
 48  *
 49  * <h4>PROVIDING ASN.1 PRIMITIVES</h4>
 50  * Here are ASN.1 DER primitive classes.
 51  * <ul>
 52  * <li>0x01 {@link KJUR.asn1.DERBoolean}</li>
 53  * <li>0x02 {@link KJUR.asn1.DERInteger}</li>
 54  * <li>0x03 {@link KJUR.asn1.DERBitString}</li>
 55  * <li>0x04 {@link KJUR.asn1.DEROctetString}</li>
 56  * <li>0x05 {@link KJUR.asn1.DERNull}</li>
 57  * <li>0x06 {@link KJUR.asn1.DERObjectIdentifier}</li>
 58  * <li>0x0c {@link KJUR.asn1.DERUTF8String}</li>
 59  * <li>0x12 {@link KJUR.asn1.DERNumericString}</li>
 60  * <li>0x13 {@link KJUR.asn1.DERPrintableString}</li>
 61  * <li>0x14 {@link KJUR.asn1.DERTeletexString}</li>
 62  * <li>0x16 {@link KJUR.asn1.DERIA5String}</li>
 63  * <li>0x17 {@link KJUR.asn1.DERUTCTime}</li>
 64  * <li>0x18 {@link KJUR.asn1.DERGeneralizedTime}</li>
 65  * <li>0x30 {@link KJUR.asn1.DERSequence}</li>
 66  * <li>0x31 {@link KJUR.asn1.DERSet}</li>
 67  * </ul>
 68  *
 69  * <h4>OTHER ASN.1 CLASSES</h4>
 70  * <ul>
 71  * <li>{@link KJUR.asn1.ASN1Object}</li>
 72  * <li>{@link KJUR.asn1.DERAbstractString}</li>
 73  * <li>{@link KJUR.asn1.DERAbstractTime}</li>
 74  * <li>{@link KJUR.asn1.DERAbstractStructured}</li>
 75  * <li>{@link KJUR.asn1.DERTaggedObject}</li>
 76  * </ul>
 77  * </p>
 78  * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
 79  * @name KJUR.asn1
 80  * @namespace
 81  */
 82 if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {};
 83 
 84 /**
 85  * ASN1 utilities class
 86  * @name KJUR.asn1.ASN1Util
 87  * @class ASN1 utilities class
 88  * @since asn1 1.0.2
 89  */
 90 KJUR.asn1.ASN1Util = new function() {
 91     this.integerToByteHex = function(i) {
 92 	var h = i.toString(16);
 93 	if ((h.length % 2) == 1) h = '0' + h;
 94 	return h;
 95     };
 96     this.bigIntToMinTwosComplementsHex = function(bigIntegerValue) {
 97 	var h = bigIntegerValue.toString(16);
 98 	if (h.substr(0, 1) != '-') {
 99 	    if (h.length % 2 == 1) {
100 		h = '0' + h;
101 	    } else {
102 		if (! h.match(/^[0-7]/)) {
103 		    h = '00' + h;
104 		}
105 	    }
106 	} else {
107 	    var hPos = h.substr(1);
108 	    var xorLen = hPos.length;
109 	    if (xorLen % 2 == 1) {
110 		xorLen += 1;
111 	    } else {
112 		if (! h.match(/^[0-7]/)) {
113 		    xorLen += 2;
114 		}
115 	    }
116 	    var hMask = '';
117 	    for (var i = 0; i < xorLen; i++) {
118 		hMask += 'f';
119 	    }
120 	    var biMask = new BigInteger(hMask, 16);
121 	    var biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE);
122 	    h = biNeg.toString(16).replace(/^-/, '');
123 	}
124 	return h;
125     };
126     /**
127      * get PEM string from hexadecimal data and header string
128      * @name getPEMStringFromHex
129      * @memberOf KJUR.asn1.ASN1Util
130      * @function
131      * @param {String} dataHex hexadecimal string of PEM body
132      * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY')
133      * @return {String} PEM formatted string of input data
134      * @description
135      * @example
136      * var pem  = KJUR.asn1.ASN1Util.getPEMStringFromHex('616161', 'RSA PRIVATE KEY');
137      * // value of pem will be:
138      * -----BEGIN PRIVATE KEY-----
139      * YWFh
140      * -----END PRIVATE KEY-----
141      */
142     this.getPEMStringFromHex = function(dataHex, pemHeader) {
143 	var ns1 = KJUR.asn1;
144 	var dataWA = CryptoJS.enc.Hex.parse(dataHex);
145 	var dataB64 = CryptoJS.enc.Base64.stringify(dataWA);
146 	var pemBody = dataB64.replace(/(.{64})/g, "$1\r\n");
147         pemBody = pemBody.replace(/\r\n$/, '');
148 	return "-----BEGIN " + pemHeader + "-----\r\n" + 
149                pemBody + 
150                "\r\n-----END " + pemHeader + "-----\r\n";
151     };
152 
153     /**
154      * generate ASN1Object specifed by JSON parameters
155      * @name newObject
156      * @memberOf KJUR.asn1.ASN1Util
157      * @function
158      * @param {Array} param JSON parameter to generate ASN1Object
159      * @return {KJUR.asn1.ASN1Object} generated object
160      * @since asn1 1.0.3
161      * @description
162      * generate any ASN1Object specified by JSON param
163      * including ASN.1 primitive or structured.
164      * Generally 'param' can be described as follows:
165      * <blockquote>
166      * {TYPE-OF-ASNOBJ: ASN1OBJ-PARAMETER}
167      * </blockquote>
168      * 'TYPE-OF-ASN1OBJ' can be one of following symbols:
169      * <ul>
170      * <li>'bool' - DERBoolean</li>
171      * <li>'int' - DERInteger</li>
172      * <li>'bitstr' - DERBitString</li>
173      * <li>'octstr' - DEROctetString</li>
174      * <li>'null' - DERNull</li>
175      * <li>'oid' - DERObjectIdentifier</li>
176      * <li>'utf8str' - DERUTF8String</li>
177      * <li>'numstr' - DERNumericString</li>
178      * <li>'prnstr' - DERPrintableString</li>
179      * <li>'telstr' - DERTeletexString</li>
180      * <li>'ia5str' - DERIA5String</li>
181      * <li>'utctime' - DERUTCTime</li>
182      * <li>'gentime' - DERGeneralizedTime</li>
183      * <li>'seq' - DERSequence</li>
184      * <li>'set' - DERSet</li>
185      * <li>'tag' - DERTaggedObject</li>
186      * </ul>
187      * @example
188      * newObject({'prnstr': 'aaa'});
189      * newObject({'seq': [{'int': 3}, {'prnstr': 'aaa'}]})
190      * // ASN.1 Tagged Object
191      * newObject({'tag': {'tag': 'a1', 
192      *                    'explicit': true,
193      *                    'obj': {'seq': [{'int': 3}, {'prnstr': 'aaa'}]}}});
194      * // more simple representation of ASN.1 Tagged Object
195      * newObject({'tag': ['a1',
196      *                    true,
197      *                    {'seq': [
198      *                      {'int': 3}, 
199      *                      {'prnstr': 'aaa'}]}
200      *                   ]});
201      */
202     this.newObject = function(param) {
203 	var ns1 = KJUR.asn1;
204 	var keys = Object.keys(param);
205 	if (keys.length != 1)
206 	    throw "key of param shall be only one.";
207 	var key = keys[0];
208 
209 	if (":bool:int:bitstr:octstr:null:oid:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + key + ":") == -1)
210 	    throw "undefined key: " + key;
211 
212 	if (key == "bool")    return new ns1.DERBoolean(param[key]);
213 	if (key == "int")     return new ns1.DERInteger(param[key]);
214 	if (key == "bitstr")  return new ns1.DERBitString(param[key]);
215 	if (key == "octstr")  return new ns1.DEROctetString(param[key]);
216 	if (key == "null")    return new ns1.DERNull(param[key]);
217 	if (key == "oid")     return new ns1.DERObjectIdentifier(param[key]);
218 	if (key == "utf8str") return new ns1.DERUTF8String(param[key]);
219 	if (key == "numstr")  return new ns1.DERNumericString(param[key]);
220 	if (key == "prnstr")  return new ns1.DERPrintableString(param[key]);
221 	if (key == "telstr")  return new ns1.DERTeletexString(param[key]);
222 	if (key == "ia5str")  return new ns1.DERIA5String(param[key]);
223 	if (key == "utctime") return new ns1.DERUTCTime(param[key]);
224 	if (key == "gentime") return new ns1.DERGeneralizedTime(param[key]);
225 
226 	if (key == "seq") {
227 	    var paramList = param[key];
228 	    var a = [];
229 	    for (var i = 0; i < paramList.length; i++) {
230 		var asn1Obj = ns1.ASN1Util.newObject(paramList[i]);
231 		a.push(asn1Obj);
232 	    }
233 	    return new ns1.DERSequence({'array': a});
234 	}
235 
236 	if (key == "set") {
237 	    var paramList = param[key];
238 	    var a = [];
239 	    for (var i = 0; i < paramList.length; i++) {
240 		var asn1Obj = ns1.ASN1Util.newObject(paramList[i]);
241 		a.push(asn1Obj);
242 	    }
243 	    return new ns1.DERSet({'array': a});
244 	}
245 
246 	if (key == "tag") {
247 	    var tagParam = param[key];
248 	    if (Object.prototype.toString.call(tagParam) === '[object Array]' &&
249 		tagParam.length == 3) {
250 		var obj = ns1.ASN1Util.newObject(tagParam[2]);
251 		return new ns1.DERTaggedObject({tag: tagParam[0], explicit: tagParam[1], obj: obj});
252 	    } else {
253 		var newParam = {};
254 		if (tagParam.explicit !== undefined)
255 		    newParam.explicit = tagParam.explicit;
256 		if (tagParam.tag !== undefined)
257 		    newParam.tag = tagParam.tag;
258 		if (tagParam.obj === undefined)
259 		    throw "obj shall be specified for 'tag'.";
260 		newParam.obj = ns1.ASN1Util.newObject(tagParam.obj);
261 		return new ns1.DERTaggedObject(newParam);
262 	    }
263 	}
264     };
265 
266     /**
267      * get encoded hexadecimal string of ASN1Object specifed by JSON parameters
268      * @name jsonToASN1HEX
269      * @memberOf KJUR.asn1.ASN1Util
270      * @function
271      * @param {Array} param JSON parameter to generate ASN1Object
272      * @return hexadecimal string of ASN1Object
273      * @since asn1 1.0.4
274      * @description
275      * As for ASN.1 object representation of JSON object,
276      * please see {@link newObject}.
277      * @example
278      * jsonToASN1HEX({'prnstr': 'aaa'}); 
279      */
280     this.jsonToASN1HEX = function(param) {
281 	var asn1Obj = this.newObject(param);
282 	return asn1Obj.getEncodedHex();
283     };
284 };
285 
286 // ********************************************************************
287 //  Abstract ASN.1 Classes
288 // ********************************************************************
289 
290 // ********************************************************************
291 
292 /**
293  * base class for ASN.1 DER encoder object
294  * @name KJUR.asn1.ASN1Object
295  * @class base class for ASN.1 DER encoder object
296  * @property {Boolean} isModified flag whether internal data was changed
297  * @property {String} hTLV hexadecimal string of ASN.1 TLV
298  * @property {String} hT hexadecimal string of ASN.1 TLV tag(T)
299  * @property {String} hL hexadecimal string of ASN.1 TLV length(L)
300  * @property {String} hV hexadecimal string of ASN.1 TLV value(V)
301  * @description
302  */
303 KJUR.asn1.ASN1Object = function() {
304     var isModified = true;
305     var hTLV = null;
306     var hT = '00';
307     var hL = '00';
308     var hV = '';
309 
310     /**
311      * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V)
312      * @name getLengthHexFromValue
313      * @memberOf KJUR.asn1.ASN1Object
314      * @function
315      * @return {String} hexadecimal string of ASN.1 TLV length(L)
316      */
317     this.getLengthHexFromValue = function() {
318 	if (typeof this.hV == "undefined" || this.hV == null) {
319 	    throw "this.hV is null or undefined.";
320 	}
321 	if (this.hV.length % 2 == 1) {
322 	    throw "value hex must be even length: n=" + hV.length + ",v=" + this.hV;
323 	}
324 	var n = this.hV.length / 2;
325 	var hN = n.toString(16);
326 	if (hN.length % 2 == 1) {
327 	    hN = "0" + hN;
328 	}
329 	if (n < 128) {
330 	    return hN;
331 	} else {
332 	    var hNlen = hN.length / 2;
333 	    if (hNlen > 15) {
334 		throw "ASN.1 length too long to represent by 8x: n = " + n.toString(16);
335 	    }
336 	    var head = 128 + hNlen;
337 	    return head.toString(16) + hN;
338 	}
339     };
340 
341     /**
342      * get hexadecimal string of ASN.1 TLV bytes
343      * @name getEncodedHex
344      * @memberOf KJUR.asn1.ASN1Object
345      * @function
346      * @return {String} hexadecimal string of ASN.1 TLV
347      */
348     this.getEncodedHex = function() {
349 	if (this.hTLV == null || this.isModified) {
350 	    this.hV = this.getFreshValueHex();
351 	    this.hL = this.getLengthHexFromValue();
352 	    this.hTLV = this.hT + this.hL + this.hV;
353 	    this.isModified = false;
354 	    //alert("first time: " + this.hTLV);
355 	}
356 	return this.hTLV;
357     };
358 
359     /**
360      * get hexadecimal string of ASN.1 TLV value(V) bytes
361      * @name getValueHex
362      * @memberOf KJUR.asn1.ASN1Object
363      * @function
364      * @return {String} hexadecimal string of ASN.1 TLV value(V) bytes
365      */
366     this.getValueHex = function() {
367 	this.getEncodedHex();
368 	return this.hV;
369     }
370 
371     this.getFreshValueHex = function() {
372 	return '';
373     };
374 };
375 
376 // == BEGIN DERAbstractString ================================================
377 /**
378  * base class for ASN.1 DER string classes
379  * @name KJUR.asn1.DERAbstractString
380  * @class base class for ASN.1 DER string classes
381  * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
382  * @property {String} s internal string of value
383  * @extends KJUR.asn1.ASN1Object
384  * @description
385  * <br/>
386  * As for argument 'params' for constructor, you can specify one of
387  * following properties:
388  * <ul>
389  * <li>str - specify initial ASN.1 value(V) by a string</li>
390  * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
391  * </ul>
392  * NOTE: 'params' can be omitted.
393  */
394 KJUR.asn1.DERAbstractString = function(params) {
395     KJUR.asn1.DERAbstractString.superclass.constructor.call(this);
396     var s = null;
397     var hV = null;
398 
399     /**
400      * get string value of this string object
401      * @name getString
402      * @memberOf KJUR.asn1.DERAbstractString
403      * @function
404      * @return {String} string value of this string object
405      */
406     this.getString = function() {
407 	return this.s;
408     };
409 
410     /**
411      * set value by a string
412      * @name setString
413      * @memberOf KJUR.asn1.DERAbstractString
414      * @function
415      * @param {String} newS value by a string to set
416      */
417     this.setString = function(newS) {
418 	this.hTLV = null;
419 	this.isModified = true;
420 	this.s = newS;
421 	this.hV = stohex(this.s);
422     };
423 
424     /**
425      * set value by a hexadecimal string
426      * @name setStringHex
427      * @memberOf KJUR.asn1.DERAbstractString
428      * @function
429      * @param {String} newHexString value by a hexadecimal string to set
430      */
431     this.setStringHex = function(newHexString) {
432 	this.hTLV = null;
433 	this.isModified = true;
434 	this.s = null;
435 	this.hV = newHexString;
436     };
437 
438     this.getFreshValueHex = function() {
439 	return this.hV;
440     };
441 
442     if (typeof params != "undefined") {
443 	if (typeof params == "string") {
444 	    this.setString(params);
445 	} else if (typeof params['str'] != "undefined") {
446 	    this.setString(params['str']);
447 	} else if (typeof params['hex'] != "undefined") {
448 	    this.setStringHex(params['hex']);
449 	}
450     }
451 };
452 YAHOO.lang.extend(KJUR.asn1.DERAbstractString, KJUR.asn1.ASN1Object);
453 // == END   DERAbstractString ================================================
454 
455 // == BEGIN DERAbstractTime ==================================================
456 /**
457  * base class for ASN.1 DER Generalized/UTCTime class
458  * @name KJUR.asn1.DERAbstractTime
459  * @class base class for ASN.1 DER Generalized/UTCTime class
460  * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'})
461  * @extends KJUR.asn1.ASN1Object
462  * @description
463  * @see KJUR.asn1.ASN1Object - superclass
464  */
465 KJUR.asn1.DERAbstractTime = function(params) {
466     KJUR.asn1.DERAbstractTime.superclass.constructor.call(this);
467     var s = null;
468     var date = null;
469 
470     // --- PRIVATE METHODS --------------------
471     this.localDateToUTC = function(d) {
472 	utc = d.getTime() + (d.getTimezoneOffset() * 60000);
473 	var utcDate = new Date(utc);
474 	return utcDate;
475     };
476 
477     this.formatDate = function(dateObject, type) {
478 	var pad = this.zeroPadding;
479 	var d = this.localDateToUTC(dateObject);
480 	var year = String(d.getFullYear());
481 	if (type == 'utc') year = year.substr(2, 2);
482 	var month = pad(String(d.getMonth() + 1), 2);
483 	var day = pad(String(d.getDate()), 2);
484 	var hour = pad(String(d.getHours()), 2);
485 	var min = pad(String(d.getMinutes()), 2);
486 	var sec = pad(String(d.getSeconds()), 2);
487 	return year + month + day + hour + min + sec + 'Z';
488     };
489 
490     this.zeroPadding = function(s, len) {
491 	if (s.length >= len) return s;
492 	return new Array(len - s.length + 1).join('0') + s;
493     };
494 
495     // --- PUBLIC METHODS --------------------
496     /**
497      * get string value of this string object
498      * @name getString
499      * @memberOf KJUR.asn1.DERAbstractTime
500      * @function
501      * @return {String} string value of this time object
502      */
503     this.getString = function() {
504 	return this.s;
505     };
506 
507     /**
508      * set value by a string
509      * @name setString
510      * @memberOf KJUR.asn1.DERAbstractTime
511      * @function
512      * @param {String} newS value by a string to set such like "130430235959Z"
513      */
514     this.setString = function(newS) {
515 	this.hTLV = null;
516 	this.isModified = true;
517 	this.s = newS;
518 	this.hV = stohex(newS);
519     };
520 
521     /**
522      * set value by a Date object
523      * @name setByDateValue
524      * @memberOf KJUR.asn1.DERAbstractTime
525      * @function
526      * @param {Integer} year year of date (ex. 2013)
527      * @param {Integer} month month of date between 1 and 12 (ex. 12)
528      * @param {Integer} day day of month
529      * @param {Integer} hour hours of date
530      * @param {Integer} min minutes of date
531      * @param {Integer} sec seconds of date
532      */
533     this.setByDateValue = function(year, month, day, hour, min, sec) {
534 	var dateObject = new Date(Date.UTC(year, month - 1, day, hour, min, sec, 0));
535 	this.setByDate(dateObject);
536     };
537 
538     this.getFreshValueHex = function() {
539 	return this.hV;
540     };
541 };
542 YAHOO.lang.extend(KJUR.asn1.DERAbstractTime, KJUR.asn1.ASN1Object);
543 // == END   DERAbstractTime ==================================================
544 
545 // == BEGIN DERAbstractStructured ============================================
546 /**
547  * base class for ASN.1 DER structured class
548  * @name KJUR.asn1.DERAbstractStructured
549  * @class base class for ASN.1 DER structured class
550  * @property {Array} asn1Array internal array of ASN1Object
551  * @extends KJUR.asn1.ASN1Object
552  * @description
553  * @see KJUR.asn1.ASN1Object - superclass
554  */
555 KJUR.asn1.DERAbstractStructured = function(params) {
556     KJUR.asn1.DERAbstractString.superclass.constructor.call(this);
557     var asn1Array = null;
558 
559     /**
560      * set value by array of ASN1Object
561      * @name setByASN1ObjectArray
562      * @memberOf KJUR.asn1.DERAbstractStructured
563      * @function
564      * @param {array} asn1ObjectArray array of ASN1Object to set
565      */
566     this.setByASN1ObjectArray = function(asn1ObjectArray) {
567 	this.hTLV = null;
568 	this.isModified = true;
569 	this.asn1Array = asn1ObjectArray;
570     };
571 
572     /**
573      * append an ASN1Object to internal array
574      * @name appendASN1Object
575      * @memberOf KJUR.asn1.DERAbstractStructured
576      * @function
577      * @param {ASN1Object} asn1Object to add
578      */
579     this.appendASN1Object = function(asn1Object) {
580 	this.hTLV = null;
581 	this.isModified = true;
582 	this.asn1Array.push(asn1Object);
583     };
584 
585     this.asn1Array = new Array();
586     if (typeof params != "undefined") {
587 	if (typeof params['array'] != "undefined") {
588 	    this.asn1Array = params['array'];
589 	}
590     }
591 };
592 YAHOO.lang.extend(KJUR.asn1.DERAbstractStructured, KJUR.asn1.ASN1Object);
593 
594 
595 // ********************************************************************
596 //  ASN.1 Object Classes
597 // ********************************************************************
598 
599 // ********************************************************************
600 /**
601  * class for ASN.1 DER Boolean
602  * @name KJUR.asn1.DERBoolean
603  * @class class for ASN.1 DER Boolean
604  * @extends KJUR.asn1.ASN1Object
605  * @description
606  * @see KJUR.asn1.ASN1Object - superclass
607  */
608 KJUR.asn1.DERBoolean = function() {
609     KJUR.asn1.DERBoolean.superclass.constructor.call(this);
610     this.hT = "01";
611     this.hTLV = "0101ff";
612 };
613 YAHOO.lang.extend(KJUR.asn1.DERBoolean, KJUR.asn1.ASN1Object);
614 
615 // ********************************************************************
616 /**
617  * class for ASN.1 DER Integer
618  * @name KJUR.asn1.DERInteger
619  * @class class for ASN.1 DER Integer
620  * @extends KJUR.asn1.ASN1Object
621  * @description
622  * <br/>
623  * As for argument 'params' for constructor, you can specify one of
624  * following properties:
625  * <ul>
626  * <li>int - specify initial ASN.1 value(V) by integer value</li>
627  * <li>bigint - specify initial ASN.1 value(V) by BigInteger object</li>
628  * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
629  * </ul>
630  * NOTE: 'params' can be omitted.
631  */
632 KJUR.asn1.DERInteger = function(params) {
633     KJUR.asn1.DERInteger.superclass.constructor.call(this);
634     this.hT = "02";
635 
636     /**
637      * set value by Tom Wu's BigInteger object
638      * @name setByBigInteger
639      * @memberOf KJUR.asn1.DERInteger
640      * @function
641      * @param {BigInteger} bigIntegerValue to set
642      */
643     this.setByBigInteger = function(bigIntegerValue) {
644 	this.hTLV = null;
645 	this.isModified = true;
646 	this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue);
647     };
648 
649     /**
650      * set value by integer value
651      * @name setByInteger
652      * @memberOf KJUR.asn1.DERInteger
653      * @function
654      * @param {Integer} integer value to set
655      */
656     this.setByInteger = function(intValue) {
657 	var bi = new BigInteger(String(intValue), 10);
658 	this.setByBigInteger(bi);
659     };
660 
661     /**
662      * set value by integer value
663      * @name setValueHex
664      * @memberOf KJUR.asn1.DERInteger
665      * @function
666      * @param {String} hexadecimal string of integer value
667      * @description
668      * <br/>
669      * NOTE: Value shall be represented by minimum octet length of
670      * two's complement representation.
671      * @example
672      * new KJUR.asn1.DERInteger(123);
673      * new KJUR.asn1.DERInteger({'int': 123});
674      * new KJUR.asn1.DERInteger({'hex': '1fad'});
675      */
676     this.setValueHex = function(newHexString) {
677 	this.hV = newHexString;
678     };
679 
680     this.getFreshValueHex = function() {
681 	return this.hV;
682     };
683 
684     if (typeof params != "undefined") {
685 	if (typeof params['bigint'] != "undefined") {
686 	    this.setByBigInteger(params['bigint']);
687 	} else if (typeof params['int'] != "undefined") {
688 	    this.setByInteger(params['int']);
689 	} else if (typeof params == "number") {
690 	    this.setByInteger(params);
691 	} else if (typeof params['hex'] != "undefined") {
692 	    this.setValueHex(params['hex']);
693 	}
694     }
695 };
696 YAHOO.lang.extend(KJUR.asn1.DERInteger, KJUR.asn1.ASN1Object);
697 
698 // ********************************************************************
699 /**
700  * class for ASN.1 DER encoded BitString primitive
701  * @name KJUR.asn1.DERBitString
702  * @class class for ASN.1 DER encoded BitString primitive
703  * @extends KJUR.asn1.ASN1Object
704  * @description 
705  * <br/>
706  * As for argument 'params' for constructor, you can specify one of
707  * following properties:
708  * <ul>
709  * <li>bin - specify binary string (ex. '10111')</li>
710  * <li>array - specify array of boolean (ex. [true,false,true,true])</li>
711  * <li>hex - specify hexadecimal string of ASN.1 value(V) including unused bits</li>
712  * </ul>
713  * NOTE: 'params' can be omitted.
714  */
715 KJUR.asn1.DERBitString = function(params) {
716     KJUR.asn1.DERBitString.superclass.constructor.call(this);
717     this.hT = "03";
718 
719     /**
720      * set ASN.1 value(V) by a hexadecimal string including unused bits
721      * @name setHexValueIncludingUnusedBits
722      * @memberOf KJUR.asn1.DERBitString
723      * @function
724      * @param {String} newHexStringIncludingUnusedBits
725      */
726     this.setHexValueIncludingUnusedBits = function(newHexStringIncludingUnusedBits) {
727 	this.hTLV = null;
728 	this.isModified = true;
729 	this.hV = newHexStringIncludingUnusedBits;
730     };
731 
732     /**
733      * set ASN.1 value(V) by unused bit and hexadecimal string of value
734      * @name setUnusedBitsAndHexValue
735      * @memberOf KJUR.asn1.DERBitString
736      * @function
737      * @param {Integer} unusedBits
738      * @param {String} hValue
739      */
740     this.setUnusedBitsAndHexValue = function(unusedBits, hValue) {
741 	if (unusedBits < 0 || 7 < unusedBits) {
742 	    throw "unused bits shall be from 0 to 7: u = " + unusedBits;
743 	}
744 	var hUnusedBits = "0" + unusedBits;
745 	this.hTLV = null;
746 	this.isModified = true;
747 	this.hV = hUnusedBits + hValue;
748     };
749 
750     /**
751      * set ASN.1 DER BitString by binary string
752      * @name setByBinaryString
753      * @memberOf KJUR.asn1.DERBitString
754      * @function
755      * @param {String} binaryString binary value string (i.e. '10111')
756      * @description
757      * Its unused bits will be calculated automatically by length of 
758      * 'binaryValue'. <br/>
759      * NOTE: Trailing zeros '0' will be ignored.
760      */
761     this.setByBinaryString = function(binaryString) {
762 	binaryString = binaryString.replace(/0+$/, '');
763 	var unusedBits = 8 - binaryString.length % 8;
764 	if (unusedBits == 8) unusedBits = 0;
765 	for (var i = 0; i <= unusedBits; i++) {
766 	    binaryString += '0';
767 	}
768 	var h = '';
769 	for (var i = 0; i < binaryString.length - 1; i += 8) {
770 	    var b = binaryString.substr(i, 8);
771 	    var x = parseInt(b, 2).toString(16);
772 	    if (x.length == 1) x = '0' + x;
773 	    h += x;  
774 	}
775 	this.hTLV = null;
776 	this.isModified = true;
777 	this.hV = '0' + unusedBits + h;
778     };
779 
780     /**
781      * set ASN.1 TLV value(V) by an array of boolean
782      * @name setByBooleanArray
783      * @memberOf KJUR.asn1.DERBitString
784      * @function
785      * @param {array} booleanArray array of boolean (ex. [true, false, true])
786      * @description
787      * NOTE: Trailing falses will be ignored.
788      */
789     this.setByBooleanArray = function(booleanArray) {
790 	var s = '';
791 	for (var i = 0; i < booleanArray.length; i++) {
792 	    if (booleanArray[i] == true) {
793 		s += '1';
794 	    } else {
795 		s += '0';
796 	    }
797 	}
798 	this.setByBinaryString(s);
799     };
800 
801     /**
802      * generate an array of false with specified length
803      * @name newFalseArray
804      * @memberOf KJUR.asn1.DERBitString
805      * @function
806      * @param {Integer} nLength length of array to generate
807      * @return {array} array of boolean faluse
808      * @description
809      * This static method may be useful to initialize boolean array.
810      */
811     this.newFalseArray = function(nLength) {
812 	var a = new Array(nLength);
813 	for (var i = 0; i < nLength; i++) {
814 	    a[i] = false;
815 	}
816 	return a;
817     };
818 
819     this.getFreshValueHex = function() {
820 	return this.hV;
821     };
822 
823     if (typeof params != "undefined") {
824 	if (typeof params == "string" && params.toLowerCase().match(/^[0-9a-f]+$/)) {
825 	    this.setHexValueIncludingUnusedBits(params);
826         } else if (typeof params['hex'] != "undefined") {
827 	    this.setHexValueIncludingUnusedBits(params['hex']);
828 	} else if (typeof params['bin'] != "undefined") {
829 	    this.setByBinaryString(params['bin']);
830 	} else if (typeof params['array'] != "undefined") {
831 	    this.setByBooleanArray(params['array']);
832 	}
833     }
834 };
835 YAHOO.lang.extend(KJUR.asn1.DERBitString, KJUR.asn1.ASN1Object);
836 
837 // ********************************************************************
838 /**
839  * class for ASN.1 DER OctetString
840  * @name KJUR.asn1.DEROctetString
841  * @class class for ASN.1 DER OctetString
842  * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
843  * @extends KJUR.asn1.DERAbstractString
844  * @description
845  * @see KJUR.asn1.DERAbstractString - superclass
846  */
847 KJUR.asn1.DEROctetString = function(params) {
848     KJUR.asn1.DEROctetString.superclass.constructor.call(this, params);
849     this.hT = "04";
850 };
851 YAHOO.lang.extend(KJUR.asn1.DEROctetString, KJUR.asn1.DERAbstractString);
852 
853 // ********************************************************************
854 /**
855  * class for ASN.1 DER Null
856  * @name KJUR.asn1.DERNull
857  * @class class for ASN.1 DER Null
858  * @extends KJUR.asn1.ASN1Object
859  * @description
860  * @see KJUR.asn1.ASN1Object - superclass
861  */
862 KJUR.asn1.DERNull = function() {
863     KJUR.asn1.DERNull.superclass.constructor.call(this);
864     this.hT = "05";
865     this.hTLV = "0500";
866 };
867 YAHOO.lang.extend(KJUR.asn1.DERNull, KJUR.asn1.ASN1Object);
868 
869 // ********************************************************************
870 /**
871  * class for ASN.1 DER ObjectIdentifier
872  * @name KJUR.asn1.DERObjectIdentifier
873  * @class class for ASN.1 DER ObjectIdentifier
874  * @param {Array} params associative array of parameters (ex. {'oid': '2.5.4.5'})
875  * @extends KJUR.asn1.ASN1Object
876  * @description
877  * <br/>
878  * As for argument 'params' for constructor, you can specify one of
879  * following properties:
880  * <ul>
881  * <li>oid - specify initial ASN.1 value(V) by a oid string (ex. 2.5.4.13)</li>
882  * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
883  * </ul>
884  * NOTE: 'params' can be omitted.
885  */
886 KJUR.asn1.DERObjectIdentifier = function(params) {
887     var itox = function(i) {
888 	var h = i.toString(16);
889 	if (h.length == 1) h = '0' + h;
890 	return h;
891     };
892     var roidtox = function(roid) {
893 	var h = '';
894 	var bi = new BigInteger(roid, 10);
895 	var b = bi.toString(2);
896 	var padLen = 7 - b.length % 7;
897 	if (padLen == 7) padLen = 0;
898 	var bPad = '';
899 	for (var i = 0; i < padLen; i++) bPad += '0';
900 	b = bPad + b;
901 	for (var i = 0; i < b.length - 1; i += 7) {
902 	    var b8 = b.substr(i, 7);
903 	    if (i != b.length - 7) b8 = '1' + b8;
904 	    h += itox(parseInt(b8, 2));
905 	}
906 	return h;
907     }
908 
909     KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this);
910     this.hT = "06";
911 
912     /**
913      * set value by a hexadecimal string
914      * @name setValueHex
915      * @memberOf KJUR.asn1.DERObjectIdentifier
916      * @function
917      * @param {String} newHexString hexadecimal value of OID bytes
918      */
919     this.setValueHex = function(newHexString) {
920 	this.hTLV = null;
921 	this.isModified = true;
922 	this.s = null;
923 	this.hV = newHexString;
924     };
925 
926     /**
927      * set value by a OID string
928      * @name setValueOidString
929      * @memberOf KJUR.asn1.DERObjectIdentifier
930      * @function
931      * @param {String} oidString OID string (ex. 2.5.4.13)
932      */
933     this.setValueOidString = function(oidString) {
934 	if (! oidString.match(/^[0-9.]+$/)) {
935 	    throw "malformed oid string: " + oidString;
936 	}
937 	var h = '';
938 	var a = oidString.split('.');
939 	var i0 = parseInt(a[0]) * 40 + parseInt(a[1]);
940 	h += itox(i0);
941 	a.splice(0, 2);
942 	for (var i = 0; i < a.length; i++) {
943 	    h += roidtox(a[i]);
944 	}
945 	this.hTLV = null;
946 	this.isModified = true;
947 	this.s = null;
948 	this.hV = h;
949     };
950 
951     /**
952      * set value by a OID name
953      * @name setValueName
954      * @memberOf KJUR.asn1.DERObjectIdentifier
955      * @function
956      * @param {String} oidName OID name (ex. 'serverAuth')
957      * @since 1.0.1
958      * @description
959      * OID name shall be defined in 'KJUR.asn1.x509.OID.name2oidList'.
960      * Otherwise raise error.
961      */
962     this.setValueName = function(oidName) {
963 	if (typeof KJUR.asn1.x509.OID.name2oidList[oidName] != "undefined") {
964 	    var oid = KJUR.asn1.x509.OID.name2oidList[oidName];
965 	    this.setValueOidString(oid);
966 	} else {
967 	    throw "DERObjectIdentifier oidName undefined: " + oidName;
968 	}
969     };
970 
971     this.getFreshValueHex = function() {
972 	return this.hV;
973     };
974 
975     if (typeof params != "undefined") {
976 	if (typeof params == "string" && params.match(/^[0-2].[0-9.]+$/)) {
977 	    this.setValueOidString(params);
978 	} else if (KJUR.asn1.x509.OID.name2oidList[params] !== undefined) {
979 	    this.setValueOidString(KJUR.asn1.x509.OID.name2oidList[params]);
980 	} else if (typeof params['oid'] != "undefined") {
981 	    this.setValueOidString(params['oid']);
982 	} else if (typeof params['hex'] != "undefined") {
983 	    this.setValueHex(params['hex']);
984 	} else if (typeof params['name'] != "undefined") {
985 	    this.setValueName(params['name']);
986 	}
987     }
988 };
989 YAHOO.lang.extend(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object);
990 
991 // ********************************************************************
992 /**
993  * class for ASN.1 DER UTF8String
994  * @name KJUR.asn1.DERUTF8String
995  * @class class for ASN.1 DER UTF8String
996  * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
997  * @extends KJUR.asn1.DERAbstractString
998  * @description
999  * @see KJUR.asn1.DERAbstractString - superclass
1000  */
1001 KJUR.asn1.DERUTF8String = function(params) {
1002     KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params);
1003     this.hT = "0c";
1004 };
1005 YAHOO.lang.extend(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString);
1006 
1007 // ********************************************************************
1008 /**
1009  * class for ASN.1 DER NumericString
1010  * @name KJUR.asn1.DERNumericString
1011  * @class class for ASN.1 DER NumericString
1012  * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
1013  * @extends KJUR.asn1.DERAbstractString
1014  * @description
1015  * @see KJUR.asn1.DERAbstractString - superclass
1016  */
1017 KJUR.asn1.DERNumericString = function(params) {
1018     KJUR.asn1.DERNumericString.superclass.constructor.call(this, params);
1019     this.hT = "12";
1020 };
1021 YAHOO.lang.extend(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString);
1022 
1023 // ********************************************************************
1024 /**
1025  * class for ASN.1 DER PrintableString
1026  * @name KJUR.asn1.DERPrintableString
1027  * @class class for ASN.1 DER PrintableString
1028  * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
1029  * @extends KJUR.asn1.DERAbstractString
1030  * @description
1031  * @see KJUR.asn1.DERAbstractString - superclass
1032  */
1033 KJUR.asn1.DERPrintableString = function(params) {
1034     KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params);
1035     this.hT = "13";
1036 };
1037 YAHOO.lang.extend(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString);
1038 
1039 // ********************************************************************
1040 /**
1041  * class for ASN.1 DER TeletexString
1042  * @name KJUR.asn1.DERTeletexString
1043  * @class class for ASN.1 DER TeletexString
1044  * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
1045  * @extends KJUR.asn1.DERAbstractString
1046  * @description
1047  * @see KJUR.asn1.DERAbstractString - superclass
1048  */
1049 KJUR.asn1.DERTeletexString = function(params) {
1050     KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params);
1051     this.hT = "14";
1052 };
1053 YAHOO.lang.extend(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString);
1054 
1055 // ********************************************************************
1056 /**
1057  * class for ASN.1 DER IA5String
1058  * @name KJUR.asn1.DERIA5String
1059  * @class class for ASN.1 DER IA5String
1060  * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
1061  * @extends KJUR.asn1.DERAbstractString
1062  * @description
1063  * @see KJUR.asn1.DERAbstractString - superclass
1064  */
1065 KJUR.asn1.DERIA5String = function(params) {
1066     KJUR.asn1.DERIA5String.superclass.constructor.call(this, params);
1067     this.hT = "16";
1068 };
1069 YAHOO.lang.extend(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString);
1070 
1071 // ********************************************************************
1072 /**
1073  * class for ASN.1 DER UTCTime
1074  * @name KJUR.asn1.DERUTCTime
1075  * @class class for ASN.1 DER UTCTime
1076  * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'})
1077  * @extends KJUR.asn1.DERAbstractTime
1078  * @description
1079  * <br/>
1080  * As for argument 'params' for constructor, you can specify one of
1081  * following properties:
1082  * <ul>
1083  * <li>str - specify initial ASN.1 value(V) by a string (ex.'130430235959Z')</li>
1084  * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
1085  * <li>date - specify Date object.</li>
1086  * </ul>
1087  * NOTE: 'params' can be omitted.
1088  * <h4>EXAMPLES</h4>
1089  * @example
1090  * var d1 = new KJUR.asn1.DERUTCTime();
1091  * d1.setString('130430125959Z');
1092  *
1093  * var d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'});
1094  * var d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))});
1095  * var d4 = new KJUR.asn1.DERUTCTime('130430125959Z');
1096  */
1097 KJUR.asn1.DERUTCTime = function(params) {
1098     KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params);
1099     this.hT = "17";
1100 
1101     /**
1102      * set value by a Date object
1103      * @name setByDate
1104      * @memberOf KJUR.asn1.DERUTCTime
1105      * @function
1106      * @param {Date} dateObject Date object to set ASN.1 value(V)
1107      */
1108     this.setByDate = function(dateObject) {
1109 	this.hTLV = null;
1110 	this.isModified = true;
1111 	this.date = dateObject;
1112 	this.s = this.formatDate(this.date, 'utc');
1113 	this.hV = stohex(this.s);
1114     };
1115 
1116     if (typeof params != "undefined") {
1117 	if (typeof params['str'] != "undefined") {
1118 	    this.setString(params['str']);
1119 	} else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) {
1120 	    this.setString(params);
1121 	} else if (typeof params['hex'] != "undefined") {
1122 	    this.setStringHex(params['hex']);
1123 	} else if (typeof params['date'] != "undefined") {
1124 	    this.setByDate(params['date']);
1125 	}
1126     }
1127 };
1128 YAHOO.lang.extend(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime);
1129 
1130 // ********************************************************************
1131 /**
1132  * class for ASN.1 DER GeneralizedTime
1133  * @name KJUR.asn1.DERGeneralizedTime
1134  * @class class for ASN.1 DER GeneralizedTime
1135  * @param {Array} params associative array of parameters (ex. {'str': '20130430235959Z'})
1136  * @extends KJUR.asn1.DERAbstractTime
1137  * @description
1138  * <br/>
1139  * As for argument 'params' for constructor, you can specify one of
1140  * following properties:
1141  * <ul>
1142  * <li>str - specify initial ASN.1 value(V) by a string (ex.'20130430235959Z')</li>
1143  * <li>hex - specify initial ASN.1 value(V) by a hexadecimal string</li>
1144  * <li>date - specify Date object.</li>
1145  * </ul>
1146  * NOTE: 'params' can be omitted.
1147  */
1148 KJUR.asn1.DERGeneralizedTime = function(params) {
1149     KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params);
1150     this.hT = "18";
1151 
1152     /**
1153      * set value by a Date object
1154      * @name setByDate
1155      * @memberOf KJUR.asn1.DERGeneralizedTime
1156      * @function
1157      * @param {Date} dateObject Date object to set ASN.1 value(V)
1158      * @example
1159      * When you specify UTC time, use 'Date.UTC' method like this:<br/>
1160      * var o = new DERUTCTime();
1161      * var date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59
1162      * o.setByDate(date);
1163      */
1164     this.setByDate = function(dateObject) {
1165 	this.hTLV = null;
1166 	this.isModified = true;
1167 	this.date = dateObject;
1168 	this.s = this.formatDate(this.date, 'gen');
1169 	this.hV = stohex(this.s);
1170     };
1171 
1172     if (typeof params != "undefined") {
1173 	if (typeof params['str'] != "undefined") {
1174 	    this.setString(params['str']);
1175 	} else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) {
1176 	    this.setString(params);
1177 	} else if (typeof params['hex'] != "undefined") {
1178 	    this.setStringHex(params['hex']);
1179 	} else if (typeof params['date'] != "undefined") {
1180 	    this.setByDate(params['date']);
1181 	}
1182     }
1183 };
1184 YAHOO.lang.extend(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime);
1185 
1186 // ********************************************************************
1187 /**
1188  * class for ASN.1 DER Sequence
1189  * @name KJUR.asn1.DERSequence
1190  * @class class for ASN.1 DER Sequence
1191  * @extends KJUR.asn1.DERAbstractStructured
1192  * @description
1193  * <br/>
1194  * As for argument 'params' for constructor, you can specify one of
1195  * following properties:
1196  * <ul>
1197  * <li>array - specify array of ASN1Object to set elements of content</li>
1198  * </ul>
1199  * NOTE: 'params' can be omitted.
1200  */
1201 KJUR.asn1.DERSequence = function(params) {
1202     KJUR.asn1.DERSequence.superclass.constructor.call(this, params);
1203     this.hT = "30";
1204     this.getFreshValueHex = function() {
1205 	var h = '';
1206 	for (var i = 0; i < this.asn1Array.length; i++) {
1207 	    var asn1Obj = this.asn1Array[i];
1208 	    h += asn1Obj.getEncodedHex();
1209 	}
1210 	this.hV = h;
1211 	return this.hV;
1212     };
1213 };
1214 YAHOO.lang.extend(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured);
1215 
1216 // ********************************************************************
1217 /**
1218  * class for ASN.1 DER Set
1219  * @name KJUR.asn1.DERSet
1220  * @class class for ASN.1 DER Set
1221  * @extends KJUR.asn1.DERAbstractStructured
1222  * @description
1223  * <br/>
1224  * As for argument 'params' for constructor, you can specify one of
1225  * following properties:
1226  * <ul>
1227  * <li>array - specify array of ASN1Object to set elements of content</li>
1228  * </ul>
1229  * NOTE: 'params' can be omitted.
1230  */
1231 KJUR.asn1.DERSet = function(params) {
1232     KJUR.asn1.DERSet.superclass.constructor.call(this, params);
1233     this.hT = "31";
1234     this.getFreshValueHex = function() {
1235 	var a = new Array();
1236 	for (var i = 0; i < this.asn1Array.length; i++) {
1237 	    var asn1Obj = this.asn1Array[i];
1238 	    a.push(asn1Obj.getEncodedHex());
1239 	}
1240 	a.sort();
1241 	this.hV = a.join('');
1242 	return this.hV;
1243     };
1244 };
1245 YAHOO.lang.extend(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured);
1246 
1247 // ********************************************************************
1248 /**
1249  * class for ASN.1 DER TaggedObject
1250  * @name KJUR.asn1.DERTaggedObject
1251  * @class class for ASN.1 DER TaggedObject
1252  * @extends KJUR.asn1.ASN1Object
1253  * @description
1254  * <br/>
1255  * Parameter 'tagNoNex' is ASN.1 tag(T) value for this object.
1256  * For example, if you find '[1]' tag in a ASN.1 dump, 
1257  * 'tagNoHex' will be 'a1'.
1258  * <br/>
1259  * As for optional argument 'params' for constructor, you can specify *ANY* of
1260  * following properties:
1261  * <ul>
1262  * <li>explicit - specify true if this is explicit tag otherwise false 
1263  *     (default is 'true').</li>
1264  * <li>tag - specify tag (default is 'a0' which means [0])</li>
1265  * <li>obj - specify ASN1Object which is tagged</li>
1266  * </ul>
1267  * @example
1268  * d1 = new KJUR.asn1.DERUTF8String({'str':'a'});
1269  * d2 = new KJUR.asn1.DERTaggedObject({'obj': d1});
1270  * hex = d2.getEncodedHex();
1271  */
1272 KJUR.asn1.DERTaggedObject = function(params) {
1273     KJUR.asn1.DERTaggedObject.superclass.constructor.call(this);
1274     this.hT = "a0";
1275     this.hV = '';
1276     this.isExplicit = true;
1277     this.asn1Object = null;
1278 
1279     /**
1280      * set value by an ASN1Object
1281      * @name setString
1282      * @memberOf KJUR.asn1.DERTaggedObject
1283      * @function
1284      * @param {Boolean} isExplicitFlag flag for explicit/implicit tag
1285      * @param {Integer} tagNoHex hexadecimal string of ASN.1 tag
1286      * @param {ASN1Object} asn1Object ASN.1 to encapsulate
1287      */
1288     this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) {
1289 	this.hT = tagNoHex;
1290 	this.isExplicit = isExplicitFlag;
1291 	this.asn1Object = asn1Object;
1292 	if (this.isExplicit) {
1293 	    this.hV = this.asn1Object.getEncodedHex();
1294 	    this.hTLV = null;
1295 	    this.isModified = true;
1296 	} else {
1297 	    this.hV = null;
1298 	    this.hTLV = asn1Object.getEncodedHex();
1299 	    this.hTLV = this.hTLV.replace(/^../, tagNoHex);
1300 	    this.isModified = false;
1301 	}
1302     };
1303 
1304     this.getFreshValueHex = function() {
1305 	return this.hV;
1306     };
1307 
1308     if (typeof params != "undefined") {
1309 	if (typeof params['tag'] != "undefined") {
1310 	    this.hT = params['tag'];
1311 	}
1312 	if (typeof params['explicit'] != "undefined") {
1313 	    this.isExplicit = params['explicit'];
1314 	}
1315 	if (typeof params['obj'] != "undefined") {
1316 	    this.asn1Object = params['obj'];
1317 	    this.setASN1Object(this.isExplicit, this.hT, this.asn1Object);
1318 	}
1319     }
1320 };
1321 YAHOO.lang.extend(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object);
1322