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