1 /* x509-2.0.3.js (c) 2012-2020 Kenji Urushima | kjur.github.io/jsrsasign/license
  2  */
  3 /*
  4  * x509.js - X509 class to read subject public key from certificate.
  5  *
  6  * Copyright (c) 2010-2020 Kenji Urushima (kenji.urushima@gmail.com)
  7  *
  8  * This software is licensed under the terms of the MIT License.
  9  * https://kjur.github.io/jsrsasign/license
 10  *
 11  * The above copyright and license notice shall be
 12  * included in all copies or substantial portions of the Software.
 13  */
 14 
 15 /**
 16  * @fileOverview
 17  * @name x509-1.1.js
 18  * @author Kenji Urushima kenji.urushima@gmail.com
 19  * @version jsrsasign 9.1.6 x509 2.0.3 (2020-Sep-04)
 20  * @since jsrsasign 1.x.x
 21  * @license <a href="https://kjur.github.io/jsrsasign/license/">MIT License</a>
 22  */
 23 
 24 /**
 25  * hexadecimal X.509 certificate ASN.1 parser class.<br/>
 26  * @class hexadecimal X.509 certificate ASN.1 parser class
 27  * @property {String} hex hexacedimal string for X.509 certificate.
 28  * @property {Number} version format version (1: X509v1, 3: X509v3, otherwise: unknown) since jsrsasign 7.1.4
 29  * @property {Array} aExtInfo (DEPRECATED) array of parameters for extensions
 30  * @author Kenji Urushima
 31  * @version 1.0.1 (08 May 2012)
 32  * @see <a href="https://kjur.github.io/jsrsasigns/">'jsrsasign'(RSA Sign JavaScript Library) home page https://kjur.github.io/jsrsasign/</a>
 33  * @description
 34  * X509 class provides following functionality:
 35  * <ul>
 36  * <li>parse X.509 certificate ASN.1 structure</li>
 37  * <li>get basic fields, extensions, signature algorithms and signature values</li>
 38  * <li>read PEM certificate</li>
 39  * </ul>
 40  *
 41  * <ul>
 42  * <li><b>TO GET FIELDS</b>
 43  *   <ul>
 44  *   <li>serial - {@link X509#getSerialNumberHex}</li>
 45  *   <li>signature algorithm field - {@link X509#getSignatureAlgorithmField}</li>
 46  *   <li>issuer - {@link X509#getIssuerHex}</li>
 47  *   <li>issuer - {@link X509#getIssuerString}</li>
 48  *   <li>notBefore - {@link X509#getNotBefore}</li>
 49  *   <li>notAfter - {@link X509#getNotAfter}</li>
 50  *   <li>subject - {@link X509#getSubjectHex}</li>
 51  *   <li>subject - {@link X509#getSubjectString}</li>
 52  *   <li>subjectPublicKeyInfo - {@link X509#getPublicKey}</li>
 53  *   <li>subjectPublicKeyInfo - {@link X509#getPublicKeyHex}</li>
 54  *   <li>subjectPublicKeyInfo - {@link X509#getPublicKeyIdx}</li>
 55  *   <li>subjectPublicKeyInfo - {@link X509.getPublicKeyFromCertPEM}</li>
 56  *   <li>subjectPublicKeyInfo - {@link X509.getPublicKeyFromCertHex}</li>
 57  *   <li>subjectPublicKeyInfo - {@link X509#getPublicKeyContentIdx}</li>
 58  *   <li>signature algorithm - {@link X509#getSignatureAlgorithmName}</li>
 59  *   <li>signature value - {@link X509#getSignatureValueHex}</li>
 60  *   </ul>
 61  * </li>
 62  * <li><b>X509 METHODS TO GET EXTENSIONS</b>
 63  *   <ul>
 64  *   <li>authorityKeyIdentifier - {@link X509#getExtAuthorityKeyIdentifier}</li>
 65  *   <li>subjectKeyIdentifier - {@link X509#getExtSubjectKeyIdentifier}</li>
 66  *   <li>keyUsage - {@link X509#getExtKeyUsage}</li>
 67  *   <li>keyUsage - {@link X509#getExtKeyUsageBin}</li>
 68  *   <li>keyUsage - {@link X509#getExtKeyUsageString}</li>
 69  *   <li>certificatePolicies - {@link X509#getExtCertificatePolicies}</li>
 70  *   <li>subjectAltName - {@link X509#getExtSubjectAltName}</li>
 71  *   <li>subjectAltName2 - {@link X509#getExtSubjectAltName2} (DEPRECATED)</li>
 72  *   <li>issuerAltName - {@link X509#getExtIssuerAltName}</li>
 73  *   <li>basicConstraints - {@link X509#getExtBasicConstraints}</li>
 74  *   <li>extKeyUsage - {@link X509#getExtExtKeyUsage}</li>
 75  *   <li>extKeyUsage - {@link X509#getExtExtKeyUsageName} (DEPRECATED)</li>
 76  *   <li>cRLDistributionPoints - {@link X509#getExtCRLDistributionPoints}</li>
 77  *   <li>cRLDistributionPoints - {@link X509#getExtCRLDistributionPointsURI} (DEPRECATED)</li>
 78  *   <li>authorityInfoAccess - {@link X509#getExtAuthorityInfoAccess}</li>
 79  *   <li>authorityInfoAccess - {@link X509#getExtAIAInfo} (DEPRECATED)</li>
 80  *   <li>cRLNumber - {@link X509#getExtCRLNumber}</li>
 81  *   <li>cRLReason - {@link X509#getExtCRLReason}</li>
 82  *   <li>ocspNonce - {@link X509#getExtOCSPNonce}</li>
 83  *   <li>ocspNoCheck - {@link X509#getExtOCSPNoCheck}</li>
 84  *   </ul>
 85  * </li>
 86  * <li><b>UTILITIES</b>
 87  *   <ul>
 88  *   <li>reading PEM X.509 certificate - {@link X509#readCertPEM}</li>
 89  *   <li>reading hexadecimal string of X.509 certificate - {@link X509#readCertHex}</li>
 90  *   <li>get all certificate information - {@link X509#getInfo}</li>
 91  *   <li>get specified extension information - {@link X509#getExtInfo}</li>
 92  *   <li>verify signature value - {@link X509#verifySignature}</li>
 93  *   </ul>
 94  * </li>
 95  * </ul>
 96  */
 97 function X509() {
 98     var _ASN1HEX = ASN1HEX,
 99 	_getChildIdx = _ASN1HEX.getChildIdx,
100 	_getV = _ASN1HEX.getV,
101 	_getTLV = _ASN1HEX.getTLV,
102 	_getVbyList = _ASN1HEX.getVbyList,
103 	_getVbyListEx = _ASN1HEX.getVbyListEx,
104 	_getTLVbyList = _ASN1HEX.getTLVbyList,
105 	_getTLVbyListEx = _ASN1HEX.getTLVbyListEx,
106 	_getIdxbyList = _ASN1HEX.getIdxbyList,
107 	_getIdxbyListEx = _ASN1HEX.getIdxbyListEx,
108 	_getVidx = _ASN1HEX.getVidx,
109 	_oidname = _ASN1HEX.oidname,
110 	_hextooidstr = _ASN1HEX.hextooidstr,
111 	_X509 = X509,
112 	_pemtohex = pemtohex,
113 	_PSSNAME2ASN1TLV;
114 
115     try {
116 	_PSSNAME2ASN1TLV = KJUR.asn1.x509.AlgorithmIdentifier.PSSNAME2ASN1TLV;
117     } catch (ex) {};
118     this.HEX2STAG = {"0c": "utf8", "13": "prn", "16": "ia5",
119 		     "1a": "vis" , "1e": "bmp"};
120 
121     this.hex = null;
122     this.version = 0; // version (1: X509v1, 3: X509v3, others: unspecified)
123     this.foffset = 0; // field index offset (-1: for X509v1, 0: for X509v3)
124     this.aExtInfo = null;
125 
126     // ===== get basic fields from hex =====================================
127 
128     /**
129      * get format version (X.509v1 or v3 certificate)<br/>
130      * @name getVersion
131      * @memberOf X509#
132      * @function
133      * @return {Number} 1 for X509v1, 3 for X509v3, otherwise 0
134      * @since jsrsasign 7.1.14 x509 1.1.13
135      * @description
136      * This method returns a format version of X.509 certificate.
137      * It returns 1 for X.509v1 certificate and 3 for v3 certificate.
138      * Otherwise returns 0.
139      * This method will be automatically called in
140      * {@link X509#readCertPEM}. After then, you can use
141      * {@link X509.version} parameter.
142      * @example
143      * var x = new X509();
144      * x.readCertPEM(sCertPEM);
145      * version = x.getVersion();    // 1 or 3
146      * sn = x.getSerialNumberHex(); // return string like "01ad..."
147      */
148     this.getVersion = function() {
149 	if (this.hex === null || this.version !== 0) return this.version;
150 
151 	// check if the first item of tbsCertificate "[0] { INTEGER 2 }"
152 	if (_getTLVbyList(this.hex, 0, [0, 0]) !==
153 	    "a003020102") {
154 	    this.version = 1;
155 	    this.foffset = -1;
156 	    return 1;
157 	}
158 
159 	this.version = 3;
160 	return 3;
161     };
162 
163     /**
164      * get hexadecimal string of serialNumber field of certificate.<br/>
165      * @name getSerialNumberHex
166      * @memberOf X509#
167      * @function
168      * @return {String} hexadecimal string of certificate serial number
169      * @example
170      * var x = new X509();
171      * x.readCertPEM(sCertPEM);
172      * var sn = x.getSerialNumberHex(); // return string like "01ad..."
173      */
174     this.getSerialNumberHex = function() {
175 	return _getVbyListEx(this.hex, 0, [0, 0], "02");
176     };
177 
178     /**
179      * get signature algorithm name in basic field
180      * @name getSignatureAlgorithmField
181      * @memberOf X509#
182      * @function
183      * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA, SHA512withRSAandMGF1)
184      * @since x509 1.1.8
185      * @see X509#getAlgorithmIdentifierName
186      * @description
187      * This method will get a name of signature algorithm in 
188      * basic field of certificate.
189      * <br/>
190      * NOTE: From jsrsasign 8.0.21, RSA-PSS certificate is also supported.
191      * For supported RSA-PSS algorithm name and PSS parameters,
192      * see {@link X509#getSignatureAlgorithmField}.
193      * @example
194      * var x = new X509();
195      * x.readCertPEM(sCertPEM);
196      * algName = x.getSignatureAlgorithmField();
197      */
198     this.getSignatureAlgorithmField = function() {
199 	var hTLV = _getTLVbyListEx(this.hex, 0, [0, 1]);
200 	return this.getAlgorithmIdentifierName(hTLV);
201     };
202 
203     /**
204      * get algorithm name name of AlgorithmIdentifier ASN.1 structure
205      * @name getAlgorithmIdentifierName
206      * @memberOf X509#
207      * @function
208      * @param {String} hTLV hexadecimal string of AlgorithmIdentifier
209      * @return {String} algorithm name (ex. SHA1withRSA, SHA256withECDSA, SHA512withRSAandMGF1, SHA1)
210      * @since jsrsasign 9.0.0 x509 2.0.0
211      * @description
212      * This method will get a name of AlgorithmIdentifier.
213      * <br/>
214      * @example
215      * var x = new X509();
216      * algName = x.getAlgorithmIdentifierName("30...");
217      */
218     this.getAlgorithmIdentifierName = function(hTLV) {
219 	for (var key in _PSSNAME2ASN1TLV) {
220 	    if (hTLV === _PSSNAME2ASN1TLV[key]) {
221 		return key;
222 	    }
223 	}
224 	return _oidname(_getVbyListEx(hTLV, 0, [0], "06"));
225     };
226 
227     /**
228      * get JSON object of issuer field<br/>
229      * @name getIssuer
230      * @memberOf X509#
231      * @function
232      * @return {Array} JSON object of issuer field
233      * @since jsrsasign 9.0.0 x509 2.0.0
234      * @description
235      * @example
236      * var x = new X509();
237      * x.readCertPEM(sCertPEM);
238      * x.getIssuer() →
239      * { array: [[{type:'C',value:'JP',ds:'prn'}],...],
240      *   str: "30..." }
241      */
242     this.getIssuer = function() {
243 	var result = {};
244 	result.array = this.getX500Name(this.getIssuerHex());
245 	result.str = this.getIssuerString();
246 	return result;
247     };
248 
249     /**
250      * get hexadecimal string of issuer field TLV of certificate.<br/>
251      * @name getIssuerHex
252      * @memberOf X509#
253      * @function
254      * @return {String} hexadecial string of issuer DN ASN.1
255      * @example
256      * var x = new X509();
257      * x.readCertPEM(sCertPEM);
258      * var issuer = x.getIssuerHex(); // return string like "3013..."
259      */
260     this.getIssuerHex = function() {
261 	return _getTLVbyList(this.hex, 0, [0, 3 + this.foffset], "30");
262     };
263 
264     /**
265      * get string of issuer field of certificate.<br/>
266      * @name getIssuerString
267      * @memberOf X509#
268      * @function
269      * @return {String} issuer DN string
270      * @example
271      * var x = new X509();
272      * x.readCertPEM(sCertPEM);
273      * var dn1 = x.getIssuerString(); // return string like "/C=US/O=TEST"
274      * var dn2 = KJUR.asn1.x509.X500Name.compatToLDAP(dn1); // returns "O=TEST, C=US"
275      */
276     this.getIssuerString = function() {
277         return _X509.hex2dn(this.getIssuerHex());
278     };
279 
280     /**
281      * get JSON object of subject field<br/>
282      * @name getSubject
283      * @memberOf X509#
284      * @function
285      * @return {Array} JSON object of subject field
286      * @since jsrsasign 9.0.0 x509 2.0.0
287      * @description
288      * @example
289      * var x = new X509();
290      * x.readCertPEM(sCertPEM);
291      * x.getIssuer() →
292      * { array: [[{type:'C',value:'JP',ds:'prn'}],...],
293      *   str: "30..." }
294      */
295     this.getSubject = function() {
296 	var result = {};
297 	result.array = this.getX500Name(this.getSubjectHex());
298 	result.str = this.getSubjectString();
299 	return result;
300     };
301 
302     /**
303      * get hexadecimal string of subject field of certificate.<br/>
304      * @name getSubjectHex
305      * @memberOf X509#
306      * @function
307      * @return {String} hexadecial string of subject DN ASN.1
308      * @example
309      * var x = new X509();
310      * x.readCertPEM(sCertPEM);
311      * var subject = x.getSubjectHex(); // return string like "3013..."
312      */
313     this.getSubjectHex = function() {
314 	return _getTLVbyList(this.hex, 0, [0, 5 + this.foffset], "30");
315     };
316 
317     /**
318      * get string of subject field of certificate.<br/>
319      * @name getSubjectString
320      * @memberOf X509#
321      * @function
322      * @return {String} subject DN string
323      * @example
324      * var x = new X509();
325      * x.readCertPEM(sCertPEM);
326      * var dn1 = x.getSubjectString(); // return string like "/C=US/O=TEST"
327      * var dn2 = KJUR.asn1.x509.X500Name.compatToLDAP(dn1); // returns "O=TEST, C=US"
328      */
329     this.getSubjectString = function() {
330         return _X509.hex2dn(this.getSubjectHex());
331     };
332 
333     /**
334      * get notBefore field string of certificate.<br/>
335      * @name getNotBefore
336      * @memberOf X509#
337      * @function
338      * @return {String} not before time value (ex. "151231235959Z")
339      * @example
340      * var x = new X509();
341      * x.readCertPEM(sCertPEM);
342      * var notBefore = x.getNotBefore(); // return string like "151231235959Z"
343      */
344     this.getNotBefore = function() {
345         var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 0]);
346         s = s.replace(/(..)/g, "%$1");
347         s = decodeURIComponent(s);
348         return s;
349     };
350 
351     /**
352      * get notAfter field string of certificate.<br/>
353      * @name getNotAfter
354      * @memberOf X509#
355      * @function
356      * @return {String} not after time value (ex. "151231235959Z")
357      * @example
358      * var x = new X509();
359      * x.readCertPEM(sCertPEM);
360      * var notAfter = x.getNotAfter(); // return string like "151231235959Z"
361      */
362     this.getNotAfter = function() {
363 	var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 1]);
364         s = s.replace(/(..)/g, "%$1");
365         s = decodeURIComponent(s);
366         return s;
367     };
368 
369     /**
370      * get a hexadecimal string of subjectPublicKeyInfo field.<br/>
371      * @name getPublicKeyHex
372      * @memberOf X509#
373      * @function
374      * @return {String} ASN.1 SEQUENCE hexadecimal string of subjectPublicKeyInfo field
375      * @since jsrsasign 7.1.4 x509 1.1.13
376      * @example
377      * x = new X509();
378      * x.readCertPEM(sCertPEM);
379      * hSPKI = x.getPublicKeyHex(); // return string like "30820122..."
380      */
381     this.getPublicKeyHex = function() {
382 	return _ASN1HEX.getTLVbyList(this.hex, 0, [0, 6 + this.foffset], "30");
383     };
384 
385     /**
386      * get a string index of subjectPublicKeyInfo field for hexadecimal string certificate.<br/>
387      * @name getPublicKeyIdx
388      * @memberOf X509#
389      * @function
390      * @return {Number} string index of subjectPublicKeyInfo field for hexadecimal string certificate.
391      * @since jsrsasign 7.1.4 x509 1.1.13
392      * @example
393      * x = new X509();
394      * x.readCertPEM(sCertPEM);
395      * idx = x.getPublicKeyIdx(); // return string index in x.hex parameter
396      */
397     this.getPublicKeyIdx = function() {
398 	return _getIdxbyList(this.hex, 0, [0, 6 + this.foffset], "30");
399     };
400 
401     /**
402      * get a string index of contents of subjectPublicKeyInfo BITSTRING value from hexadecimal certificate<br/>
403      * @name getPublicKeyContentIdx
404      * @memberOf X509#
405      * @function
406      * @return {Integer} string index of key contents
407      * @since jsrsasign 8.0.0 x509 1.2.0
408      * @example
409      * x = new X509();
410      * x.readCertPEM(sCertPEM);
411      * idx = x.getPublicKeyContentIdx(); // return string index in x.hex parameter
412      */
413     // NOTE: Without BITSTRING encapsulation.
414     this.getPublicKeyContentIdx = function() {
415 	var idx = this.getPublicKeyIdx();
416 	return _getIdxbyList(this.hex, idx, [1, 0], "30");
417     };
418 
419     /**
420      * get a RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field.<br/>
421      * @name getPublicKey
422      * @memberOf X509#
423      * @function
424      * @return {Object} RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field
425      * @since jsrsasign 7.1.4 x509 1.1.13
426      * @example
427      * x = new X509();
428      * x.readCertPEM(sCertPEM);
429      * pubkey= x.getPublicKey();
430      */
431     this.getPublicKey = function() {
432 	return KEYUTIL.getKey(this.getPublicKeyHex(), null, "pkcs8pub");
433     };
434 
435     /**
436      * get signature algorithm name from hexadecimal certificate data
437      * @name getSignatureAlgorithmName
438      * @memberOf X509#
439      * @function
440      * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA)
441      * @since jsrsasign 7.2.0 x509 1.1.14
442      * @see X509#getAlgorithmIdentifierName
443      * @description
444      * This method will get signature algorithm name of certificate:
445      * @example
446      * var x = new X509();
447      * x.readCertPEM(sCertPEM);
448      * x.getSignatureAlgorithmName() → "SHA256withRSA"
449      */
450     this.getSignatureAlgorithmName = function() {
451 	var hTLV = _getTLVbyList(this.hex, 0, [1], "30");
452 	return this.getAlgorithmIdentifierName(hTLV);
453     };
454 
455     /**
456      * get signature value as hexadecimal string<br/>
457      * @name getSignatureValueHex
458      * @memberOf X509#
459      * @function
460      * @return {String} signature value hexadecimal string without BitString unused bits
461      * @since jsrsasign 7.2.0 x509 1.1.14
462      *
463      * @description
464      * This method will get signature value of certificate:
465      *
466      * @example
467      * var x = new X509();
468      * x.readCertPEM(sCertPEM);
469      * x.getSignatureValueHex() &rarr "8a4c47913..."
470      */
471     this.getSignatureValueHex = function() {
472 	return _getVbyList(this.hex, 0, [2], "03", true);
473     };
474 
475     /**
476      * verifies signature value by public key<br/>
477      * @name verifySignature
478      * @memberOf X509#
479      * @function
480      * @param {Object} pubKey public key object
481      * @return {Boolean} true if signature value is valid otherwise false
482      * @since jsrsasign 7.2.0 x509 1.1.14
483      *
484      * @description
485      * This method verifies signature value of hexadecimal string of 
486      * X.509 certificate by specified public key object.
487      * The signature algorithm used to verify will refer
488      * signatureAlgorithm field. (See {@link X509#getSignatureAlgorithmField})
489      * RSA-PSS signature algorithms (SHA{,256,384,512}withRSAandMGF1)
490      * are available.
491      *
492      * @example
493      * pubKey = KEYUTIL.getKey(pemPublicKey); // or certificate
494      * x = new X509();
495      * x.readCertPEM(pemCert);
496      * x.verifySignature(pubKey) → true, false or raising exception
497      */
498     this.verifySignature = function(pubKey) {
499 	var algName = this.getSignatureAlgorithmField();
500 	var hSigVal = this.getSignatureValueHex();
501 	var hTbsCert = _getTLVbyList(this.hex, 0, [0], "30");
502 	
503 	var sig = new KJUR.crypto.Signature({alg: algName});
504 	sig.init(pubKey);
505 	sig.updateHex(hTbsCert);
506 	return sig.verify(hSigVal);
507     };
508 
509     // ===== parse extension ======================================
510     /**
511      * set array of X.509v3 and CSR extesion information such as extension OID, criticality and value index. (DEPRECATED)<br/>
512      * @name parseExt
513      * @memberOf X509#
514      * @function
515      * @param {String} hCSR - PEM string of certificate signing requrest(CSR) (OPTION)
516      * @since jsrsasign 7.2.0 x509 1.1.14
517      * @deprecated jsrsasign 9.1.1 x509 2.0.1
518      *
519      * @description
520      * This method will set an array of X.509v3 extension information having 
521      * following parameters:
522      * <ul>
523      * <li>oid - extension OID (ex. 2.5.29.19)</li>
524      * <li>critical - true or false</li>
525      * <li>vidx - string index for extension value</li>
526      * <br/>
527      * When you want to parse extensionRequest of CSR,
528      * argument 'hCSR' shall be specified.
529      * <br/>
530      * NOTE: CSR is supported from jsrsasign 8.0.20 x509 1.1.22.
531      * <br/>
532      * This method and X509.aExtInfo property
533      * have been *deprecated* since jsrsasign 9.1.1.
534      * All extension parser method such as X509.getExt* shall be
535      * call with argument "hExtV" and "critical" explicitly.
536      *
537      * @example
538      * x = new X509();
539      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
540      *
541      * x.aExtInfo →
542      * [ { oid: "2.5.29,19", critical: true, vidx: 2504 }, ... ]
543      *
544      * // to parse CSR
545      * X = new X509()
546      * x.parseExt("-----BEGIN CERTIFICATE REQUEST-----...");
547      * x.aExtInfo →
548      * [ { oid: "2.5.29,19", critical: true, vidx: 2504 }, ... ]
549      */
550     this.parseExt = function(hCSR) {
551 	var iExtSeq, aExtIdx, h;
552 
553 	if (hCSR === undefined) {
554 	    h = this.hex;
555 	    if (this.version !== 3) return -1;
556 	    iExtSeq = _getIdxbyList(h, 0, [0, 7, 0], "30");
557 	    aExtIdx = _getChildIdx(h, iExtSeq);
558 	} else {
559 	    h = pemtohex(hCSR);
560 	    var idx1 = _getIdxbyList(h, 0, [0, 3, 0, 0], "06");
561 
562 	    if (_getV(h, idx1) != "2a864886f70d01090e") {
563 		this.aExtInfo = new Array();
564 		return;
565 	    }
566 
567 	    iExtSeq = _getIdxbyList(h, 0, [0, 3, 0, 1, 0], "30");
568 	    aExtIdx = _getChildIdx(h, iExtSeq);
569 
570 	    this.hex = h;
571 	}
572 	    
573 	this.aExtInfo = new Array();
574 	for (var i = 0; i < aExtIdx.length; i++) {
575 	    var item = {};
576 	    item.critical = false;
577 	    var a = _getChildIdx(h, aExtIdx[i]);
578 	    var offset = 0;
579 
580 	    if (a.length === 3) {
581 		item.critical = true;
582 		offset = 1;
583 	    }
584 
585 	    item.oid = _ASN1HEX.hextooidstr(_getVbyList(h, aExtIdx[i], [0], "06"));
586 	    var octidx = _getIdxbyList(h, aExtIdx[i], [1 + offset]);
587 	    item.vidx = _getVidx(h, octidx);
588 	    this.aExtInfo.push(item);
589 	}
590     };
591 
592     /**
593      * get a X.509v3 extesion information such as extension OID, criticality and value index for specified oid or name.<br/>
594      * @name getExtInfo
595      * @memberOf X509#
596      * @function
597      * @param {String} oidOrName X.509 extension oid or name (ex. keyUsage or 2.5.29.19)
598      * @return X.509 extension information such as extension OID or value indx (see {@link X509#parseExt})
599      * @since jsrsasign 7.2.0 x509 1.1.14
600      * @description
601      * This method will get an X.509v3 extension information JSON object
602      * having extension OID, criticality and value idx for specified
603      * extension OID or name.
604      * If there is no such extension, this returns undefined.
605      * @example
606      * x = new X509();
607      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
608      *
609      * x.getExtInfo("keyUsage") → { oid: "2.5.29.15", critical: true, vidx: 1714 }
610      * x.getExtInfo("unknownExt") → undefined
611      */
612     this.getExtInfo = function(oidOrName) {
613 	var a = this.aExtInfo;
614 	var oid = oidOrName;
615 	if (! oidOrName.match(/^[0-9.]+$/)) {
616 	    oid = KJUR.asn1.x509.OID.name2oid(oidOrName);
617 	}
618 	if (oid === '') return undefined;
619 
620 	for (var i = 0; i < a.length; i++) {
621 	    if (a[i].oid === oid) return a[i];
622 	}
623 	return undefined;
624     };
625 
626     /**
627      * get BasicConstraints extension value as object in the certificate
628      * @name getExtBasicConstraints
629      * @memberOf X509#
630      * @function
631      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
632      * @param {Boolean} critical flag (OPTIONAL)
633      * @return {Array} JSON object of BasicConstraints parameter or undefined
634      * @since jsrsasign 7.2.0 x509 1.1.14
635      * @see {@link KJUR.asn1.x509.BasicConstraints}
636      * @description
637      * This method will get basic constraints extension value as object with following paramters.
638      * <ul>
639      * <li>{Boolean}cA - CA flag whether CA or not</li>
640      * <li>{Integer}pathLen - maximum intermediate certificate length</li>
641      * <li>{Boolean}critical - critical flag</li>
642      * </ul>
643      * There are use cases for return values:
644      * <ul>
645      * <li>{cA:true,pathLen:3,critical:true} - cA flag is true and pathLen is 3</li>
646      * <li>{cA:true,critical:true} - cA flag is true and no pathLen</li>
647      * <li>{} - basic constraints has no value in case of end entity certificate</li>
648      * <li>undefined - there is no basic constraints extension</li>
649      * </ul>
650      * @example
651      * x = new X509();
652      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
653      * x.getExtBasicConstraints() → {cA:true,pathLen:3,critical:true}
654      */
655     this.getExtBasicConstraints = function(hExtV, critical) {
656 	if (hExtV === undefined && critical === undefined) {
657 	    var info = this.getExtInfo("basicConstraints");
658 	    if (info === undefined) return undefined;
659 	    hExtV = _getTLV(this.hex, info.vidx);
660 	    critical = info.critical;
661 	}
662 
663 	var result = {extname:"basicConstraints"};
664 	if (critical) result.critical = true;
665 
666 	if (hExtV === '3000') return result;
667 	if (hExtV === '30030101ff') {
668 	    result.cA = true;
669 	    return result;
670 	}
671 	if (hExtV.substr(0, 12) === '30060101ff02') {
672 	    var pathLexHex = _getV(hExtV, 10);
673 	    var pathLen = parseInt(pathLexHex, 16);
674 	    result.cA = true;
675 	    result.pathLen = pathLen;
676 	    return result;
677 	}
678 	throw new Error("hExtV parse error: " + hExtV);
679     };
680 
681     /**
682      * get KeyUsage extension value as JSON object
683      * @memberOf X509#
684      * @function
685      * @name getExtKeyUsage
686      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
687      * @param {Boolean} critical flag (OPTIONAL)
688      * @return {Array} JSON object of KeyUsage parameter or undefined
689      * @since jsrsasign 9.0.0 x509 2.0.0
690      * @see {@link KJUR.asn1.x509.KeyUsage}
691      * @see {@link X509#getExtKeyUsageString}
692      * @description
693      * This method parse keyUsage extension. When arguments are
694      * not specified, its extension in X509 object will be parsed.
695      * Result of this method can be passed to 
696      * {@link KJUR.asn1.x509.KeyUsage} constructor.
697      * <br>
698      * When hExtV and critical specified as arguments, return value
699      * will be generated from them.
700      * <pre>
701      * id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
702      * KeyUsage ::= BIT STRING {
703      *      digitalSignature        (0),
704      *      nonRepudiation          (1),
705      *      keyEncipherment         (2),
706      *      dataEncipherment        (3),
707      *      keyAgreement            (4),
708      *      keyCertSign             (5),
709      *      cRLSign                 (6),
710      *      encipherOnly            (7),
711      *      decipherOnly            (8) }     
712      * </pre>
713      * @example
714      * x = new X509();
715      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
716      * x.getExtKeyUsage() →
717      * {
718      *   critial: true,
719      *   names: ["digitalSignature", "decipherOnly"]
720      * }
721      *
722      * x = new X509();
723      * x.getExtKeyUsage("306230...") 
724      * x.getExtKeyUsage("306230...", true) 
725      */
726     this.getExtKeyUsage = function(hExtV, critical) {
727 	if (hExtV === undefined && critical === undefined) {
728 	    var info = this.getExtInfo("keyUsage");
729 	    if (info === undefined) return undefined;
730 	    hExtV = _getTLV(this.hex, info.vidx);
731 	    critical = info.critical;
732 	}
733 
734 	var result = {extname:"keyUsage"};
735 	if (critical) result.critical = true;
736 
737 	result.names = this.getExtKeyUsageString(hExtV).split(",");
738 
739 	return result;
740     };
741 
742     /**
743      * get KeyUsage extension value as binary string in the certificate<br/>
744      * @name getExtKeyUsageBin
745      * @memberOf X509#
746      * @function
747      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
748      * @return {String} binary string of key usage bits (ex. '101')
749      * @since jsrsasign 7.2.0 x509 1.1.14
750      * @see {@link X509#getExtKeyUsage}
751      * @description
752      * This method will get key usage extension value
753      * as binary string such like '101'.
754      * Key usage bits definition is in the RFC 5280.
755      * If there is no key usage extension in the certificate,
756      * it returns empty string (i.e. '').
757      * <br/>
758      * NOTE: argument 'hExtV' supported since jsrsasign 9.0.0 x509 2.0.0.
759      * @example
760      * x = new X509();
761      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
762      * x.getExtKeyUsageBin() → '101'
763      * // 1 - digitalSignature
764      * // 0 - nonRepudiation
765      * // 1 - keyEncipherment
766      */
767     this.getExtKeyUsageBin = function(hExtV) {
768 	if (hExtV === undefined) {
769 	    var info = this.getExtInfo("keyUsage");
770 	    if (info === undefined) return '';
771 	    hExtV = _getTLV(this.hex, info.vidx);
772 	}
773 	
774 	if (hExtV.length != 8 && hExtV.length != 10)
775 	    throw new Error("malformed key usage value: " + hExtV);
776 
777 	var s = "000000000000000" + parseInt(hExtV.substr(6), 16).toString(2);
778 	if (hExtV.length == 8) s = s.slice(-8);
779 	if (hExtV.length == 10) s = s.slice(-16);
780 	s = s.replace(/0+$/, '');
781 	if (s == '') s = '0';
782 	return s;
783     };
784 
785     /**
786      * get KeyUsage extension value as names in the certificate<br/>
787      * @name getExtKeyUsageString
788      * @memberOf X509#
789      * @function
790      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
791      * @return {String} comma separated string of key usage
792      * @since jsrsasign 7.2.0 x509 1.1.14
793      * @see {@link X509#getExtKeyUsage}
794      * @description
795      * This method will get key usage extension value
796      * as comma separated string of usage names.
797      * If there is no key usage extension in the certificate,
798      * it returns empty string (i.e. '').
799      * <br/>
800      * NOTE: argument 'hExtV' supported since jsrsasign 9.0.0 x509 2.0.0.
801      * @example
802      * x = new X509();
803      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
804      * x.getExtKeyUsageString() → "digitalSignature,keyEncipherment"
805      */
806     this.getExtKeyUsageString = function(hExtV) {
807 	var bKeyUsage = this.getExtKeyUsageBin(hExtV);
808 	var a = new Array();
809 	for (var i = 0; i < bKeyUsage.length; i++) {
810 	    if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]);
811 	}
812 	return a.join(",");
813     };
814 
815     /**
816      * get subjectKeyIdentifier value as hexadecimal string in the certificate<br/>
817      * @name getExtSubjectKeyIdentifier
818      * @memberOf X509#
819      * @function
820      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
821      * @param {Boolean} critical flag (OPTIONAL)
822      * @return {Array} JSON object of SubjectKeyIdentifier parameter or undefined
823      * @since jsrsasign 7.2.0 x509 1.1.14
824      * @description
825      * This method will get 
826      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.2">
827      * SubjectKeyIdentifier extension</a> value as JSON object.
828      * <br>
829      * When hExtV and critical specified as arguments, return value
830      * will be generated from them.
831      * If there is no such extension in the certificate, it returns undefined.
832      * <br>
833      * Result of this method can be passed to 
834      * {@link KJUR.asn1.x509.SubjectKeyIdentifier} constructor.
835      * <pre>
836      * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 }
837      * SubjectKeyIdentifier ::= KeyIdentifier
838      * </pre>
839      * <br>
840      * CAUTION:
841      * Returned JSON value format have been changed without 
842      * backward compatibility since jsrsasign 9.0.0 x509 2.0.0.
843      *
844      * @example
845      * x = new X509();
846      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
847      * x.getExtSubjectKeyIdentifier() → 
848      * { kid: {hex: "1b3347ab..."}, critical: true };
849      */
850     this.getExtSubjectKeyIdentifier = function(hExtV, critical) {
851 	if (hExtV === undefined && critical === undefined) {
852 	    var info = this.getExtInfo("subjectKeyIdentifier");
853 	    if (info === undefined) return undefined;
854 	    hExtV = _getTLV(this.hex, info.vidx);
855 	    critical = info.critical;
856 	}
857 
858 	var result = {extname:"subjectKeyIdentifier"};
859 	if (critical) result.critical = true;
860 
861 	var hKID = _getV(hExtV, 0);
862 	result.kid = {hex: hKID};
863 
864 	return result;
865     };
866 
867     /**
868      * get authorityKeyIdentifier value as JSON object in the certificate<br/>
869      * @name getExtAuthorityKeyIdentifier
870      * @memberOf X509#
871      * @function
872      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
873      * @param {Boolean} critical flag (OPTIONAL)
874      * @return {Array} JSON object of AuthorityKeyIdentifier parameter or undefined
875      * @since jsrsasign 7.2.0 x509 1.1.14
876      * @see {@link KJUR.asn1.x509.AuthorityKeyIdentifier}
877      * @description
878      * This method will get 
879      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.1">
880      * AuthorityKeyIdentifier extension</a> value as JSON object.
881      * <br>
882      * When hExtV and critical specified as arguments, return value
883      * will be generated from them.
884      * If there is no such extension in the certificate, it returns undefined.
885      * <br/>
886      * Result of this method can be passed to 
887      * {@link KJUR.asn1.x509.AuthorityKeyIdentifier} constructor.
888      * <pre>
889      *    id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
890      *    AuthorityKeyIdentifier ::= SEQUENCE {
891      *       keyIdentifier             [0] KeyIdentifier           OPTIONAL,
892      *       authorityCertIssuer       [1] GeneralNames            OPTIONAL,
893      *       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
894      *    KeyIdentifier ::= OCTET STRING
895      * </pre>
896      * Constructor may have following parameters:
897      * <ul>
898      * <li>{Array}kid - JSON object of {@link KJUR.asn1.DEROctetString} parameters</li>
899      * <li>{Array}issuer - JSON object of {@link KJUR.asn1.x509.X500Name} parameters</li>
900      * <li>{Array}sn - JSON object of {@link KJUR.asn1.DERInteger} parameters</li>
901      * <li>{Boolean}critical - critical flag</li>
902      * </ul>
903      * <br>
904      * NOTE: The 'authorityCertIssuer' and 'authorityCertSerialNumber'
905      * supported since jsrsasign 9.0.0 x509 2.0.0.
906      * @example
907      * x = new X509();
908      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
909      * x.getExtAuthorityKeyIdentifier() → 
910      * { kid: {hex: "1234abcd..."},
911      *   issuer: {hex: "30..."},
912      *   sn: {hex: "1234..."},
913      *   critical: true}
914      */
915     this.getExtAuthorityKeyIdentifier = function(hExtV, critical) {
916 	if (hExtV === undefined && critical === undefined) {
917 	    var info = this.getExtInfo("authorityKeyIdentifier");
918 	    if (info === undefined) return undefined;
919 	    hExtV = _getTLV(this.hex, info.vidx);
920 	    critical = info.critical;
921 	}
922 
923 	var result = {extname:"authorityKeyIdentifier"};
924 	if (critical) result.critical = true;
925 
926 	var a = _getChildIdx(hExtV, 0);
927 	for (var i = 0; i < a.length; i++) {
928 	    var tag = hExtV.substr(a[i], 2);
929 	    if (tag === "80") {
930 		result.kid = {hex: _getV(hExtV, a[i])};
931 	    }
932 	    if (tag === "a1") {
933 		var hGNS = _getTLV(hExtV, a[i]);
934 		var gnsParam = this.getGeneralNames(hGNS);
935 		result.issuer = gnsParam[0]["dn"];
936 	    }
937 	    if (tag === "82") {
938 		result.sn = {hex: _getV(hExtV, a[i])};
939 	    }
940 	}
941 	return result;
942     };
943 
944     /**
945      * get extKeyUsage value as JSON object
946      * @name getExtExtKeyUsage
947      * @memberOf X509#
948      * @function
949      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
950      * @param {Boolean} critical flag (OPTIONAL)
951      * @return {Array} JSON object of ExtKeyUsage parameter or undefined
952      * @return {Object} JSONarray of extended key usage ID name or oid
953      * @since jsrsasign 9.0.0 x509 2.0.0
954      * @see {@link KJUR.asn1.x509.ExtKeyUsage}
955      * @description
956      * This method parse extKeyUsage extension. When arguments are
957      * not specified, its extension in X509 object will be parsed.
958      * Result of this method can be passed to 
959      * {@link KJUR.asn1.x509.ExtKeyUsage} constructor.
960      * <br>
961      * When hExtV and critical specified as arguments, return value
962      * will be generated from them.
963      * @example
964      * x = new X509();
965      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
966      * x.getExtExtKeyUsage() →
967      * { array: ["clientAuth", "emailProtection", "1.3.6.1.4.1.311.10.3.4"], 
968      *   critical: true},
969      */
970     this.getExtExtKeyUsage = function(hExtV, critical) {
971 	if (hExtV === undefined && critical === undefined) {
972 	    var info = this.getExtInfo("extKeyUsage");
973 	    if (info === undefined) return undefined;
974 	    hExtV = _getTLV(this.hex, info.vidx);
975 	    critical = info.critical;
976 	}
977 
978 	var result = {extname:"extKeyUsage",array:[]};
979 	if (critical) result.critical = true;
980 
981 	var a = _getChildIdx(hExtV, 0);
982 
983 	for (var i = 0; i < a.length; i++) {
984 	    result.array.push(_oidname(_getV(hExtV, a[i])));
985 	}
986 
987 	return result;
988     };
989 
990     /**
991      * get extKeyUsage value as array of name string in the certificate(DEPRECATED)<br/>
992      * @name getExtExtKeyUsageName
993      * @memberOf X509#
994      * @function
995      * @return {Object} array of extended key usage ID name or oid
996      * @since jsrsasign 7.2.0 x509 1.1.14
997      * @deprecated since jsrsasign 9.0.0 x509 2.0.0
998      * @description
999      * This method will get extended key usage extension value
1000      * as array of name or OID string.
1001      * If there is this in the certificate, it returns undefined;
1002      * <br>
1003      * NOTE: Supported extended key usage ID names are defined in
1004      * name2oidList parameter in asn1x509.js file.
1005      * @example
1006      * x = new X509();
1007      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1008      * x.getExtExtKeyUsageName() → ["serverAuth", "clientAuth", "0.1.2.3.4.5"]
1009      */
1010     this.getExtExtKeyUsageName = function() {
1011 	var info = this.getExtInfo("extKeyUsage");
1012 	if (info === undefined) return info;
1013 
1014 	var result = new Array();
1015 	
1016 	var h = _getTLV(this.hex, info.vidx);
1017 	if (h === '') return result;
1018 
1019 	var a = _getChildIdx(h, 0);
1020 	for (var i = 0; i < a.length; i++) {
1021 	    result.push(_oidname(_getV(h, a[i])));
1022 	}
1023 
1024 	return result;
1025     };
1026 
1027     /**
1028      * get subjectAltName value as array of string in the certificate
1029      * @name getExtSubjectAltName
1030      * @memberOf X509#
1031      * @function
1032      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1033      * @param {Boolean} critical flag (OPTIONAL)
1034      * @return {Array} JSON object of SubjectAltName parameters or undefined
1035      * @since jsrsasign 7.2.0 x509 1.1.14
1036      * @see {@link KJUR.asn1.x509.SubjectAltName}
1037      * @see {@link X509#IssuerAltName}
1038      * @description
1039      * This method will get subjectAltName value
1040      * as an array of JSON object which has properties defined
1041      * in {@link KJUR.asn1.x509.SubjectAltName}.
1042      * Result of this method can be passed to 
1043      * {@link KJUR.asn1.x509.SubjectAltName} constructor.
1044      * If there is no this extension in the certificate,
1045      * it returns undefined.
1046      * <br>
1047      * When hExtV and critical specified as arguments, return value
1048      * will be generated from them.
1049      * <br>
1050      * CAUTION: return value of JSON object format have been changed
1051      * from jsrsasign 9.0.0 x509 2.0.0 without backword compatibility.
1052      * @example
1053      * x = new X509();
1054      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1055      * x.getExtSubjectAltName() → 
1056      * { array: [
1057      *     {uri: "http://example.com/"},
1058      *     {rfc822: "user1@example.com"},
1059      *     {dns: "example.com"}
1060      *   ],
1061      *   critical: true
1062      * }
1063      *
1064      * x.getExtSubjectAltName("3026...") →
1065      * { array: [{ip: "192.168.1.1"}] }
1066      */
1067     this.getExtSubjectAltName = function(hExtV, critical) {
1068 	if (hExtV === undefined && critical === undefined) {
1069 	    var info = this.getExtInfo("subjectAltName");
1070 	    if (info === undefined) return undefined;
1071 	    hExtV = _getTLV(this.hex, info.vidx);
1072 	    critical = info.critical;
1073 	}
1074 
1075 	var result = {extname:"subjectAltName",array:[]};
1076 	if (critical) result.critical = true;
1077 
1078 	result.array = this.getGeneralNames(hExtV);
1079 
1080 	return result;
1081     };
1082 
1083     /**
1084      * get issuerAltName value as array of string in the certificate
1085      * @name getExtIssuerAltName
1086      * @memberOf X509#
1087      * @function
1088      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1089      * @param {Boolean} critical flag (OPTIONAL)
1090      * @return {Array} JSON object of IssuerAltName parameters
1091      * @since jsrsasign 9.0.0 x509 2.0.0
1092      * @see {@link KJUR.asn1.x509.IssuerAltName}
1093      * @see {@link X509#SubjectAltName}
1094      * @description
1095      * This method will get issuerAltName value
1096      * as an array of JSON object which has properties defined
1097      * in {@link KJUR.asn1.x509.IssuerAltName}.
1098      * Result of this method can be passed to 
1099      * {@link KJUR.asn1.x509.IssuerAltName} constructor.
1100      * If there is no this extension in the certificate,
1101      * it returns undefined.
1102      * <br>
1103      * When hExtV and critical specified as arguments, return value
1104      * will be generated from them.
1105      * @example
1106      * x = new X509();
1107      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1108      * x.getExtIssuerAltName() → 
1109      * { array: [
1110      *     {uri: "http://example.com/"},
1111      *     {rfc822: "user1@example.com"},
1112      *     {dns: "example.com"}
1113      *   ],
1114      *   critical: true
1115      * }
1116      *
1117      * x.getExtIssuerAltName("3026...") →
1118      * { array: [{ip: "192.168.1.1"}] }
1119      */
1120     this.getExtIssuerAltName = function(hExtV, critical) {
1121 	if (hExtV === undefined && critical === undefined) {
1122 	    var info = this.getExtInfo("issuerAltName");
1123 	    if (info === undefined) return undefined;
1124 	    hExtV = _getTLV(this.hex, info.vidx);
1125 	    critical = info.critical;
1126 	}
1127 
1128 	var result = {extname:"issuerAltName",array:[]};
1129 	if (critical) result.critical = true;
1130 
1131 	result.array = this.getGeneralNames(hExtV);
1132 
1133 	return result;
1134     };
1135 
1136     /**
1137      * get GeneralNames ASN.1 structure parameter as JSON object
1138      * @name getGeneralNames
1139      * @memberOf X509#
1140      * @function
1141      * @param {String} h hexadecimal string of GeneralNames
1142      * @return {Array} array of GeneralNames parameters
1143      * @see {@link KJUR.asn1.x509.GeneralNames}
1144      * @see {@link KJUR.asn1.x509.GeneralName}
1145      * @see {@link X509#getGeneralNames}
1146      * @since jsrsasign 9.0.0 x509 2.0.0
1147      * @description
1148      * This method will get GeneralNames parameters defined in
1149      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6">
1150      * RFC 5280 4.2.1.6</a>.
1151      * <pre>
1152      * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1153      * </pre>
1154      * Result of this method can be passed to
1155      * {@link KJUR.asn1.x509.GeneralNames} constructor.
1156      * @example
1157      * x = new X509();
1158      * x.getGeneralNames("3011860f687474703a2f2f6161612e636f6d2f")
1159      * → [{uri: "http://aaa.com/"}]
1160      */
1161     this.getGeneralNames = function(h) {
1162 	var aIdx = _getChildIdx(h, 0);
1163 	var result = [];
1164 	for (var i = 0; i < aIdx.length; i++) {
1165 	    var gnParam = this.getGeneralName(_getTLV(h, aIdx[i]));
1166 	    if (gnParam !== undefined) result.push(gnParam);
1167 	}
1168 	return result;
1169     };
1170 
1171     /**
1172      * get GeneralName ASN.1 structure parameter as JSON object
1173      * @name getGeneralName
1174      * @memberOf X509#
1175      * @function
1176      * @param {String} h hexadecimal string of GeneralName
1177      * @return {Array} JSON object of GeneralName parameters or undefined
1178      * @see {@link KJUR.asn1.x509.GeneralNames}
1179      * @see {@link X509#getGeneralName}
1180      * @since jsrsasign 9.0.0 x509 2.0.0
1181      * @description
1182      * This method will get GeneralName parameters defined in
1183      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6">
1184      * RFC 5280 4.2.1.6</a>.
1185      * <pre>
1186      * GeneralName ::= CHOICE {
1187      *      otherName                       [0]     OtherName,
1188      *      rfc822Name                      [1]     IA5String,
1189      *      dNSName                         [2]     IA5String,
1190      *      x400Address                     [3]     ORAddress,
1191      *      directoryName                   [4]     Name,
1192      *      ediPartyName                    [5]     EDIPartyName,
1193      *      uniformResourceIdentifier       [6]     IA5String,
1194      *      iPAddress                       [7]     OCTET STRING,
1195      *      registeredID                    [8]     OBJECT IDENTIFIER }
1196      * </pre>
1197      * Result of this method can be passed to
1198      * {@link KJUR.asn1.x509.GeneralName} constructor.
1199      * @example
1200      * x = new X509();
1201      * x.getGeneralName("860f687474703a2f2f6161612e636f6d2f") 
1202      * → {uri: "http://aaa.com/"}
1203      */
1204     this.getGeneralName = function(h) {
1205 	var tag = h.substr(0, 2);
1206 	var hValue = _getV(h, 0);
1207 	var sValue = hextorstr(hValue);
1208 	if (tag == "81") return {rfc822: sValue};
1209 	if (tag == "82") return {dns: sValue};
1210 	if (tag == "a4") return {dn: {hex: hValue}};
1211 	if (tag == "86") return {uri: sValue};
1212 	if (tag == "87") return {ip: hextoip(hValue)};
1213 	return undefined;
1214     };
1215 
1216     /**
1217      * get subjectAltName value as array of string in the certificate (DEPRECATED)
1218      * @name getExtSubjectAltName2
1219      * @memberOf X509#
1220      * @function
1221      * @return {Object} array of alt name array
1222      * @since jsrsasign 8.0.1 x509 1.1.17
1223      * @deprecated jsrsasign 9.0.0 x509 2.0.0
1224      * @description
1225      * This method will get subject alt name extension value
1226      * as array of type and name.
1227      * If there is this in the certificate, it returns undefined;
1228      * Type of GeneralName will be shown as following:
1229      * <ul>
1230      * <li>"MAIL" - [1]rfc822Name</li>
1231      * <li>"DNS"  - [2]dNSName</li>
1232      * <li>"DN"   - [4]directoryName</li>
1233      * <li>"URI"  - [6]uniformResourceIdentifier</li>
1234      * <li>"IP"   - [7]iPAddress</li>
1235      * </ul>
1236      * @example
1237      * x = new X509();
1238      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1239      * x.getExtSubjectAltName2() →
1240      * [["DNS",  "example.com"],
1241      *  ["DNS",  "example.org"],
1242      *  ["MAIL", "foo@example.com"],
1243      *  ["IP",   "192.168.1.1"],
1244      *  ["IP",   "2001:db8::2:1"],
1245      *  ["DN",   "/C=US/O=TEST1"]]
1246      */
1247     this.getExtSubjectAltName2 = function() {
1248 	var gnValueHex, gnValueStr, gnTag;
1249 	var info = this.getExtInfo("subjectAltName");
1250 	if (info === undefined) return info;
1251 
1252 	var result = new Array();
1253 	var h = _getTLV(this.hex, info.vidx);
1254 
1255 	var a = _getChildIdx(h, 0);
1256 	for (var i = 0; i < a.length; i++) {
1257 	    gnTag = h.substr(a[i], 2);
1258 	    gnValueHex = _getV(h, a[i]);
1259 	    
1260 	    if (gnTag === "81") { // rfc822Name [1]
1261 		gnValueStr = hextoutf8(gnValueHex);
1262 		result.push(["MAIL", gnValueStr]);
1263 	    }
1264 	    if (gnTag === "82") { // dNSName [2]
1265 		gnValueStr = hextoutf8(gnValueHex);
1266 		result.push(["DNS", gnValueStr]);
1267 	    }
1268 	    if (gnTag === "84") { // directoryName [4]
1269 		gnValueStr = X509.hex2dn(gnValueHex, 0);
1270 		result.push(["DN", gnValueStr]);
1271 	    }
1272 	    if (gnTag === "86") { // uniformResourceIdentifier [6]
1273 		gnValueStr = hextoutf8(gnValueHex);
1274 		result.push(["URI", gnValueStr]);
1275 	    }
1276 	    if (gnTag === "87") { // iPAddress [7]
1277 		gnValueStr = hextoip(gnValueHex);
1278 		result.push(["IP", gnValueStr]);
1279 	    }
1280 	}
1281 	return result;
1282     };
1283 
1284     /**
1285      * get CRLDistributionPoints extension value as JSON object
1286      * @name getExtCRLDistributionPoints
1287      * @memberOf X509#
1288      * @function
1289      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1290      * @param {Boolean} critical flag (OPTIONAL)
1291      * @return {Object} JSON object of CRLDistributionPoints parameters or undefined
1292      * @since jsrsasign 9.0.0 x509 2.0.0
1293      * @see {@link KJUR.asn1.x509.CRLDistributionPoints}
1294      * @see {@link X509#getDistributionPoint}
1295      * @see {@link X509#getDistributionPointName}
1296      * @see {@link X509#getGeneralNames}
1297      * @see {@link X509#getGeneralName}
1298      * @description
1299      * This method will get certificate policies value
1300      * as an array of JSON object which has properties defined
1301      * in {@link KJUR.asn1.x509.CRLDistributionPoints}.
1302      * Result of this method can be passed to 
1303      * {@link KJUR.asn1.x509.CRLDistributionPoints} constructor.
1304      * If there is no this extension in the certificate,
1305      * it returns undefined.
1306      * @example
1307      * x = new X509();
1308      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1309      * x.getExtCRLDistributionPoints() → 
1310      * {array: [
1311      *   {dpname: {full: [{uri: "http://example.com/"}]}},
1312      *   {dpname: {full: [{uri: "ldap://example.com/"}]}}
1313      *  ],
1314      *  critical: true}
1315      */
1316     this.getExtCRLDistributionPoints = function(hExtV, critical) {
1317 	if (hExtV === undefined && critical === undefined) {
1318 	    var info = this.getExtInfo("cRLDistributionPoints");
1319 	    if (info === undefined) return undefined;
1320 	    hExtV = _getTLV(this.hex, info.vidx);
1321 	    critical = info.critical;
1322 	}
1323 
1324 	var result = {extname:"cRLDistributionPoints",array:[]};
1325 	if (critical) result.critical = true;
1326 
1327 	var a = _getChildIdx(hExtV, 0);
1328 	for (var i = 0; i < a.length; i++) {
1329 	    var hTLV = _getTLV(hExtV, a[i]);
1330 	    result.array.push(this.getDistributionPoint(hTLV));
1331 	}
1332 
1333 	return result;
1334     };
1335 
1336     /**
1337      * get DistributionPoint ASN.1 structure parameter as JSON object
1338      * @name getDistributionPoint
1339      * @memberOf X509#
1340      * @function
1341      * @param {String} h hexadecimal string of DistributionPoint
1342      * @return {Object} JSON object of DistributionPoint parameters
1343      * @since jsrsasign 9.0.0 x509 2.0.0
1344      * @see {@link X509#getExtCRLDistributionPoints}
1345      * @see {@link X509#getDistributionPointName}
1346      * @see {@link X509#getGeneralNames}
1347      * @see {@link X509#getGeneralName}
1348      * @description
1349      * This method will get DistributionPoint parameters.
1350      * Result of this method can be passed to
1351      * {@link KJUR.asn1.x509.DistributionPoint} constructor.
1352      * <br/>
1353      * NOTE: reasons[1] and CRLIssuer[2] field not supported
1354      * @example
1355      * x = new X509();
1356      * x.getDistributionPoint("30...") →
1357      * {dpname: {full: [{uri: "http://aaa.com/"}]}}
1358      */
1359     this.getDistributionPoint = function(h) {
1360 	var result = {};
1361 	var a = _getChildIdx(h, 0);
1362 	for (var i = 0; i < a.length; i++) {
1363 	    var tag = h.substr(a[i], 2);
1364 	    var hTLV = _getTLV(h, a[i]);
1365 	    if (tag == "a0") {
1366 		result.dpname = this.getDistributionPointName(hTLV);
1367 	    }
1368 	}
1369 	return result;
1370     };
1371 
1372     /**
1373      * get DistributionPointName ASN.1 structure parameter as JSON object
1374      * @name getDistributionPointName
1375      * @memberOf X509#
1376      * @function
1377      * @param {String} h hexadecimal string of DistributionPointName
1378      * @return {Object} JSON object of DistributionPointName parameters
1379      * @since jsrsasign 9.0.0 x509 2.0.0
1380      * @see {@link X509#getExtCRLDistributionPoints}
1381      * @see {@link X509#getDistributionPoint}
1382      * @see {@link X509#getGeneralNames}
1383      * @see {@link X509#getGeneralName}
1384      * @description
1385      * This method will get DistributionPointName parameters.
1386      * Result of this method can be passed to
1387      * {@link KJUR.asn1.x509.DistributionPointName} constructor.
1388      * <br/>
1389      * NOTE: nameRelativeToCRLIssuer[1] not supported
1390      * @example
1391      * x = new X509();
1392      * x.getDistributionPointName("a0...") →
1393      * {full: [{uri: "http://aaa.com/"}]}
1394      */
1395     this.getDistributionPointName = function(h) {
1396 	var result = {};
1397 	var a = _getChildIdx(h, 0);
1398 	for (var i = 0; i < a.length; i++) {
1399 	    var tag = h.substr(a[i], 2);
1400 	    var hTLV = _getTLV(h, a[i]);
1401 	    if (tag == "a0") {
1402 		result.full = this.getGeneralNames(hTLV);
1403 	    }
1404 	}
1405 	return result;
1406     };
1407 
1408     /**
1409      * get array of string for fullName URIs in cRLDistributionPoints(CDP) in the certificate (DEPRECATED)
1410      * @name getExtCRLDistributionPointsURI
1411      * @memberOf X509#
1412      * @function
1413      * @return {Object} array of fullName URIs of CDP of the certificate
1414      * @since jsrsasign 7.2.0 x509 1.1.14
1415      * @description
1416      * This method will get all fullName URIs of cRLDistributionPoints extension
1417      * in the certificate as array of URI string.
1418      * If there is this in the certificate, it returns undefined;
1419      * <br>
1420      * NOTE: Currently this method supports only fullName URI so that
1421      * other parameters will not be returned.
1422      * @example
1423      * x = new X509();
1424      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1425      * x.getExtCRLDistributionPointsURI() →
1426      * ["http://example.com/aaa.crl", "http://example.org/aaa.crl"]
1427      */
1428     this.getExtCRLDistributionPointsURI = function() {
1429 	var info = this.getExtInfo("cRLDistributionPoints");
1430 	if (info === undefined) return info;
1431 
1432 	var result = new Array();
1433 	var a = _getChildIdx(this.hex, info.vidx);
1434 	for (var i = 0; i < a.length; i++) {
1435 	    try {
1436 		var hURI = _getVbyList(this.hex, a[i], [0, 0, 0], "86");
1437 		var uri = hextoutf8(hURI);
1438 		result.push(uri);
1439 	    } catch(ex) {};
1440 	}
1441 
1442 	return result;
1443     };
1444 
1445     /**
1446      * get AuthorityInfoAccess extension value in the certificate as associative array
1447      * @name getExtAIAInfo
1448      * @memberOf X509#
1449      * @function
1450      * @return {Object} associative array of AIA extension properties
1451      * @since jsrsasign 7.2.0 x509 1.1.14
1452      * @description
1453      * This method will get authority info access value
1454      * as associate array which has following properties:
1455      * <ul>
1456      * <li>ocsp - array of string for OCSP responder URL</li>
1457      * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li>
1458      * </ul>
1459      * If there is this in the certificate, it returns undefined;
1460      * @example
1461      * x = new X509();
1462      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1463      * x.getExtAIAInfo(hCert) → 
1464      * { ocsp:     ["http://ocsp.foo.com"],
1465      *   caissuer: ["http://rep.foo.com/aaa.p8m"] }
1466      */
1467     this.getExtAIAInfo = function() {
1468 	var info = this.getExtInfo("authorityInfoAccess");
1469 	if (info === undefined) return info;
1470 
1471 	var result = { ocsp: [], caissuer: [] };
1472 	var a = _getChildIdx(this.hex, info.vidx);
1473 	for (var i = 0; i < a.length; i++) {
1474 	    var hOID = _getVbyList(this.hex, a[i], [0], "06");
1475 	    var hName = _getVbyList(this.hex, a[i], [1], "86");
1476 	    if (hOID === "2b06010505073001") {
1477 		result.ocsp.push(hextoutf8(hName));
1478 	    }
1479 	    if (hOID === "2b06010505073002") {
1480 		result.caissuer.push(hextoutf8(hName));
1481 	    }
1482 	}
1483 
1484 	return result;
1485     };
1486 
1487     /**
1488      * get AuthorityInfoAccess extension value as JSON object
1489      * @name getExtAuthorityInfoAccess
1490      * @memberOf X509#
1491      * @function
1492      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1493      * @param {Boolean} critical flag (OPTIONAL)
1494      * @return {Array} JSON object of AuthorityInfoAccess parameters or undefined
1495      * @since jsrsasign 9.0.0 x509 2.0.0
1496      * @see {@link KJUR.asn1.x509.AuthorityInfoAccess}
1497      * @description
1498      * This method parse authorityInfoAccess extension. When arguments are
1499      * not specified, its extension in X509 object will be parsed.
1500      * Result of this method can be passed to 
1501      * {@link KJUR.asn1.x509.AuthorityInfoAccess} constructor.
1502      * <br>
1503      * When hExtV and critical specified as arguments, return value
1504      * will be generated from them.
1505      * @example
1506      * x = new X509();
1507      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1508      * x.getExtAuthorityInfoAccess() →
1509      * {
1510      *   critial: true, // 
1511      *   array: [{ocsp: http://ocsp.example.com/},
1512      *           {caissuer: https://repository.example.com/}]
1513      * }
1514      *
1515      * x = new X509();
1516      * x.getExtAuthorityInfoAccesss("306230...") 
1517      * x.getExtAuthorityInfoAccesss("306230...", true) 
1518      */
1519     this.getExtAuthorityInfoAccess = function(hExtV, critical) {
1520 	if (hExtV === undefined && critical === undefined) {
1521 	    var info = this.getExtInfo("authorityInfoAccess");
1522 	    if (info === undefined) return undefined;
1523 	    hExtV = _getTLV(this.hex, info.vidx);
1524 	    critical = info.critical;
1525 	}
1526 
1527 	var result = {extname:"authorityInfoAccess",array:[]};
1528 	if (critical) result.critical = true;
1529 
1530 	var a = _getChildIdx(hExtV, 0);
1531 	for (var i = 0; i < a.length; i++) {
1532 	    var hMethod = _getVbyListEx(hExtV, a[i], [0], "06");
1533 	    var hLoc = _getVbyList(hExtV, a[i], [1], "86");
1534 	    var sLoc = hextoutf8(hLoc);
1535 	    if (hMethod == "2b06010505073001") {
1536 		result.array.push({ocsp: sLoc});
1537 	    } else if (hMethod == "2b06010505073002") {
1538 		result.array.push({caissuer: sLoc});
1539 	    } else {
1540 		throw new Error("unknown method: " + hMethod);
1541 	    }
1542 	}
1543 
1544 	return result;
1545     }
1546 
1547     /**
1548      * get CertificatePolicies extension value as JSON object
1549      * @name getExtCertificatePolicies
1550      * @memberOf X509#
1551      * @function
1552      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1553      * @param {Boolean} critical flag (OPTIONAL)
1554      * @return {Object} JSON object of CertificatePolicies parameters or undefined
1555      * @since jsrsasign 7.2.0 x509 1.1.14
1556      * @description
1557      * This method will get certificate policies value
1558      * as an array of JSON object which has properties defined
1559      * in {@link KJUR.asn1.x509.CertificatePolicies}.
1560      * Result of this method can be passed to 
1561      * {@link KJUR.asn1.x509.CertificatePolicies} constructor.
1562      * If there is no this extension in the certificate,
1563      * it returns undefined.
1564      * <br>
1565      * CAUTION: return value of JSON object format have been changed
1566      * from jsrsasign 9.0.0 without backword compatibility.
1567      * <br>
1568      * When hExtV and critical specified as arguments, return value
1569      * will be generated from them.
1570      * @example
1571      * x = new X509();
1572      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1573      * x.getExtCertificatePolicies() → 
1574      * { array: [
1575      *   { policyoid: "1.2.3.4" }
1576      *   { policyoid: "1.2.3.5",
1577      *     array: [
1578      *       { cps: "https://example.com/" },
1579      *       { unotice: { exptext: { type: "bmp", str: "sample text" } } }
1580      *     ] 
1581      *   }
1582      * ]}
1583      */
1584     this.getExtCertificatePolicies = function(hExtV, critical) {
1585 	if (hExtV === undefined && critical === undefined) {
1586 	    var info = this.getExtInfo("certificatePolicies");
1587 	    if (info === undefined) return undefined;
1588 	    hExtV = _getTLV(this.hex, info.vidx);
1589 	    critical = info.critical;
1590 	}
1591 	var result = {extname:"certificatePolicies",array:[]};
1592 	if (critical) result.critical = true;
1593 
1594 	var aIdxPI = _getChildIdx(hExtV, 0); // PolicyInformation list index
1595 	for (var i = 0; i < aIdxPI.length; i++) {
1596 	    var hPolicyInformation = _getTLV(hExtV, aIdxPI[i]);
1597 	    var polinfo = this.getPolicyInformation(hPolicyInformation);
1598 	    result.array.push(polinfo);
1599 	}
1600 	return result;
1601     }
1602 
1603     /**
1604      * get PolicyInformation ASN.1 structure parameter as JSON object
1605      * @name getPolicyInformation
1606      * @memberOf X509#
1607      * @function
1608      * @param {String} h hexadecimal string of PolicyInformation
1609      * @return {Object} JSON object of PolicyInformation parameters
1610      * @since jsrsasign 9.0.0 x509 2.0.0
1611      * @description
1612      * This method will get PolicyInformation parameters defined in
1613      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
1614      * RFC 5280 4.2.1.4</a>.
1615      * <pre>
1616      * PolicyInformation ::= SEQUENCE {
1617      *      policyIdentifier   CertPolicyId,
1618      *      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
1619      *                              PolicyQualifierInfo OPTIONAL }
1620      * </pre>
1621      * Result of this method can be passed to
1622      * {@link KJUR.asn1.x509.PolicyInformation} constructor.
1623      * @example
1624      * x = new X509();
1625      * x.getPolicyInformation("30...") →
1626      * {
1627      *     policyoid: "2.16.840.1.114412.2.1",
1628      *     array: [{cps: "https://www.digicert.com/CPS"}]
1629      * }
1630      */
1631     this.getPolicyInformation = function(h) {
1632 	var result = {};
1633 
1634 	var hPOLICYOID = _getVbyList(h, 0, [0], "06");
1635 	result.policyoid = _oidname(hPOLICYOID);
1636 	
1637 	var idxPQSEQ = _getIdxbyListEx(h, 0, [1], "30");
1638 	if (idxPQSEQ != -1) {
1639 	    result.array = [];
1640 	    var aIdx = _getChildIdx(h, idxPQSEQ);
1641 	    for (var j = 0; j < aIdx.length; j++) {
1642 		var hPQI = _getTLV(h, aIdx[j]);
1643 		var pqinfo = this.getPolicyQualifierInfo(hPQI);
1644 		result.array.push(pqinfo);
1645 	    }
1646 	}
1647 
1648 	return result;
1649     };
1650 
1651     /**
1652      * get PolicyQualifierInfo ASN.1 structure parameter as JSON object
1653      * @name getPolicyQualifierInfo
1654      * @memberOf X509#
1655      * @function
1656      * @param {String} h hexadecimal string of PolicyQualifierInfo
1657      * @return {Object} JSON object of PolicyQualifierInfo parameters
1658      * @since jsrsasign 9.0.0 x509 2.0.0
1659      * @see {@link X509#getExtCertificatePolicies}
1660      * @see {@link X509#getPolicyInformation}
1661      * @description
1662      * This method will get 
1663      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
1664      * PolicyQualifierInfo</a> parameters.
1665      * <pre>
1666      * PolicyQualifierInfo ::= SEQUENCE {
1667      *      policyQualifierId  PolicyQualifierId,
1668      *      qualifier          ANY DEFINED BY policyQualifierId }
1669      * id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
1670      * id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
1671      * id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
1672      * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
1673      * Qualifier ::= CHOICE {
1674      *      cPSuri           CPSuri,
1675      *      userNotice       UserNotice }
1676      * CPSuri ::= IA5String
1677      * </pre>
1678      * Result of this method can be passed to 
1679      * {@link KJUR.asn1.x509.PolicyQualifierInfo} constructor.
1680      * @example
1681      * x = new X509();
1682      * x.getPolicyQualifierInfo("30...") 
1683      * → {unotice: {exptext: {type: 'utf8', str: 'aaa'}}}
1684      * x.getPolicyQualifierInfo("30...") 
1685      * → {cps: "https://repository.example.com/"}
1686      */
1687     this.getPolicyQualifierInfo = function(h) {
1688 	var result = {};
1689 	var hPQOID = _getVbyList(h, 0, [0], "06");
1690 	if (hPQOID === "2b06010505070201") { // cps
1691 	    var hCPSURI = _getVbyListEx(h, 0, [1], "16");
1692 	    result.cps = hextorstr(hCPSURI);
1693 	} else if (hPQOID === "2b06010505070202") { // unotice
1694 	    var hUserNotice = _getTLVbyList(h, 0, [1], "30");
1695 	    result.unotice = this.getUserNotice(hUserNotice);
1696 	}
1697 	return result;
1698     };
1699 
1700     /**
1701      * get UserNotice ASN.1 structure parameter as JSON object
1702      * @name getUserNotice
1703      * @memberOf X509#
1704      * @function
1705      * @param {String} h hexadecimal string of UserNotice
1706      * @return {Object} JSON object of UserNotice parameters
1707      * @since jsrsasign 9.0.0 x509 2.0.0
1708      * @see {@link X509#getExtCertificatePolicies}
1709      * @see {@link X509#getPolicyInformation}
1710      * @see {@link X509#getPolicyQualifierInfo}
1711      * @description
1712      * This method will get 
1713      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
1714      * UserNotice</a> parameters.
1715      * <pre>
1716      * UserNotice ::= SEQUENCE {
1717      *      noticeRef        NoticeReference OPTIONAL,
1718      *      explicitText     DisplayText OPTIONAL }
1719      * </pre>
1720      * Result of this method can be passed to 
1721      * {@link KJUR.asn1.x509.NoticeReference} constructor.
1722      * <br/>
1723      * NOTE: NoticeReference parsing is currently not supported and
1724      * it will be ignored.
1725      * @example
1726      * x = new X509();
1727      * x.getUserNotice("30...") → {exptext: {type: 'utf8', str: 'aaa'}}
1728      */
1729     this.getUserNotice = function(h) {
1730 	var result = {};
1731 	var a = _getChildIdx(h, 0);
1732 	for (var i = 0; i < a.length; i++) {
1733 	    var hItem = _getTLV(h, a[i]);
1734 	    if (hItem.substr(0, 2) != "30") {
1735 		result.exptext = this.getDisplayText(hItem);
1736 	    }
1737 	}
1738 	return result;
1739     };
1740 
1741     /**
1742      * get DisplayText ASN.1 structure parameter as JSON object
1743      * @name getDisplayText
1744      * @memberOf X509#
1745      * @function
1746      * @param {String} h hexadecimal string of DisplayText
1747      * @return {Object} JSON object of DisplayText parameters
1748      * @since jsrsasign 9.0.0 x509 2.0.0
1749      * @see {@link X509#getExtCertificatePolicies}
1750      * @see {@link X509#getPolicyInformation}
1751      * @description
1752      * This method will get 
1753      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
1754      * DisplayText</a> parameters.
1755      * <pre>
1756      * DisplayText ::= CHOICE {
1757      *      ia5String        IA5String      (SIZE (1..200)),
1758      *      visibleString    VisibleString  (SIZE (1..200)),
1759      *      bmpString        BMPString      (SIZE (1..200)),
1760      *      utf8String       UTF8String     (SIZE (1..200)) }     
1761      * </pre>
1762      * Result of this method can be passed to 
1763      * {@link KJUR.asn1.x509.DisplayText} constructor.
1764      * @example
1765      * x = new X509();
1766      * x.getDisplayText("0c03616161") &rarr {type: 'utf8', str: 'aaa'}
1767      * x.getDisplayText("1e03616161") &rarr {type: 'bmp',  str: 'aaa'}
1768      */
1769     this.getDisplayText = function(h) {
1770 	var _DISPLAYTEXTTAG = {"0c": "utf8", "16": "ia5", "1a": "vis" , "1e": "bmp"};
1771 	var result = {};
1772 	result.type = _DISPLAYTEXTTAG[h.substr(0, 2)];
1773 	result.str = hextorstr(_getV(h, 0));
1774 	return result;
1775     };
1776 
1777     /**
1778      * parse cRLNumber CRL extension as JSON object<br/>
1779      * @name getExtCRLNumber
1780      * @memberOf X509#
1781      * @function
1782      * @param {String} hExtV hexadecimal string of extension value
1783      * @param {Boolean} critical flag
1784      * @since jsrsasign 9.1.1 x509 2.0.1
1785      * @see {@link KJUR.asn1.x509.CRLNumber}
1786      * @see {@link X509#getExtParamArray}
1787      * @description
1788      * This method parses
1789      * CRLNumber CRL extension value defined in
1790      * <a href="https://tools.ietf.org/html/rfc5280#section-5.2.3">
1791      * RFC 5280 5.2.3</a> as JSON object.
1792      * <pre>
1793      * id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
1794      * CRLNumber ::= INTEGER (0..MAX)
1795      * </pre>
1796      * <br/>
1797      * Result of this method can be passed to 
1798      * {@link KJUR.asn1.x509.CRLNumber} constructor.
1799      * @example
1800      * crl = X509CRL("-----BEGIN X509 CRL...");
1801      * ... get hExtV and critical flag ...
1802      * crl.getExtCRLNumber("02...", false) →
1803      * {extname: "cRLNumber", num: {hex: "12af"}}
1804      */
1805     this.getExtCRLNumber = function(hExtV, critical) {
1806 	var result = {extname:"cRLNumber"};
1807 	if (critical) result.critical = true;
1808 
1809 	if (hExtV.substr(0, 2) == "02") {
1810 	    result.num = {hex: _getV(hExtV, 0)};
1811 	    return result;
1812 	}
1813 	throw new Error("hExtV parse error: " + hExtV);
1814     };
1815 
1816     /**
1817      * parse cRLReason CRL entry extension as JSON object<br/>
1818      * @name getExtCRLReason
1819      * @memberOf X509#
1820      * @function
1821      * @param {String} hExtV hexadecimal string of extension value
1822      * @param {Boolean} critical flag
1823      * @since jsrsasign 9.1.1 x509 2.0.1
1824      * @see {@link KJUR.asn1.x509.CRLReason}
1825      * @see {@link X509#getExtParamArray}
1826      * @description
1827      * This method parses
1828      * CRLReason CRL entry extension value defined in
1829      * <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1">
1830      * RFC 5280 5.3.1</a> as JSON object.
1831      * <pre>
1832      * id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
1833      * -- reasonCode ::= { CRLReason }
1834      * CRLReason ::= ENUMERATED {
1835      *      unspecified             (0),
1836      *      keyCompromise           (1),
1837      *      cACompromise            (2),
1838      *      affiliationChanged      (3),
1839      *      superseded              (4),
1840      *      cessationOfOperation    (5),
1841      *      certificateHold         (6),
1842      *      removeFromCRL           (8),
1843      *      privilegeWithdrawn      (9),
1844      *      aACompromise           (10) }
1845      * </pre>
1846      * <br/>
1847      * Result of this method can be passed to 
1848      * {@link KJUR.asn1.x509.CRLReason} constructor.
1849      * @example
1850      * crl = X509CRL("-----BEGIN X509 CRL...");
1851      * ... get hExtV and critical flag ...
1852      * crl.getExtCRLReason("02...", false) →
1853      * {extname: "cRLReason", code: 3}
1854      */
1855     this.getExtCRLReason = function(hExtV, critical) {
1856 	var result = {extname:"cRLReason"};
1857 	if (critical) result.critical = true;
1858 
1859 	if (hExtV.substr(0, 2) == "0a") {
1860 	    result.code = parseInt(_getV(hExtV, 0), 16);
1861 	    return result;
1862 	}
1863 	throw new Error("hExtV parse error: " + hExtV);
1864     };
1865 
1866     /**
1867      * parse OCSPNonce OCSP extension as JSON object<br/>
1868      * @name getExtOCSPNonce
1869      * @memberOf X509#
1870      * @function
1871      * @param {String} hExtV hexadecimal string of extension value
1872      * @param {Boolean} critical flag
1873      * @return {Array} JSON object of parsed OCSPNonce extension
1874      * @since jsrsasign 9.1.6 x509 2.0.3
1875      * @see {@link KJUR.asn1.x509.OCSPNonce}
1876      * @see {@link X509#getExtParamArray}
1877      * @see {@link X509#getExtParam}
1878      * @description
1879      * This method parses
1880      * Nonce OCSP extension value defined in
1881      * <a href="https://tools.ietf.org/html/rfc6960#section-4.4.1">
1882      * RFC 6960 4.4.1</a> as JSON object.
1883      * <pre>
1884      * id-pkix-ocsp           OBJECT IDENTIFIER ::= { id-ad-ocsp }
1885      * id-pkix-ocsp-nonce     OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 }
1886      * Nonce ::= OCTET STRING
1887      * </pre>
1888      * <br/>
1889      * Result of this method can be passed to 
1890      * {@link KJUR.asn1.x509.OCSPNonce} constructor.
1891      * @example
1892      * x = new X509();
1893      * x.getExtOCSPNonce(<<extn hex value >>) →
1894      * { extname: "ocspNonce", hex: "1a2b..." }
1895      */
1896     this.getExtOcspNonce = function(hExtV, critical) {
1897 	var result = {extname:"ocspNonce"};
1898 	if (critical) result.critical = true;
1899 
1900 	var hNonce = _getV(hExtV, 0);
1901 	result.hex = hNonce;
1902 
1903 	return result;
1904     };
1905 
1906     /**
1907      * parse OCSPNoCheck OCSP extension as JSON object<br/>
1908      * @name getExtOCSPNoCheck
1909      * @memberOf X509#
1910      * @function
1911      * @param {String} hExtV hexadecimal string of extension value
1912      * @param {Boolean} critical flag
1913      * @return {Array} JSON object of parsed OCSPNoCheck extension
1914      * @since jsrsasign 9.1.6 x509 2.0.3
1915      * @see {@link KJUR.asn1.x509.OCSPNoCheck}
1916      * @see {@link X509#getExtParamArray}
1917      * @see {@link X509#getExtParam}
1918      * @description
1919      * This method parses
1920      * OCSPNoCheck extension value defined in
1921      * <a href="https://tools.ietf.org/html/rfc6960#section-4.2.2.2.1">
1922      * RFC 6960 4.2.2.2.1</a> as JSON object.
1923      * <pre>
1924      * id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 }
1925      * </pre>
1926      * <br/>
1927      * Result of this method can be passed to 
1928      * {@link KJUR.asn1.x509.OCSPNoCheck} constructor.
1929      * @example
1930      * x = new X509();
1931      * x.getExtOCSPNoCheck(<<extn hex value >>) →
1932      * { extname: "ocspNoCheck" }
1933      */
1934     this.getExtOcspNoCheck = function(hExtV, critical) {
1935 	var result = {extname:"ocspNoCheck"};
1936 	if (critical) result.critical = true;
1937 
1938 	return result;
1939     };
1940 
1941     // ===== BEGIN X500Name related =====================================
1942 
1943     this.getX500NameRule = function(aDN) {
1944 	var isPRNRule = true;
1945 	var isUTF8Rule = true;
1946 	var isMixedRule = false;
1947 	var logfull = "";
1948 	var logcheck = "";
1949 	var lasttag = null;
1950 
1951 	var a = [];
1952 	for (var i = 0; i < aDN.length; i++) {
1953 	    var aRDN = aDN[i];
1954 	    for (var j = 0; j < aRDN.length; j++) {
1955 		a.push(aRDN[j]);
1956 	    }
1957 	}
1958 
1959 	for (var i = 0; i < a.length; i++) {
1960 	    var item = a[i];
1961 	    var tag = item.ds;
1962 	    var value = item.value;
1963 	    var type = item.type;
1964 	    logfull += ":" + tag;
1965 	    
1966 	    if (tag != "prn" && tag != "utf8" && tag != "ia5") {
1967 		return "mixed";
1968 	    }
1969 	    if (tag == "ia5") {
1970 		if (type != "CN") {
1971 		    return "mixed";
1972 		} else {
1973 		    if (! KJUR.lang.String.isMail(value)) {
1974 			return "mixed";
1975 		    } else {
1976 			continue;
1977 		    }
1978 		}
1979 	    }
1980 	    if (type == "C") {
1981 		if (tag == "prn") {
1982 		    continue;
1983 		} else {
1984 		    return "mixed";
1985 		}
1986 	    }
1987 	    logcheck += ":" + tag;
1988 	    if (lasttag == null) {
1989 		lasttag = tag;
1990 	    } else {
1991 		if (lasttag !== tag) return "mixed";
1992 	    }
1993 	}
1994 	if (lasttag == null) {
1995 	    return "prn";
1996 	} else {
1997 	    return lasttag;
1998 	}
1999     };
2000 
2001     /**
2002      * get Name ASN.1 structure parameter array<br/>
2003      * @name getX500Name
2004      * @memberOf X509#
2005      * @function
2006      * @param {String} h hexadecimal string of Name
2007      * @return {Array} array of RDN parameter array
2008      * @since jsrsasign 9.0.0 x509 2.0.0
2009      * @see {@link X509#getX500Name}
2010      * @see {@link X509#getRDN}
2011      * @see {@link X509#getAttrTypeAndValue}
2012      * @description
2013      * This method will get Name parameter defined in
2014      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2015      * RFC 5280 4.1.2.4</a>.
2016      * <pre>
2017      * Name ::= CHOICE { -- only one possibility for now --
2018      *   rdnSequence  RDNSequence }
2019      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
2020      * </pre>
2021      * @example
2022      * x = new X509();
2023      * x.getX500Name("30...") →
2024      * [[{type:"C",value:"US",ds:"prn"}],
2025      *  [{type:"O",value:"Sample Corp.",ds:"utf8"}],
2026      *  [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]]
2027      */
2028     this.getX500Name = function(h) {
2029 	var result = [];
2030 	var a = _getChildIdx(h, 0);
2031 	for (var i = 0; i < a.length; i++) {
2032 	    result.push(this.getRDN(_getTLV(h, a[i])));
2033 	}
2034 	return result;
2035     };
2036     
2037     /**
2038      * get RelativeDistinguishedName ASN.1 structure parameter array<br/>
2039      * @name getRDN
2040      * @memberOf X509#
2041      * @function
2042      * @param {String} h hexadecimal string of RDN
2043      * @return {Array} array of AttrTypeAndValue parameters
2044      * @since jsrsasign 9.0.0 x509 2.0.0
2045      * @see {@link X509#getX500Name}
2046      * @see {@link X509#getRDN}
2047      * @see {@link X509#getAttrTypeAndValue}
2048      * @description
2049      * This method will get RelativeDistinguishedName parameters defined in
2050      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2051      * RFC 5280 4.1.2.4</a>.
2052      * <pre>
2053      * RelativeDistinguishedName ::=
2054      *   SET SIZE (1..MAX) OF AttributeTypeAndValue
2055      * </pre>
2056      * @example
2057      * x = new X509();
2058      * x.getRDN("31...") →
2059      * [{type:"C",value:"US",ds:"prn"}] or
2060      * [{type:"O",value:"Sample Corp.",ds:"prn"}] or
2061      * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]
2062      */
2063     this.getRDN = function(h) {
2064 	var result = [];
2065 	var a = _getChildIdx(h, 0);
2066 	for (var i = 0; i < a.length; i++) {
2067 	    result.push(this.getAttrTypeAndValue(_getTLV(h, a[i])));
2068 	}
2069 	return result;
2070     };
2071 
2072     /**
2073      * get AttributeTypeAndValue ASN.1 structure parameter as JSON object<br/>
2074      * @name getAttrTypeAndValue
2075      * @memberOf X509#
2076      * @function
2077      * @param {String} h hexadecimal string of AttributeTypeAndValue
2078      * @return {Object} JSON object of AttributeTypeAndValue parameters
2079      * @since jsrsasign 9.0.0 x509 2.0.0
2080      * @see {@link X509#getX500Name}
2081      * @see {@link X509#getRDN}
2082      * @description
2083      * This method will get AttributeTypeAndValue parameters defined in
2084      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2085      * RFC 5280 4.1.2.4</a>.
2086      * <pre>
2087      * AttributeTypeAndValue ::= SEQUENCE {
2088      *   type     AttributeType,
2089      *   value    AttributeValue }
2090      * AttributeType ::= OBJECT IDENTIFIER
2091      * AttributeValue ::= ANY -- DEFINED BY AttributeType
2092      * </pre>
2093      * <ul>
2094      * <li>{String}type - AttributeType name or OID(ex. C,O,CN)</li>
2095      * <li>{String}value - raw string of ASN.1 value of AttributeValue</li>
2096      * <li>{String}ds - DirectoryString type of AttributeValue</li>
2097      * </ul>
2098      * "ds" has one of following value:
2099      * <ul>
2100      * <li>utf8 - (0x0c) UTF8String</li>
2101      * <li>prn  - (0x13) PrintableString</li>
2102      * <li>ia5  - (0x16) IA5String</li>
2103      * <li>vis  - (0x1a) VisibleString</li>
2104      * <li>bmp  - (0x1e) BMPString</li>
2105      * </ul>
2106      * @example
2107      * x = new X509();
2108      * x.getAttrTypeAndValue("30...") →
2109      * {type:"CN",value:"john.smith@example.com",ds:"ia5"} or
2110      * {type:"O",value:"Sample Corp.",ds:"prn"}
2111      */
2112     // tel  - (0x14) TeletexString ... for future
2113     // num  - (0x12) NumericString ... for future
2114     // unv  - (0x1c??) UniversalString ... for future
2115     this.getAttrTypeAndValue = function(h) {
2116 	var result = {type: null, value: null, ds: null};
2117 	var a = _getChildIdx(h, 0);
2118 	var hOID = _getVbyList(h, a[0], [], "06");
2119 	var hValue = _getVbyList(h, a[1], []);
2120 	var oid = KJUR.asn1.ASN1Util.oidHexToInt(hOID);
2121 	result.type = KJUR.asn1.x509.OID.oid2atype(oid);
2122 	result.value = hextorstr(hValue);
2123 	result.ds = this.HEX2STAG[h.substr(a[1], 2)];
2124 	return result;
2125     };
2126 
2127     // ===== END X500Name related =====================================
2128 
2129     // ===== BEGIN read certificate =====================================
2130     /**
2131      * read PEM formatted X.509 certificate from string.<br/>
2132      * @name readCertPEM
2133      * @memberOf X509#
2134      * @function
2135      * @param {String} sCertPEM string for PEM formatted X.509 certificate
2136      * @example
2137      * x = new X509();
2138      * x.readCertPEM(sCertPEM); // read certificate
2139      */
2140     this.readCertPEM = function(sCertPEM) {
2141         this.readCertHex(_pemtohex(sCertPEM));
2142     };
2143 
2144     /**
2145      * read a hexadecimal string of X.509 certificate<br/>
2146      * @name readCertHex
2147      * @memberOf X509#
2148      * @function
2149      * @param {String} sCertHex hexadecimal string of X.509 certificate
2150      * @since jsrsasign 7.1.4 x509 1.1.13
2151      * @description
2152      * NOTE: {@link X509#parseExt} will called internally since jsrsasign 7.2.0.
2153      * @example
2154      * x = new X509();
2155      * x.readCertHex("3082..."); // read certificate
2156      */
2157     this.readCertHex = function(sCertHex) {
2158         this.hex = sCertHex;
2159 	this.getVersion(); // set version parameter
2160 
2161 	try {
2162 	    _getIdxbyList(this.hex, 0, [0, 7], "a3"); // has [3] v3ext
2163 	    this.parseExt();
2164 	} catch(ex) {};
2165     };
2166 
2167     // ===== END read certificate =====================================
2168 
2169     /**
2170      * get JSON object of certificate parameters<br/>
2171      * @name getParam
2172      * @memberOf X509#
2173      * @function
2174      * @return {Array} JSON object of certificate parameters
2175      * @since jsrsasign 9.0.0 x509 2.0.0
2176      * @see KJUR.asn1.x509.X509Util.newCertPEM
2177      * @description
2178      * This method returns a JSON object of the certificate
2179      * parameters. Return value can be passed to
2180      * {@link KJUR.asn1.x509.X509Util.newCertPEM}.
2181      * @example
2182      * x = new X509();
2183      * x.readCertPEM("-----BEGIN CERTIFICATE...");
2184      * x.getParam() →
2185      * {version:3,
2186      *  serial:{hex:"12ab"},
2187      *  sigalg:"SHA256withRSA",
2188      *  issuer: {array:[[{type:'CN',value:'CA1',ds:'prn'}]],str:"/O=CA1"},
2189      *  notbefore:"160403023700Z",
2190      *  notafter:"160702023700Z",
2191      *  subject: {array:[[{type:'CN',value:'Test1',ds:'prn'}]],str:"/CN=Test1"},
2192      *  sbjpubkey:"-----BEGIN PUBLIC KEY...",
2193      *  ext:[
2194      *   {extname:"keyUsage",critical:true,names:["digitalSignature"]},
2195      *   {extname:"basicConstraints",critical:true},
2196      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
2197      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
2198      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
2199      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}
2200      *  }],
2201      *  sighex:"0b76...8"
2202      * };
2203      */
2204     this.getParam = function() {
2205 	var result = {};
2206 	result.version = this.getVersion();
2207 	result.serial = {hex: this.getSerialNumberHex()};
2208 	result.sigalg = this.getSignatureAlgorithmField();
2209 	result.issuer = this.getIssuer();
2210 	result.notbefore = this.getNotBefore();
2211 	result.notafter = this.getNotAfter();
2212 	result.subject = this.getSubject();
2213 	result.sbjpubkey = hextopem(this.getPublicKeyHex(), "PUBLIC KEY");
2214 	if (this.aExtInfo.length > 0) {
2215 	    result.ext = this.getExtParamArray();
2216 	}
2217 	result.sighex = this.getSignatureValueHex();
2218 	return result;
2219     };
2220 
2221     /** 
2222      * get array of certificate extension parameter JSON object<br/>
2223      * @name getExtParamArray
2224      * @memberOf X509#
2225      * @function
2226      * @param {String} hExtSeq hexadecimal string of SEQUENCE of Extension
2227      * @return {Array} array of certificate extension parameter JSON object
2228      * @since jsrsasign 9.0.0 x509 2.0.0
2229      * @see KJUR.asn1.x509.X509Util.newCertPEM
2230      * @see X509#getParam
2231      * @see X509#getExtParam
2232      * @see X509CRL#getParam
2233      * @see KJUR.asn1.csr.CSRUtil.getParam
2234      *
2235      * @description
2236      * This method returns an array of certificate extension
2237      * parameters. 
2238      * <br/>
2239      * NOTE: Argument "hExtSeq" have been supported since jsrsasign 9.1.1.
2240      *
2241      * @example
2242      * x = new X509();
2243      * x.readCertPEM("-----BEGIN CERTIFICATE...");
2244      * x.getExtParamArray() →
2245      * [ {extname:"keyUsage",critical:true,names:["digitalSignature"]},
2246      *   {extname:"basicConstraints",critical:true},
2247      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
2248      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
2249      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
2250      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}]
2251      */
2252     this.getExtParamArray = function(hExtSeq) {
2253 	if (hExtSeq == undefined) {
2254 	    // for X.509v3 certificate
2255 	    var idx1 = _getIdxbyListEx(this.hex, 0, [0, "[3]"]);
2256 	    if (idx1 != -1) {
2257 		hExtSeq = _getTLVbyListEx(this.hex, 0, [0, "[3]", 0], "30");
2258 	    }
2259 	}
2260 	var result = [];
2261 	var aIdx = _getChildIdx(hExtSeq, 0);
2262 
2263 	for (var i = 0; i < aIdx.length; i++) {
2264 	    var hExt = _getTLV(hExtSeq, aIdx[i]);
2265 	    var extParam = this.getExtParam(hExt);
2266 	    if (extParam != null) result.push(extParam);
2267 	}
2268 
2269 	return result;
2270     };
2271 
2272     /** 
2273      * get a extension parameter JSON object<br/>
2274      * @name getExtParam
2275      * @memberOf X509#
2276      * @function
2277      * @param {String} hExt hexadecimal string of Extension
2278      * @return {Array} Extension parameter JSON object
2279      * @since jsrsasign 9.1.1 x509 2.0.1
2280      * @see KJUR.asn1.x509.X509Util.newCertPEM
2281      * @see X509#getParam
2282      * @see X509#getExtParamArray
2283      * @see X509CRL#getParam
2284      * @see KJUR.asn1.csr.CSRUtil.getParam
2285      *
2286      * @description
2287      * This method returns a extension parameters as JSON object. 
2288      *
2289      * @example
2290      * x = new X509();
2291      * ...
2292      * x.getExtParam("30...") →
2293      * {extname:"keyUsage",critical:true,names:["digitalSignature"]}
2294      */
2295     this.getExtParam = function(hExt) {
2296 	var result = {};
2297 	var aIdx = _getChildIdx(hExt, 0);
2298 	var aIdxLen = aIdx.length;
2299 	if (aIdxLen != 2 && aIdxLen != 3)
2300 	    throw new Error("wrong number elements in Extension: " + 
2301 			    aIdxLen + " " + hExt);
2302 
2303 	var oid = _hextooidstr(_getVbyList(hExt, 0, [0], "06"));
2304 
2305 	var critical = false;
2306 	if (aIdxLen == 3 && _getTLVbyList(hExt, 0, [1]) == "0101ff")
2307 	    critical = true;
2308 
2309 	var hExtV = _getTLVbyList(hExt, 0, [aIdxLen - 1, 0]);
2310 
2311 	var extParam = undefined;
2312 	if (oid == "2.5.29.14") {
2313 	    extParam = this.getExtSubjectKeyIdentifier(hExtV, critical);
2314 	} else if (oid == "2.5.29.15") {
2315 	    extParam = this.getExtKeyUsage(hExtV, critical);
2316 	} else if (oid == "2.5.29.17") {
2317 	    extParam = this.getExtSubjectAltName(hExtV, critical);
2318 	} else if (oid == "2.5.29.18") {
2319 	    extParam = this.getExtIssuerAltName(hExtV, critical);
2320 	} else if (oid == "2.5.29.19") {
2321 	    extParam = this.getExtBasicConstraints(hExtV, critical);
2322 	} else if (oid == "2.5.29.31") {
2323 	    extParam = this.getExtCRLDistributionPoints(hExtV, critical);
2324 	} else if (oid == "2.5.29.32") {
2325 	    extParam = this.getExtCertificatePolicies(hExtV, critical);
2326 	} else if (oid == "2.5.29.35") {
2327 	    extParam = this.getExtAuthorityKeyIdentifier(hExtV, critical);
2328 	} else if (oid == "2.5.29.37") {
2329 	    extParam = this.getExtExtKeyUsage(hExtV, critical);
2330 	} else if (oid == "1.3.6.1.5.5.7.1.1") {
2331 	    extParam = this.getExtAuthorityInfoAccess(hExtV, critical);
2332 	} else if (oid == "2.5.29.20") {
2333 	    extParam = this.getExtCRLNumber(hExtV, critical);
2334 	} else if (oid == "2.5.29.21") {
2335 	    extParam = this.getExtCRLReason(hExtV, critical);
2336 	} else if (oid == "1.3.6.1.5.5.7.48.1.2") {
2337 	    extParam = this.getExtOcspNonce(hExtV, critical);
2338 	} else if (oid == "1.3.6.1.5.5.7.48.1.5") {
2339 	    extParam = this.getExtOcspNoCheck(hExtV, critical);
2340 	}
2341 	if (extParam != undefined) return extParam;
2342 
2343 	var privateParam = { extname: oid, extn: hExtV };
2344 	if (critical) privateParam.critical = true;
2345 	return privateParam;
2346     };
2347 
2348     /**
2349      * get certificate information as string.<br/>
2350      * @name getInfo
2351      * @memberOf X509#
2352      * @function
2353      * @return {String} certificate information string
2354      * @since jsrsasign 5.0.10 x509 1.1.8
2355      * @example
2356      * x = new X509();
2357      * x.readCertPEM(certPEM);
2358      * console.log(x.getInfo());
2359      * // this shows as following
2360      * Basic Fields
2361      *   serial number: 02ac5c266a0b409b8f0b79f2ae462577
2362      *   signature algorithm: SHA1withRSA
2363      *   issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
2364      *   notBefore: 061110000000Z
2365      *   notAfter: 311110000000Z
2366      *   subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
2367      *   subject public key info:
2368      *     key algorithm: RSA
2369      *     n=c6cce573e6fbd4bb...
2370      *     e=10001
2371      * X509v3 Extensions:
2372      *   keyUsage CRITICAL:
2373      *     digitalSignature,keyCertSign,cRLSign
2374      *   basicConstraints CRITICAL:
2375      *     cA=true
2376      *   subjectKeyIdentifier :
2377      *     b13ec36903f8bf4701d498261a0802ef63642bc3
2378      *   authorityKeyIdentifier :
2379      *     kid=b13ec36903f8bf4701d498261a0802ef63642bc3
2380      * signature algorithm: SHA1withRSA
2381      * signature: 1c1a0697dcd79c9f...
2382      */
2383     this.getInfo = function() {
2384 	var _getSubjectAltNameStr = function(params) {
2385 	    var s = JSON.stringify(params.array).replace(/[\[\]\{\}\"]/g, '');
2386 	    return s;
2387 	};
2388 	var _getCertificatePoliciesStr = function(params) {
2389 	    var s = "";
2390 	    var a = params.array;
2391 	    for (var i = 0; i < a.length; i++) {
2392 		var pi = a[i];
2393 		s += "    policy oid: " + pi.policyoid + "\n";
2394 		if (pi.array === undefined) continue;
2395 		for (var j = 0; j < pi.array.length; j++) {
2396 		    var pqi = pi.array[j];
2397 		    if (pqi.cps !== undefined) {
2398 			s += "    cps: " + pqi.cps + "\n";
2399 		    }
2400 		}
2401 	    }
2402 	    return s;
2403 	};
2404 	var _getCRLDistributionPointsStr = function(params) {
2405 	    var s = "";
2406 	    var a = params.array;
2407 	    for (var i = 0; i < a.length; i++) {
2408 		var dp = a[i];
2409 		try {
2410 		    if (dp.dpname.full[0].uri !== undefined)
2411 			s += "    " + dp.dpname.full[0].uri + "\n";
2412 		} catch(ex) {};
2413 		try {
2414 		    if (dp.dname.full[0].dn.hex !== undefined)
2415 			s += "    " + X509.hex2dn(dp.dpname.full[0].dn.hex) + "\n";
2416 		} catch(ex) {};
2417 	    }
2418 	    return s;
2419 	}
2420 	var _getAuthorityInfoAccessStr = function(params) {
2421 	    var s = "";
2422 	    var a = params.array;
2423 	    for (var i = 0; i < a.length; i++) {
2424 		var ad = a[i];
2425 
2426 		if (ad.caissuer !== undefined)
2427 		    s += "    caissuer: " + ad.caissuer + "\n";
2428 		if (ad.ocsp !== undefined)
2429 		    s += "    ocsp: " + ad.ocsp + "\n";
2430 	    }
2431 	    return s;
2432 	};
2433 	var _X509 = X509;
2434 	var s, pubkey, aExt;
2435 	s  = "Basic Fields\n";
2436         s += "  serial number: " + this.getSerialNumberHex() + "\n";
2437 	s += "  signature algorithm: " + this.getSignatureAlgorithmField() + "\n";
2438 	s += "  issuer: " + this.getIssuerString() + "\n";
2439 	s += "  notBefore: " + this.getNotBefore() + "\n";
2440 	s += "  notAfter: " + this.getNotAfter() + "\n";
2441 	s += "  subject: " + this.getSubjectString() + "\n";
2442 	s += "  subject public key info: " + "\n";
2443 
2444 	// subject public key info
2445 	pubkey = this.getPublicKey();
2446 	s += "    key algorithm: " + pubkey.type + "\n";
2447 
2448 	if (pubkey.type === "RSA") {
2449 	    s += "    n=" + hextoposhex(pubkey.n.toString(16)).substr(0, 16) + "...\n";
2450 	    s += "    e=" + hextoposhex(pubkey.e.toString(16)) + "\n";
2451 	}
2452 
2453 	// X.509v3 Extensions
2454         aExt = this.aExtInfo;
2455 
2456 	if (aExt !== undefined && aExt !== null) {
2457             s += "X509v3 Extensions:\n";
2458 	    
2459             for (var i = 0; i < aExt.length; i++) {
2460 		var info = aExt[i];
2461 
2462 		// show extension name and critical flag
2463 		var extName = KJUR.asn1.x509.OID.oid2name(info["oid"]);
2464 		if (extName === '') extName = info["oid"];
2465 
2466 		var critical = '';
2467 		if (info["critical"] === true) critical = "CRITICAL";
2468 
2469 		s += "  " + extName + " " + critical + ":\n";
2470 
2471 		// show extension value if supported
2472 		if (extName === "basicConstraints") {
2473 		    var bc = this.getExtBasicConstraints();
2474 		    if (bc.cA === undefined) {
2475 			s += "    {}\n";
2476 		    } else {
2477 			s += "    cA=true";
2478 			if (bc.pathLen !== undefined)
2479 			    s += ", pathLen=" + bc.pathLen;
2480 			s += "\n";
2481 		    }
2482 		} else if (extName === "keyUsage") {
2483 		    s += "    " + this.getExtKeyUsageString() + "\n";
2484 		} else if (extName === "subjectKeyIdentifier") {
2485 		    s += "    " + this.getExtSubjectKeyIdentifier().kid.hex + "\n";
2486 		} else if (extName === "authorityKeyIdentifier") {
2487 		    var akid = this.getExtAuthorityKeyIdentifier();
2488 		    if (akid.kid !== undefined)
2489 			s += "    kid=" + akid.kid.hex + "\n";
2490 		} else if (extName === "extKeyUsage") {
2491 		    var eku = this.getExtExtKeyUsage().array;
2492 		    s += "    " + eku.join(", ") + "\n";
2493 		} else if (extName === "subjectAltName") {
2494 		    var san = _getSubjectAltNameStr(this.getExtSubjectAltName());
2495 		    s += "    " + san + "\n";
2496 		} else if (extName === "cRLDistributionPoints") {
2497 		    var cdp = this.getExtCRLDistributionPoints();
2498 		    s += _getCRLDistributionPointsStr(cdp);
2499 		} else if (extName === "authorityInfoAccess") {
2500 		    var aia = this.getExtAuthorityInfoAccess();
2501 		    s += _getAuthorityInfoAccessStr(aia);
2502 		} else if (extName === "certificatePolicies") {
2503 		    s += _getCertificatePoliciesStr(this.getExtCertificatePolicies());
2504 		}
2505 	    }
2506         }
2507 
2508 	s += "signature algorithm: " + this.getSignatureAlgorithmName() + "\n";
2509 	s += "signature: " + this.getSignatureValueHex().substr(0, 16) + "...\n";
2510 	return s;
2511     };
2512 };
2513 
2514 /**
2515  * get distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER X.500 name<br/>
2516  * @name hex2dn
2517  * @memberOf X509
2518  * @function
2519  * @param {String} hex hexadecimal string of ASN.1 DER distinguished name
2520  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
2521  * @return {String} OpenSSL online format distinguished name
2522  * @description
2523  * This static method converts from a hexadecimal string of 
2524  * distinguished name (DN)
2525  * specified by 'hex' and 'idx' to OpenSSL oneline string representation (ex. /C=US/O=a).
2526  * @example
2527  * X509.hex2dn("3031310b3...") → /C=US/O=a/CN=b2+OU=b1
2528  */
2529 X509.hex2dn = function(hex, idx) {
2530     if (idx === undefined) idx = 0;
2531     if (hex.substr(idx, 2) !== "30") throw new Error("malformed DN");
2532 
2533     var a = new Array();
2534 
2535     var aIdx = ASN1HEX.getChildIdx(hex, idx);
2536     for (var i = 0; i < aIdx.length; i++) {
2537 	a.push(X509.hex2rdn(hex, aIdx[i]));
2538     }
2539 
2540     a = a.map(function(s) { return s.replace("/", "\\/"); });
2541     return "/" + a.join("/");
2542 };
2543 
2544 /**
2545  * get relative distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER RDN<br/>
2546  * @name hex2rdn
2547  * @memberOf X509
2548  * @function
2549  * @param {String} hex hexadecimal string of ASN.1 DER concludes relative distinguished name
2550  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
2551  * @return {String} OpenSSL online format relative distinguished name
2552  * @description
2553  * This static method converts from a hexadecimal string of 
2554  * relative distinguished name (RDN)
2555  * specified by 'hex' and 'idx' to LDAP string representation (ex. O=test+CN=test).<br/>
2556  * NOTE: Multi-valued RDN is supported since jsnrsasign 6.2.2 x509 1.1.10.
2557  * @example
2558  * X509.hex2rdn("310a3008060355040a0c0161") → O=a
2559  * X509.hex2rdn("31143008060355040a0c01613008060355040a0c0162") → O=a+O=b
2560  */
2561 X509.hex2rdn = function(hex, idx) {
2562     if (idx === undefined) idx = 0;
2563     if (hex.substr(idx, 2) !== "31") throw new Error("malformed RDN");
2564 
2565     var a = new Array();
2566 
2567     var aIdx = ASN1HEX.getChildIdx(hex, idx);
2568     for (var i = 0; i < aIdx.length; i++) {
2569 	a.push(X509.hex2attrTypeValue(hex, aIdx[i]));
2570     }
2571 
2572     a = a.map(function(s) { return s.replace("+", "\\+"); });
2573     return a.join("+");
2574 };
2575 
2576 /**
2577  * get string from hexadecimal string of ASN.1 DER AttributeTypeAndValue<br/>
2578  * @name hex2attrTypeValue
2579  * @memberOf X509
2580  * @function
2581  * @param {String} hex hexadecimal string of ASN.1 DER concludes AttributeTypeAndValue
2582  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
2583  * @return {String} string representation of AttributeTypeAndValue (ex. C=US)
2584  * @description
2585  * This static method converts from a hexadecimal string of AttributeTypeAndValue
2586  * specified by 'hex' and 'idx' to LDAP string representation (ex. C=US).
2587  * @example
2588  * X509.hex2attrTypeValue("3008060355040a0c0161") → O=a
2589  * X509.hex2attrTypeValue("300806035504060c0161") → C=a
2590  * X509.hex2attrTypeValue("...3008060355040a0c0161...", 128) → O=a
2591  */
2592 X509.hex2attrTypeValue = function(hex, idx) {
2593     var _ASN1HEX = ASN1HEX;
2594     var _getV = _ASN1HEX.getV;
2595 
2596     if (idx === undefined) idx = 0;
2597     if (hex.substr(idx, 2) !== "30") 
2598 	throw new Error("malformed attribute type and value");
2599 
2600     var aIdx = _ASN1HEX.getChildIdx(hex, idx);
2601     if (aIdx.length !== 2 || hex.substr(aIdx[0], 2) !== "06")
2602 	"malformed attribute type and value";
2603 
2604     var oidHex = _getV(hex, aIdx[0]);
2605     var oidInt = KJUR.asn1.ASN1Util.oidHexToInt(oidHex);
2606     var atype = KJUR.asn1.x509.OID.oid2atype(oidInt);
2607 
2608     var hV = _getV(hex, aIdx[1]);
2609     var rawV = hextorstr(hV);
2610 
2611     return atype + "=" + rawV;
2612 };
2613 
2614 /**
2615  * get RSA/DSA/ECDSA public key object from X.509 certificate hexadecimal string<br/>
2616  * @name getPublicKeyFromCertHex
2617  * @memberOf X509
2618  * @function
2619  * @param {String} h hexadecimal string of X.509 certificate for RSA/ECDSA/DSA public key
2620  * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
2621  * @since jsrasign 7.1.0 x509 1.1.11
2622  */
2623 X509.getPublicKeyFromCertHex = function(h) {
2624     var x = new X509();
2625     x.readCertHex(h);
2626     return x.getPublicKey();
2627 };
2628 
2629 /**
2630  * get RSA/DSA/ECDSA public key object from PEM certificate string
2631  * @name getPublicKeyFromCertPEM
2632  * @memberOf X509
2633  * @function
2634  * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
2635  * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
2636  * @since x509 1.1.1
2637  * @description
2638  * NOTE: DSA is also supported since x509 1.1.2.
2639  */
2640 X509.getPublicKeyFromCertPEM = function(sCertPEM) {
2641     var x = new X509();
2642     x.readCertPEM(sCertPEM);
2643     return x.getPublicKey();
2644 };
2645 
2646 /**
2647  * get public key information from PEM certificate
2648  * @name getPublicKeyInfoPropOfCertPEM
2649  * @memberOf X509
2650  * @function
2651  * @param {String} sCertPEM string of PEM formatted certificate
2652  * @return {Hash} hash of information for public key
2653  * @since x509 1.1.1
2654  * @description
2655  * Resulted associative array has following properties:<br/>
2656  * <ul>
2657  * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li>
2658  * <li>algparam - hexadecimal string of OID of ECC curve name or null</li>
2659  * <li>keyhex - hexadecimal string of key in the certificate</li>
2660  * </ul>
2661  * NOTE: X509v1 certificate is also supported since x509.js 1.1.9.
2662  */
2663 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
2664     var _ASN1HEX = ASN1HEX;
2665     var _getVbyList = _ASN1HEX.getVbyList;
2666 
2667     var result = {};
2668     var x, hSPKI, pubkey;
2669     result.algparam = null;
2670 
2671     x = new X509();
2672     x.readCertPEM(sCertPEM);
2673 
2674     hSPKI = x.getPublicKeyHex();
2675     result.keyhex = _getVbyList(hSPKI, 0, [1], "03").substr(2);
2676     result.algoid = _getVbyList(hSPKI, 0, [0, 0], "06");
2677 
2678     if (result.algoid === "2a8648ce3d0201") { // ecPublicKey
2679 	result.algparam = _getVbyList(hSPKI, 0, [0, 1], "06");
2680     };
2681 
2682     return result;
2683 };
2684 
2685 /* ======================================================================
2686  *   Specific V3 Extensions
2687  * ====================================================================== */
2688 
2689 X509.KEYUSAGE_NAME = [
2690     "digitalSignature",
2691     "nonRepudiation",
2692     "keyEncipherment",
2693     "dataEncipherment",
2694     "keyAgreement",
2695     "keyCertSign",
2696     "cRLSign",
2697     "encipherOnly",
2698     "decipherOnly"
2699 ];
2700