1 /* x509-2.1.1.js (c) 2012-2022 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-2022 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 10.6.1 x509 2.1.1 (2022-Nov-20)
 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>policyMappings - {@link X509#getExtPolicyMappings}</li>
 71  *   <li>policyConstraints - {@link X509#getExtPolicyConstraints}</li>
 72  *   <li>inhibitAnyPolicy - {@link X509#getExtInhibitAnyPolicy}</li>
 73  *   <li>subjectAltName - {@link X509#getExtSubjectAltName}</li>
 74  *   <li>subjectAltName2 - {@link X509#getExtSubjectAltName2} (DEPRECATED)</li>
 75  *   <li>issuerAltName - {@link X509#getExtIssuerAltName}</li>
 76  *   <li>basicConstraints - {@link X509#getExtBasicConstraints}</li>
 77  *   <li>nameConstraints - {@link X509#getExtNameConstraints}</li>
 78  *   <li>extKeyUsage - {@link X509#getExtExtKeyUsage}</li>
 79  *   <li>extKeyUsage - {@link X509#getExtExtKeyUsageName} (DEPRECATED)</li>
 80  *   <li>cRLDistributionPoints - {@link X509#getExtCRLDistributionPoints}</li>
 81  *   <li>cRLDistributionPoints - {@link X509#getExtCRLDistributionPointsURI} (DEPRECATED)</li>
 82  *   <li>authorityInfoAccess - {@link X509#getExtAuthorityInfoAccess}</li>
 83  *   <li>authorityInfoAccess - {@link X509#getExtAIAInfo} (DEPRECATED)</li>
 84  *   <li>cRLNumber - {@link X509#getExtCRLNumber}</li>
 85  *   <li>cRLReason - {@link X509#getExtCRLReason}</li>
 86  *   <li>ocspNonce - {@link X509#getExtOcspNonce}</li>
 87  *   <li>ocspNoCheck - {@link X509#getExtOcspNoCheck}</li>
 88  *   <li>adobeTimeStamp - {@link X509#getExtAdobeTimeStamp}</li>
 89  *   </ul>
 90  * </li>
 91  * <li><b>UTILITIES</b>
 92  *   <ul>
 93  *   <li>reading PEM X.509 certificate - {@link X509#readCertPEM}</li>
 94  *   <li>reading hexadecimal string of X.509 certificate - {@link X509#readCertHex}</li>
 95  *   <li>get all certificate information - {@link X509#getInfo}</li>
 96  *   <li>get specified extension information - {@link X509#getExtInfo}</li>
 97  *   <li>verify signature value - {@link X509#verifySignature}</li>
 98  *   <li>utility for extensions - {@link X509#getCriticalExtV}</li>
 99  *   </ul>
100  * </li>
101  * </ul>
102  */
103 function X509(params) {
104     var _ASN1HEX = ASN1HEX,
105 	_getChildIdx = _ASN1HEX.getChildIdx,
106 	_getV = _ASN1HEX.getV,
107 	_dump = _ASN1HEX.dump,
108 	_ASN1HEX_parse = _ASN1HEX.parse,
109 	_getTLV = _ASN1HEX.getTLV,
110 	_getVbyList = _ASN1HEX.getVbyList,
111 	_getVbyListEx = _ASN1HEX.getVbyListEx,
112 	_getTLVbyList = _ASN1HEX.getTLVbyList,
113 	_getTLVbyListEx = _ASN1HEX.getTLVbyListEx,
114 	_getIdxbyList = _ASN1HEX.getIdxbyList,
115 	_getIdxbyListEx = _ASN1HEX.getIdxbyListEx,
116 	_getVidx = _ASN1HEX.getVidx,
117 	_getInt = _ASN1HEX.getInt,
118 	_oidname = _ASN1HEX.oidname,
119 	_hextooidstr = _ASN1HEX.hextooidstr,
120 	_X509 = X509,
121 	_pemtohex = pemtohex,
122 	_PSSNAME2ASN1TLV,
123 	_Error = Error;
124 
125     try {
126 	_PSSNAME2ASN1TLV = KJUR.asn1.x509.AlgorithmIdentifier.PSSNAME2ASN1TLV;
127     } catch (ex) {};
128     this.HEX2STAG = {"0c": "utf8", "13": "prn", "16": "ia5",
129 		     "1a": "vis" , "1e": "bmp"};
130 
131     this.hex = null;
132     this.version = 0; // version (1: X509v1, 3: X509v3, others: unspecified)
133     this.foffset = 0; // field index offset (-1: for X509v1, 0: for X509v3)
134     this.aExtInfo = null;
135 
136     // ===== get basic fields from hex =====================================
137 
138     /**
139      * get format version (X.509v1 or v3 certificate)<br/>
140      * @name getVersion
141      * @memberOf X509#
142      * @function
143      * @return {Number} 1 for X509v1, 3 for X509v3, otherwise 0
144      * @since jsrsasign 7.1.14 x509 1.1.13
145      * @description
146      * This method returns a format version of X.509 certificate.
147      * It returns 1 for X.509v1 certificate and 3 for v3 certificate.
148      * Otherwise returns 0.
149      * This method will be automatically called in
150      * {@link X509#readCertPEM}. After then, you can use
151      * {@link X509.version} parameter.
152      * @example
153      * var x = new X509();
154      * x.readCertPEM(sCertPEM);
155      * version = x.getVersion();    // 1 or 3
156      * sn = x.getSerialNumberHex(); // return string like "01ad..."
157      */
158     this.getVersion = function() {
159 	if (this.hex === null || this.version !== 0) return this.version;
160 
161 	// check if the first item of tbsCertificate "[0] { INTEGER 2 }"
162 	var hFirstObj = _getTLVbyList(this.hex, 0, [0, 0]);
163 	if (hFirstObj.substr(0, 2) == "a0") {
164 	    var hVersionTLV = _getTLVbyList(hFirstObj, 0, [0]);
165 	    var iVersion = _getInt(hVersionTLV, 0);
166 	    if (iVersion < 0 || 2 < iVersion) {
167 		throw new Error("malformed version field");
168 	    }
169 	    this.version = iVersion + 1;
170 	    return this.version;
171 	} else {
172 	    this.version = 1;
173 	    this.foffset = -1;
174 	    return 1;
175 	}
176     };
177 
178     /**
179      * get hexadecimal string of serialNumber field of certificate.<br/>
180      * @name getSerialNumberHex
181      * @memberOf X509#
182      * @function
183      * @return {String} hexadecimal string of certificate serial number
184      * @example
185      * var x = new X509();
186      * x.readCertPEM(sCertPEM);
187      * var sn = x.getSerialNumberHex(); // return string like "01ad..."
188      */
189     this.getSerialNumberHex = function() {
190 	return _getVbyListEx(this.hex, 0, [0, 0], "02");
191     };
192 
193     /**
194      * get signature algorithm name in basic field
195      * @name getSignatureAlgorithmField
196      * @memberOf X509#
197      * @function
198      * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA, SHA512withRSAandMGF1)
199      * @since x509 1.1.8
200      * @see X509#getAlgorithmIdentifierName
201      * @description
202      * This method will get a name of signature algorithm in 
203      * basic field of certificate.
204      * <br/>
205      * NOTE: From jsrsasign 8.0.21, RSA-PSS certificate is also supported.
206      * For supported RSA-PSS algorithm name and PSS parameters,
207      * see {@link X509#getSignatureAlgorithmField}.
208      * @example
209      * var x = new X509();
210      * x.readCertPEM(sCertPEM);
211      * algName = x.getSignatureAlgorithmField();
212      */
213     this.getSignatureAlgorithmField = function() {
214 	var hTLV = _getTLVbyListEx(this.hex, 0, [0, 1]);
215 	return this.getAlgorithmIdentifierName(hTLV);
216     };
217 
218     /**
219      * get algorithm name name of AlgorithmIdentifier ASN.1 structure
220      * @name getAlgorithmIdentifierName
221      * @memberOf X509#
222      * @function
223      * @param {String} hTLV hexadecimal string of AlgorithmIdentifier
224      * @return {String} algorithm name (ex. SHA1withRSA, SHA256withECDSA, SHA512withRSAandMGF1, SHA1)
225      * @since jsrsasign 9.0.0 x509 2.0.0
226      * @description
227      * This method will get a name of AlgorithmIdentifier.
228      * <br/>
229      * @example
230      * var x = new X509();
231      * algName = x.getAlgorithmIdentifierName("30...");
232      */
233     this.getAlgorithmIdentifierName = function(hTLV) {
234 	for (var key in _PSSNAME2ASN1TLV) {
235 	    if (hTLV === _PSSNAME2ASN1TLV[key]) {
236 		return key;
237 	    }
238 	}
239 	return _oidname(_getVbyListEx(hTLV, 0, [0], "06"));
240     };
241 
242     /**
243      * get JSON object of issuer field<br/>
244      * @name getIssuer
245      * @memberOf X509#
246      * @function
247      * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false)
248      * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false)
249      * @return {Array} JSON object of issuer field
250      * @since jsrsasign 9.0.0 x509 2.0.0
251      * @see X509#getX500Name
252      *
253      * @description
254      * Get a JSON object of an issuer field.
255      * <br>
256      * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 
257      * supported to conclude a canonicalized name for caseIgnoreMatch
258      * desribed in <a href="https://tools.ietf.org/html/rfc4518">
259      * RFC 4518</a>.
260      *
261      * @example
262      * var x = new X509(sCertPEM);
263      * x.getIssuer() →
264      * { array: [[{type:'C',value:'JP',ds:'prn'}],...],
265      *   str: "/C=JP/..." }
266      *
267      * // with flags
268      * x.getIssuer(true, true) →
269      * { array: ...,
270      *   str: "/C=JP/O=   Test    123   ",
271      *   canon: "/c=jp/o=test 123",
272      *   hex: "30..." }
273      */
274     this.getIssuer = function(flagCanon, flagHex) {
275 	return this.getX500Name(this.getIssuerHex(), flagCanon, flagHex);
276     };
277 
278     /**
279      * get hexadecimal string of issuer field TLV of certificate.<br/>
280      * @name getIssuerHex
281      * @memberOf X509#
282      * @function
283      * @return {String} hexadecial string of issuer DN ASN.1
284      * @example
285      * var x = new X509();
286      * x.readCertPEM(sCertPEM);
287      * var issuer = x.getIssuerHex(); // return string like "3013..."
288      */
289     this.getIssuerHex = function() {
290 	return _getTLVbyList(this.hex, 0, [0, 3 + this.foffset], "30");
291     };
292 
293     /**
294      * get string of issuer field of certificate.<br/>
295      * @name getIssuerString
296      * @memberOf X509#
297      * @function
298      * @return {String} issuer DN string
299      * @see X509#getIssuer
300      * @example
301      * var x = new X509();
302      * x.readCertPEM(sCertPEM);
303      * var dn1 = x.getIssuerString(); // return string like "/C=US/O=TEST"
304      * var dn2 = KJUR.asn1.x509.X500Name.compatToLDAP(dn1); // returns "O=TEST, C=US"
305      */
306     this.getIssuerString = function() {
307 	var pIssuer = this.getIssuer();
308 	return pIssuer.str;
309     };
310 
311     /**
312      * get JSON object of subject field<br/>
313      * @name getSubject
314      * @memberOf X509#
315      * @function
316      * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false)
317      * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false)
318      * @return {object} JSON object of subject field
319      * @since jsrsasign 9.0.0 x509 2.0.0
320      * @see X509#getX500Name
321      *
322      * @description
323      * Get a JSON object of a subject field.
324      * <br>
325      * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 
326      * supported to conclude a canonicalized name for caseIgnoreMatch
327      * desribed in <a href="https://tools.ietf.org/html/rfc4518">
328      * RFC 4518</a>.
329      *
330      * @example
331      * var x = new X509(sCertPEM);
332      * x.getSubject() →
333      * { array: [[{type:'C',value:'JP',ds:'prn'}],...],
334      *   str: "/C=JP/..." }
335      *
336      * // with flags
337      * x.getSubject(true, true) →
338      * { array: ...,
339      *   str: "/C=JP/O=   Test    123   ",
340      *   canon: "/c=jp/o=test 123",
341      *   hex: "30..." }
342      */
343     this.getSubject = function(flagCanon, flagHex) {
344 	return this.getX500Name(this.getSubjectHex(), flagCanon, flagHex);
345     };
346 
347     /**
348      * get hexadecimal string of subject field of certificate.<br/>
349      * @name getSubjectHex
350      * @memberOf X509#
351      * @function
352      * @return {String} hexadecial string of subject DN ASN.1
353      * @example
354      * var x = new X509();
355      * x.readCertPEM(sCertPEM);
356      * var subject = x.getSubjectHex(); // return string like "3013..."
357      */
358     this.getSubjectHex = function() {
359 	return _getTLVbyList(this.hex, 0, [0, 5 + this.foffset], "30");
360     };
361 
362     /**
363      * get string of subject field of certificate.<br/>
364      * @name getSubjectString
365      * @memberOf X509#
366      * @function
367      * @return {String} subject DN string
368      * @see X509#getSubject
369      * @example
370      * var x = new X509();
371      * x.readCertPEM(sCertPEM);
372      * var dn1 = x.getSubjectString(); // return string like "/C=US/O=TEST"
373      * var dn2 = KJUR.asn1.x509.X500Name.compatToLDAP(dn1); // returns "O=TEST, C=US"
374      */
375     this.getSubjectString = function() {
376 	var pSubject = this.getSubject();
377 	return pSubject.str;
378     };
379 
380     /**
381      * get notBefore field string of certificate.<br/>
382      * @name getNotBefore
383      * @memberOf X509#
384      * @function
385      * @return {String} not before time value (ex. "151231235959Z")
386      * @example
387      * var x = new X509();
388      * x.readCertPEM(sCertPEM);
389      * var notBefore = x.getNotBefore(); // return string like "151231235959Z"
390      */
391     this.getNotBefore = function() {
392         var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 0]);
393         s = s.replace(/(..)/g, "%$1");
394         s = decodeURIComponent(s);
395         return s;
396     };
397 
398     /**
399      * get notAfter field string of certificate.<br/>
400      * @name getNotAfter
401      * @memberOf X509#
402      * @function
403      * @return {String} not after time value (ex. "151231235959Z")
404      * @example
405      * var x = new X509();
406      * x.readCertPEM(sCertPEM);
407      * var notAfter = x.getNotAfter(); // return string like "151231235959Z"
408      */
409     this.getNotAfter = function() {
410 	var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 1]);
411         s = s.replace(/(..)/g, "%$1");
412         s = decodeURIComponent(s);
413         return s;
414     };
415 
416     /**
417      * get a hexadecimal string of subjectPublicKeyInfo field.<br/>
418      * @name getPublicKeyHex
419      * @memberOf X509#
420      * @function
421      * @return {String} ASN.1 SEQUENCE hexadecimal string of subjectPublicKeyInfo field
422      * @since jsrsasign 7.1.4 x509 1.1.13
423      * @deprecated since jsrsasign 10.5.7 x509 2.0.13. Please use {@link X509#getSPKI} instead.
424      *
425      * @example
426      * x = new X509(sCertPEM);
427      * hSPKI = x.getPublicKeyHex(); // return string like "30820122..."
428      */
429     this.getPublicKeyHex = function() {
430 	return this.getSPKI();
431     };
432 
433     /**
434      * get ASN.1 TLV hexadecimal string of subjectPublicKeyInfo field.<br/>
435      * @name getSPKI
436      * @memberOf X509#
437      * @function
438      * @return {string} ASN.1 SEQUENCE hexadecimal string of subjectPublicKeyInfo field
439      * @since jsrsasign 10.5.8 x509 2.0.13
440      * @see X509#getPublicKeyHex
441      * @see X509#getSPKIValue
442      *
443      * @description
444      * Get a hexadecimal string of SubjectPublicKeyInfo ASN.1 TLV of the certificate.<br/>
445      * <pre>
446      * SubjectPublicKeyInfo  ::=  SEQUENCE  {
447      *    algorithm         AlgorithmIdentifier,
448      *    subjectPublicKey  BIT STRING  }
449      * </pre>
450      *
451      * @example
452      * x = new X509(sCertPEM);
453      * hSPKI = x.getSPKI(); // return string like "30820122..."
454      */
455     this.getSPKI = function() {
456 	return _getTLVbyList(this.hex, 0, [0, 6 + this.foffset], "30");
457     };
458 
459     /**
460      * get hexadecimal string of subjectPublicKey of subjectPublicKeyInfo field.<br/>
461      * @name getSPKIValue
462      * @memberOf X509#
463      * @function
464      * @return {string} ASN.1 hexadecimal string of subjectPublicKey
465      * @since jsrsasign 10.5.8 x509 2.0.13
466      * @see X509#getSPKI
467      *
468      * @description
469      * Get a hexadecimal string of subjectPublicKey ASN.1 value of SubjectPublicKeyInfo 
470      * of the certificate without unusedbit "00".
471      * The "subjectPublicKey" is encapsulated by BIT STRING.
472      * This method returns BIT STRING value without unusedbits.
473      * <br/>
474      * <pre>
475      * SubjectPublicKeyInfo  ::=  SEQUENCE  {
476      *    algorithm         AlgorithmIdentifier,
477      *    subjectPublicKey  BIT STRING  }
478      * </pre>
479      *
480      * @example
481      * x = new X509(sCertPEM);
482      * hSPKIValue = x.getSPKIValue(); // without BIT STRING Encapusulation.
483      */
484     this.getSPKIValue = function() {
485 	var hSPKI = this.getSPKI();
486 	if (hSPKI == null) return null;
487 	return _getVbyList(hSPKI, 0, [1], "03", true); // true: remove unused bit
488     };
489 
490     /**
491      * get a string index of subjectPublicKeyInfo field for hexadecimal string certificate.<br/>
492      * @name getPublicKeyIdx
493      * @memberOf X509#
494      * @function
495      * @return {Number} string index of subjectPublicKeyInfo field for hexadecimal string certificate.
496      * @since jsrsasign 7.1.4 x509 1.1.13
497      * @example
498      * x = new X509();
499      * x.readCertPEM(sCertPEM);
500      * idx = x.getPublicKeyIdx(); // return string index in x.hex parameter
501      */
502     this.getPublicKeyIdx = function() {
503 	return _getIdxbyList(this.hex, 0, [0, 6 + this.foffset], "30");
504     };
505 
506     /**
507      * get a string index of contents of subjectPublicKeyInfo BITSTRING value from hexadecimal certificate<br/>
508      * @name getPublicKeyContentIdx
509      * @memberOf X509#
510      * @function
511      * @return {Integer} string index of key contents
512      * @since jsrsasign 8.0.0 x509 1.2.0
513      * @example
514      * x = new X509();
515      * x.readCertPEM(sCertPEM);
516      * idx = x.getPublicKeyContentIdx(); // return string index in x.hex parameter
517      */
518     // NOTE: Without BITSTRING encapsulation.
519     this.getPublicKeyContentIdx = function() {
520 	var idx = this.getPublicKeyIdx();
521 	return _getIdxbyList(this.hex, idx, [1, 0], "30");
522     };
523 
524     /**
525      * get a RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field.<br/>
526      * @name getPublicKey
527      * @memberOf X509#
528      * @function
529      * @return {Object} RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field
530      * @since jsrsasign 7.1.4 x509 1.1.13
531      * @example
532      * x = new X509();
533      * x.readCertPEM(sCertPEM);
534      * pubkey= x.getPublicKey();
535      */
536     this.getPublicKey = function() {
537 	return KEYUTIL.getKey(this.getPublicKeyHex(), null, "pkcs8pub");
538     };
539 
540     /**
541      * get signature algorithm name from hexadecimal certificate data
542      * @name getSignatureAlgorithmName
543      * @memberOf X509#
544      * @function
545      * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA)
546      * @since jsrsasign 7.2.0 x509 1.1.14
547      * @see X509#getAlgorithmIdentifierName
548      * @description
549      * This method will get signature algorithm name of certificate:
550      * @example
551      * var x = new X509();
552      * x.readCertPEM(sCertPEM);
553      * x.getSignatureAlgorithmName() → "SHA256withRSA"
554      */
555     this.getSignatureAlgorithmName = function() {
556 	var hTLV = _getTLVbyList(this.hex, 0, [1], "30");
557 	return this.getAlgorithmIdentifierName(hTLV);
558     };
559 
560     /**
561      * get signature value as hexadecimal string<br/>
562      * @name getSignatureValueHex
563      * @memberOf X509#
564      * @function
565      * @return {String} signature value hexadecimal string without BitString unused bits
566      * @since jsrsasign 7.2.0 x509 1.1.14
567      *
568      * @description
569      * This method will get signature value of certificate:
570      *
571      * @example
572      * var x = new X509();
573      * x.readCertPEM(sCertPEM);
574      * x.getSignatureValueHex() &rarr "8a4c47913..."
575      */
576     this.getSignatureValueHex = function() {
577 	return _getVbyList(this.hex, 0, [2], "03", true);
578     };
579 
580     /**
581      * verifies signature value by public key<br/>
582      * @name verifySignature
583      * @memberOf X509#
584      * @function
585      * @param {Object} pubKey public key object
586      * @return {Boolean} true if signature value is valid otherwise false
587      * @since jsrsasign 7.2.0 x509 1.1.14
588      *
589      * @description
590      * This method verifies signature value of hexadecimal string of 
591      * X.509 certificate by specified public key object.
592      * The signature algorithm used to verify will refer
593      * signatureAlgorithm field. (See {@link X509#getSignatureAlgorithmField})
594      * RSA-PSS signature algorithms (SHA{,256,384,512}withRSAandMGF1)
595      * are available.
596      *
597      * @example
598      * pubKey = KEYUTIL.getKey(pemPublicKey); // or certificate
599      * x = new X509();
600      * x.readCertPEM(pemCert);
601      * x.verifySignature(pubKey) → true, false or raising exception
602      */
603     this.verifySignature = function(pubKey) {
604 	var algName = this.getSignatureAlgorithmField();
605 	var hSigVal = this.getSignatureValueHex();
606 	var hTbsCert = _getTLVbyList(this.hex, 0, [0], "30");
607 	
608 	var sig = new KJUR.crypto.Signature({alg: algName});
609 	sig.init(pubKey);
610 	sig.updateHex(hTbsCert);
611 	return sig.verify(hSigVal);
612     };
613 
614     // ===== parse extension ======================================
615     /**
616      * set array of X.509v3 and CSR extesion information such as extension OID, criticality and value index. (DEPRECATED)<br/>
617      * @name parseExt
618      * @memberOf X509#
619      * @function
620      * @param {String} hCSR - PEM string of certificate signing requrest(CSR) (OPTION)
621      * @since jsrsasign 7.2.0 x509 1.1.14
622      * @deprecated jsrsasign 9.1.1 x509 2.0.1
623      *
624      * @description
625      * This method will set an array of X.509v3 extension information having 
626      * following parameters:
627      * <ul>
628      * <li>oid - extension OID (ex. 2.5.29.19)</li>
629      * <li>critical - true or false</li>
630      * <li>vidx - string index for extension value</li>
631      * <br/>
632      * When you want to parse extensionRequest of CSR,
633      * argument 'hCSR' shall be specified.
634      * <br/>
635      * NOTE: CSR is supported from jsrsasign 8.0.20 x509 1.1.22.
636      * <br/>
637      * This method and X509.aExtInfo property
638      * have been *deprecated* since jsrsasign 9.1.1.
639      * All extension parser method such as X509.getExt* shall be
640      * call with argument "hExtV" and "critical" explicitly.
641      *
642      * @example
643      * x = new X509();
644      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
645      *
646      * x.aExtInfo →
647      * [ { oid: "2.5.29,19", critical: true, vidx: 2504 }, ... ]
648      *
649      * // to parse CSR
650      * X = new X509()
651      * x.parseExt("-----BEGIN CERTIFICATE REQUEST-----...");
652      * x.aExtInfo →
653      * [ { oid: "2.5.29,19", critical: true, vidx: 2504 }, ... ]
654      */
655     this.parseExt = function(hCSR) {
656 	var iExtSeq, aExtIdx, h;
657 
658 	if (hCSR === undefined) {
659 	    h = this.hex;
660 	    if (this.version !== 3) return -1;
661 	    iExtSeq = _getIdxbyList(h, 0, [0, 7, 0], "30");
662 	    aExtIdx = _getChildIdx(h, iExtSeq);
663 	} else {
664 	    h = pemtohex(hCSR);
665 	    var idx1 = _getIdxbyList(h, 0, [0, 3, 0, 0], "06");
666 
667 	    if (_getV(h, idx1) != "2a864886f70d01090e") {
668 		this.aExtInfo = new Array();
669 		return;
670 	    }
671 
672 	    iExtSeq = _getIdxbyList(h, 0, [0, 3, 0, 1, 0], "30");
673 	    aExtIdx = _getChildIdx(h, iExtSeq);
674 
675 	    this.hex = h;
676 	}
677 	    
678 	this.aExtInfo = new Array();
679 	for (var i = 0; i < aExtIdx.length; i++) {
680 	    var item = {};
681 	    item.critical = false;
682 	    var a = _getChildIdx(h, aExtIdx[i]);
683 	    var offset = 0;
684 
685 	    if (a.length === 3) {
686 		item.critical = true;
687 		offset = 1;
688 	    }
689 
690 	    item.oid = _ASN1HEX.hextooidstr(_getVbyList(h, aExtIdx[i], [0], "06"));
691 	    var octidx = _getIdxbyList(h, aExtIdx[i], [1 + offset]);
692 	    item.vidx = _getVidx(h, octidx);
693 	    this.aExtInfo.push(item);
694 	}
695     };
696 
697     /**
698      * get a X.509v3 extesion information such as extension OID, criticality and value index for specified oid or name.<br/>
699      * @name getExtInfo
700      * @memberOf X509#
701      * @function
702      * @param {String} oidOrName X.509 extension oid or name (ex. keyUsage or 2.5.29.19)
703      * @return X.509 extension information such as extension OID or value indx (see {@link X509#parseExt})
704      * @since jsrsasign 7.2.0 x509 1.1.14
705      * @description
706      * This method will get an X.509v3 extension information JSON object
707      * having extension OID, criticality and value idx for specified
708      * extension OID or name.
709      * If there is no such extension, this returns undefined.
710      * @example
711      * x = new X509();
712      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
713      *
714      * x.getExtInfo("keyUsage") → { oid: "2.5.29.15", critical: true, vidx: 1714 }
715      * x.getExtInfo("unknownExt") → undefined
716      */
717     this.getExtInfo = function(oidOrName) {
718 	var a = this.aExtInfo;
719 	var oid = oidOrName;
720 	if (! oidOrName.match(/^[0-9.]+$/)) {
721 	    oid = KJUR.asn1.x509.OID.name2oid(oidOrName);
722 	}
723 	if (oid === '') return undefined;
724 
725 	for (var i = 0; i < a.length; i++) {
726 	    if (a[i].oid === oid) return a[i];
727 	}
728 	return undefined;
729     };
730 
731     /**
732      * get extension value and critical flag value<br/>
733      * @name getCriticalExtV
734      * @memberOf X509#
735      * @function
736      * @param {string} extname name string of the extension
737      * @param {string} hExtV hexadecimal string of extension
738      * @param {boolean} critical flag
739      * @return {Array} extension value hex and critical flag
740      * @since jsrsasign 10.6.1 x509 2.1.1
741      *
742      * @description
743      * This method is an utility method for all getExt* of extensions.
744      *
745      * @example
746      * x = new X509(sCertPEM);
747      * x.getCriticalExtV("inhibitAnyPolicy") &rarr ["020103", true] // get from X509 object
748      * x.getCriticalExtV("inhibitAnyPolicy",
749      *                   "020104",
750      *                   true) &rarr ["020104", true] // by argument of method.
751      */
752     this.getCriticalExtV = function(extname, hExtV, critical) {
753 	if (hExtV != undefined) return [hExtV, critical];
754 	var info = this.getExtInfo(extname);
755 	if (info == undefined) return [null, null];
756 	return [_getTLV(this.hex, info.vidx), info.critical];
757     };
758 
759     /**
760      * get BasicConstraints extension value as object in the certificate
761      * @name getExtBasicConstraints
762      * @memberOf X509#
763      * @function
764      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
765      * @param {Boolean} critical flag (OPTIONAL)
766      * @return {Array} JSON object of BasicConstraints parameter or undefined
767      * @since jsrsasign 7.2.0 x509 1.1.14
768      * @see KJUR.asn1.x509.BasicConstraints
769      * @description
770      * This method will get basic constraints extension value as object with following paramters.
771      * <ul>
772      * <li>{Boolean}cA - CA flag whether CA or not</li>
773      * <li>{Integer}pathLen - maximum intermediate certificate length</li>
774      * <li>{Boolean}critical - critical flag</li>
775      * </ul>
776      * There are use cases for return values:
777      * <ul>
778      * <li>{cA:true,pathLen:3,critical:true} - cA flag is true and pathLen is 3</li>
779      * <li>{cA:true,critical:true} - cA flag is true and no pathLen</li>
780      * <li>{} - basic constraints has no value in case of end entity certificate</li>
781      * <li>undefined - there is no basic constraints extension</li>
782      * </ul>
783      * @example
784      * x = new X509();
785      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
786      * x.getExtBasicConstraints() → {cA:true,pathLen:3,critical:true}
787      */
788     this.getExtBasicConstraints = function(hExtV, critical) {
789 	if (hExtV === undefined && critical === undefined) {
790 	    var info = this.getExtInfo("basicConstraints");
791 	    if (info === undefined) return undefined;
792 	    hExtV = _getTLV(this.hex, info.vidx);
793 	    critical = info.critical;
794 	}
795 
796 	var result = {extname:"basicConstraints"};
797 	if (critical) result.critical = true;
798 
799 	if (hExtV === '3000') return result;
800 	if (hExtV === '30030101ff') {
801 	    result.cA = true;
802 	    return result;
803 	}
804 	if (hExtV.substr(0, 12) === '30060101ff02') {
805 	    var pathLexHex = _getV(hExtV, 10);
806 	    var pathLen = parseInt(pathLexHex, 16);
807 	    result.cA = true;
808 	    result.pathLen = pathLen;
809 	    return result;
810 	}
811 	throw new Error("hExtV parse error: " + hExtV);
812     };
813 
814     /**
815      * get NameConstraints extension value as object in the certificate<br/>
816      * @name getExtNameConstraints
817      * @memberOf X509#
818      * @function
819      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
820      * @param {Boolean} critical flag (OPTIONAL)
821      * @return {Object} JSON object of NamConstraints parameter or undefined
822      * @since jsrsasign 10.5.16 x509 2.0.16
823      * @see KJUR.asn1.x509.NameConstraints
824      * @see KJUR.asn1.x509.GeneralSubtree
825      * @see KJUR.asn1.x509.GeneralName
826      * @see X509#getGeneralSubtree
827      * @see X509#getGeneralName
828      *
829      * @description
830      * This method will get name constraints extension value as object with following paramters.
831      * <ul>
832      * <li>{Array}permit - array of {@link KJUR.asn1.x509.GeneralSubtree} parameter</li>
833      * <li>{Array}exclude - array of {@link KJUR.asn1.x509.GeneralSubtree} parameter</li>
834      * <li>{Boolean}critical - critical flag</li>
835      * </ul>
836      *
837      * @example
838      * x = new X509(sCertPEM);
839      * x.getExtNameConstraints() → {
840      *   critical: true,
841      *   permit: [{dns: 'example.com'},{rfc822: 'john@example.com'}],
842      *   exclude: [{dn: {...X500Name parameter...}}]
843      * }
844      */
845     this.getExtNameConstraints = function(hExtV, critical) {
846 	var aExtVCritical = this.getCriticalExtV("nameConstraints", hExtV, critical);
847 	hExtV = aExtVCritical[0];
848 	critical = aExtVCritical[1];
849 	if (hExtV == null) return undefined;
850 	var result = {extname:"nameConstraints"};
851 	if (critical) result.critical = true;
852 
853 	var aIdx = _getChildIdx(hExtV, 0);
854 	for (var i = 0; i < aIdx.length; i++) {
855 	    var aList = [];
856 	    var aIdx2 = _getChildIdx(hExtV, aIdx[i]);
857 	    for (var j = 0; j < aIdx2.length; j++) {
858 		var hSub = _getTLV(hExtV, aIdx2[j]);
859 		var p = this.getGeneralSubtree(hSub);
860 		aList.push(p);
861 	    }
862 
863 	    var tag = hExtV.substr(aIdx[i], 2); 
864 	    if (tag == "a0") {
865 		result.permit = aList;
866 	    } else if (tag == "a1") {
867 		result.exclude = aList;
868 	    }
869 	}
870 	return result;
871     };
872 
873     /**
874      * get GeneralSubtree ASN.1 structure parameter as JSON object<br/>
875      * @name getGeneralSubtree
876      * @memberOf X509#
877      * @function
878      * @param {String} h hexadecimal string of GeneralSubtree
879      * @return {Object} JSON object of GeneralSubtree parameters or undefined
880      * @since jsrsasign 10.5.16 x509 2.0.16
881      * @see KJUR.asn1.x509.GeneralSubtree
882      * @see KJUR.asn1.x509.GeneralName
883      * @see X509#getExtNameConstraints
884      * @see X509#getGeneralName
885      *
886      * @description
887      * This method will get GeneralSubtree parameters defined in
888      * <a href="https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10">
889      * RFC 5280 4.2.1.10</a>.
890      * <pre>
891      * GeneralSubtree ::= SEQUENCE {
892      *      base                    GeneralName,
893      *      minimum         [0]     BaseDistance DEFAULT 0,
894      *      maximum         [1]     BaseDistance OPTIONAL }
895      * BaseDistance ::= INTEGER (0..MAX)
896      * </pre>
897      * Result of this method can be passed to
898      * {@link KJUR.asn1.x509.GeneralSubtree} constructor.
899      * 
900      * @example
901      * x = new X509(sPEM);
902      * x.getGeneralSubtree("30...") → { dn: ...X500NameObject..., min: 1, max: 3 }
903      * x.getGeneralSubtree("30...") → { dns: ".example.com" }
904      */
905     this.getGeneralSubtree = function(h) {
906 	var aIdx = _getChildIdx(h, 0);
907 	var len = aIdx.length;
908 	if (len < 1 || 2 < len) throw new Error("wrong num elements");
909 	var result = this.getGeneralName(_getTLV(h, aIdx[0]));
910 
911 	for (var i = 1; i < len; i++) {
912 	    var tag = h.substr(aIdx[i], 2);
913 	    var hV = _getV(h, aIdx[i]);
914 	    var minmaxValue = parseInt(hV, 16);
915 	    if (tag == "80") result.min = minmaxValue;
916 	    if (tag == "81") result.max = minmaxValue;
917 	}
918 	return result;
919     };
920 
921     /**
922      * get KeyUsage extension value as JSON object
923      * @memberOf X509#
924      * @function
925      * @name getExtKeyUsage
926      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
927      * @param {Boolean} critical flag (OPTIONAL)
928      * @return {Array} JSON object of KeyUsage parameter or undefined
929      * @since jsrsasign 9.0.0 x509 2.0.0
930      * @see KJUR.asn1.x509.KeyUsage
931      * @see X509#getExtKeyUsageString
932      * @description
933      * This method parse keyUsage extension. When arguments are
934      * not specified, its extension in X509 object will be parsed.
935      * Result of this method can be passed to 
936      * {@link KJUR.asn1.x509.KeyUsage} constructor.
937      * <br>
938      * When hExtV and critical specified as arguments, return value
939      * will be generated from them.
940      * <pre>
941      * id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
942      * KeyUsage ::= BIT STRING {
943      *      digitalSignature        (0),
944      *      nonRepudiation          (1),
945      *      keyEncipherment         (2),
946      *      dataEncipherment        (3),
947      *      keyAgreement            (4),
948      *      keyCertSign             (5),
949      *      cRLSign                 (6),
950      *      encipherOnly            (7),
951      *      decipherOnly            (8) }     
952      * </pre>
953      * @example
954      * x = new X509();
955      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
956      * x.getExtKeyUsage() →
957      * {
958      *   critial: true,
959      *   names: ["digitalSignature", "decipherOnly"]
960      * }
961      *
962      * x = new X509();
963      * x.getExtKeyUsage("306230...") 
964      * x.getExtKeyUsage("306230...", true) 
965      */
966     this.getExtKeyUsage = function(hExtV, critical) {
967 	var aExtVCritical = this.getCriticalExtV("keyUsage", hExtV, critical);
968 	hExtV = aExtVCritical[0];
969 	critical = aExtVCritical[1];
970 	if (hExtV == null) return undefined;
971 	var result = {extname:"keyUsage"};
972 	if (critical) result.critical = true;
973 
974 	result.names = this.getExtKeyUsageString(hExtV).split(",");
975 
976 	return result;
977     };
978 
979     /**
980      * get KeyUsage extension value as binary string in the certificate<br/>
981      * @name getExtKeyUsageBin
982      * @memberOf X509#
983      * @function
984      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
985      * @return {String} binary string of key usage bits (ex. '101')
986      * @since jsrsasign 7.2.0 x509 1.1.14
987      * @see X509#getExtKeyUsage
988      * @description
989      * This method will get key usage extension value
990      * as binary string such like '101'.
991      * Key usage bits definition is in the RFC 5280.
992      * If there is no key usage extension in the certificate,
993      * it returns empty string (i.e. '').
994      * <br/>
995      * NOTE: argument 'hExtV' supported since jsrsasign 9.0.0 x509 2.0.0.
996      * @example
997      * x = new X509();
998      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
999      * x.getExtKeyUsageBin() → '101'
1000      * // 1 - digitalSignature
1001      * // 0 - nonRepudiation
1002      * // 1 - keyEncipherment
1003      */
1004     this.getExtKeyUsageBin = function(hExtV) {
1005 	if (hExtV === undefined) {
1006 	    var info = this.getExtInfo("keyUsage");
1007 	    if (info === undefined) return '';
1008 	    hExtV = _getTLV(this.hex, info.vidx);
1009 	}
1010 	
1011 	if (hExtV.length != 8 && hExtV.length != 10)
1012 	    throw new Error("malformed key usage value: " + hExtV);
1013 
1014 	var s = "000000000000000" + parseInt(hExtV.substr(6), 16).toString(2);
1015 	if (hExtV.length == 8) s = s.slice(-8);
1016 	if (hExtV.length == 10) s = s.slice(-16);
1017 	s = s.replace(/0+$/, '');
1018 	if (s == '') s = '0';
1019 	return s;
1020     };
1021 
1022     /**
1023      * get KeyUsage extension value as names in the certificate<br/>
1024      * @name getExtKeyUsageString
1025      * @memberOf X509#
1026      * @function
1027      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1028      * @return {String} comma separated string of key usage
1029      * @since jsrsasign 7.2.0 x509 1.1.14
1030      * @see X509#getExtKeyUsage
1031      * @description
1032      * This method will get key usage extension value
1033      * as comma separated string of usage names.
1034      * If there is no key usage extension in the certificate,
1035      * it returns empty string (i.e. '').
1036      * <br/>
1037      * NOTE: argument 'hExtV' supported since jsrsasign 9.0.0 x509 2.0.0.
1038      * @example
1039      * x = new X509();
1040      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1041      * x.getExtKeyUsageString() → "digitalSignature,keyEncipherment"
1042      */
1043     this.getExtKeyUsageString = function(hExtV) {
1044 	var bKeyUsage = this.getExtKeyUsageBin(hExtV);
1045 	var a = new Array();
1046 	for (var i = 0; i < bKeyUsage.length; i++) {
1047 	    if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]);
1048 	}
1049 	return a.join(",");
1050     };
1051 
1052     /**
1053      * get subjectKeyIdentifier value as hexadecimal string in the certificate<br/>
1054      * @name getExtSubjectKeyIdentifier
1055      * @memberOf X509#
1056      * @function
1057      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1058      * @param {Boolean} critical flag (OPTIONAL)
1059      * @return {Array} JSON object of SubjectKeyIdentifier parameter or undefined
1060      * @since jsrsasign 7.2.0 x509 1.1.14
1061      * @description
1062      * This method will get 
1063      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.2">
1064      * SubjectKeyIdentifier extension</a> value as JSON object.
1065      * <br>
1066      * When hExtV and critical specified as arguments, return value
1067      * will be generated from them.
1068      * If there is no such extension in the certificate, it returns undefined.
1069      * <br>
1070      * Result of this method can be passed to 
1071      * {@link KJUR.asn1.x509.SubjectKeyIdentifier} constructor.
1072      * <pre>
1073      * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 }
1074      * SubjectKeyIdentifier ::= KeyIdentifier
1075      * </pre>
1076      * <br>
1077      * CAUTION:
1078      * Returned JSON value format have been changed without 
1079      * backward compatibility since jsrsasign 9.0.0 x509 2.0.0.
1080      *
1081      * @example
1082      * x = new X509();
1083      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1084      * x.getExtSubjectKeyIdentifier() → 
1085      * { kid: {hex: "1b3347ab..."}, critical: true };
1086      */
1087     this.getExtSubjectKeyIdentifier = function(hExtV, critical) {
1088 	if (hExtV === undefined && critical === undefined) {
1089 	    var info = this.getExtInfo("subjectKeyIdentifier");
1090 	    if (info === undefined) return undefined;
1091 	    hExtV = _getTLV(this.hex, info.vidx);
1092 	    critical = info.critical;
1093 	}
1094 
1095 	var result = {extname:"subjectKeyIdentifier"};
1096 	if (critical) result.critical = true;
1097 
1098 	var hKID = _getV(hExtV, 0);
1099 	result.kid = {hex: hKID};
1100 
1101 	return result;
1102     };
1103 
1104     /**
1105      * get authorityKeyIdentifier value as JSON object in the certificate<br/>
1106      * @name getExtAuthorityKeyIdentifier
1107      * @memberOf X509#
1108      * @function
1109      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1110      * @param {Boolean} critical flag (OPTIONAL)
1111      * @return {Array} JSON object of AuthorityKeyIdentifier parameter or undefined
1112      * @since jsrsasign 7.2.0 x509 1.1.14
1113      * @see KJUR.asn1.x509.AuthorityKeyIdentifier
1114      * @description
1115      * This method will get 
1116      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.1">
1117      * AuthorityKeyIdentifier extension</a> value as JSON object.
1118      * <br>
1119      * When hExtV and critical specified as arguments, return value
1120      * will be generated from them.
1121      * If there is no such extension in the certificate, it returns undefined.
1122      * <br/>
1123      * Result of this method can be passed to 
1124      * {@link KJUR.asn1.x509.AuthorityKeyIdentifier} constructor.
1125      * <pre>
1126      *    id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
1127      *    AuthorityKeyIdentifier ::= SEQUENCE {
1128      *       keyIdentifier             [0] KeyIdentifier           OPTIONAL,
1129      *       authorityCertIssuer       [1] GeneralNames            OPTIONAL,
1130      *       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
1131      *    KeyIdentifier ::= OCTET STRING
1132      * </pre>
1133      * Constructor may have following parameters:
1134      * <ul>
1135      * <li>{Array}kid - JSON object of {@link KJUR.asn1.DEROctetString} parameters</li>
1136      * <li>{Array}issuer - JSON object of {@link KJUR.asn1.x509.X500Name} parameters</li>
1137      * <li>{Array}sn - JSON object of {@link KJUR.asn1.DERInteger} parameters</li>
1138      * <li>{Boolean}critical - critical flag</li>
1139      * </ul>
1140      * <br>
1141      * NOTE: The 'authorityCertIssuer' and 'authorityCertSerialNumber'
1142      * supported since jsrsasign 9.0.0 x509 2.0.0.
1143      * @example
1144      * x = new X509();
1145      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1146      * x.getExtAuthorityKeyIdentifier() → 
1147      * { kid: {hex: "1234abcd..."},
1148      *   issuer: {hex: "30..."},
1149      *   sn: {hex: "1234..."},
1150      *   critical: true}
1151      */
1152     this.getExtAuthorityKeyIdentifier = function(hExtV, critical) {
1153 	if (hExtV === undefined && critical === undefined) {
1154 	    var info = this.getExtInfo("authorityKeyIdentifier");
1155 	    if (info === undefined) return undefined;
1156 	    hExtV = _getTLV(this.hex, info.vidx);
1157 	    critical = info.critical;
1158 	}
1159 
1160 	var result = {extname:"authorityKeyIdentifier"};
1161 	if (critical) result.critical = true;
1162 
1163 	var a = _getChildIdx(hExtV, 0);
1164 	for (var i = 0; i < a.length; i++) {
1165 	    var tag = hExtV.substr(a[i], 2);
1166 	    if (tag === "80") {
1167 		result.kid = {hex: _getV(hExtV, a[i])};
1168 	    }
1169 	    if (tag === "a1") {
1170 		var hGNS = _getTLV(hExtV, a[i]);
1171 		var gnsParam = this.getGeneralNames(hGNS);
1172 		result.issuer = gnsParam[0]["dn"];
1173 	    }
1174 	    if (tag === "82") {
1175 		result.sn = {hex: _getV(hExtV, a[i])};
1176 	    }
1177 	}
1178 	return result;
1179     };
1180 
1181     /**
1182      * get extKeyUsage value as JSON object
1183      * @name getExtExtKeyUsage
1184      * @memberOf X509#
1185      * @function
1186      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1187      * @param {Boolean} critical flag (OPTIONAL)
1188      * @return {Array} JSON object of ExtKeyUsage parameter or undefined
1189      * @return {Object} JSONarray of extended key usage ID name or oid
1190      * @since jsrsasign 9.0.0 x509 2.0.0
1191      * @see KJUR.asn1.x509.ExtKeyUsage
1192      * @description
1193      * This method parse extKeyUsage extension. When arguments are
1194      * not specified, its extension in X509 object will be parsed.
1195      * Result of this method can be passed to 
1196      * {@link KJUR.asn1.x509.ExtKeyUsage} constructor.
1197      * <br>
1198      * When hExtV and critical specified as arguments, return value
1199      * will be generated from them.
1200      * @example
1201      * x = new X509();
1202      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1203      * x.getExtExtKeyUsage() →
1204      * { array: ["clientAuth", "emailProtection", "1.3.6.1.4.1.311.10.3.4"], 
1205      *   critical: true},
1206      */
1207     this.getExtExtKeyUsage = function(hExtV, critical) {
1208 	if (hExtV === undefined && critical === undefined) {
1209 	    var info = this.getExtInfo("extKeyUsage");
1210 	    if (info === undefined) return undefined;
1211 	    hExtV = _getTLV(this.hex, info.vidx);
1212 	    critical = info.critical;
1213 	}
1214 
1215 	var result = {extname:"extKeyUsage",array:[]};
1216 	if (critical) result.critical = true;
1217 
1218 	var a = _getChildIdx(hExtV, 0);
1219 
1220 	for (var i = 0; i < a.length; i++) {
1221 	    result.array.push(_oidname(_getV(hExtV, a[i])));
1222 	}
1223 
1224 	return result;
1225     };
1226 
1227     /**
1228      * get extKeyUsage value as array of name string in the certificate(DEPRECATED)<br/>
1229      * @name getExtExtKeyUsageName
1230      * @memberOf X509#
1231      * @function
1232      * @return {Object} array of extended key usage ID name or oid
1233      * @since jsrsasign 7.2.0 x509 1.1.14
1234      * @deprecated since jsrsasign 9.0.0 x509 2.0.0
1235      * @description
1236      * This method will get extended key usage extension value
1237      * as array of name or OID string.
1238      * If there is this in the certificate, it returns undefined;
1239      * <br>
1240      * NOTE: Supported extended key usage ID names are defined in
1241      * name2oidList parameter in asn1x509.js file.
1242      * @example
1243      * x = new X509();
1244      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1245      * x.getExtExtKeyUsageName() → ["serverAuth", "clientAuth", "0.1.2.3.4.5"]
1246      */
1247     this.getExtExtKeyUsageName = function() {
1248 	var info = this.getExtInfo("extKeyUsage");
1249 	if (info === undefined) return info;
1250 
1251 	var result = new Array();
1252 	
1253 	var h = _getTLV(this.hex, info.vidx);
1254 	if (h === '') return result;
1255 
1256 	var a = _getChildIdx(h, 0);
1257 	for (var i = 0; i < a.length; i++) {
1258 	    result.push(_oidname(_getV(h, a[i])));
1259 	}
1260 
1261 	return result;
1262     };
1263 
1264     /**
1265      * get subjectAltName value as array of string in the certificate
1266      * @name getExtSubjectAltName
1267      * @memberOf X509#
1268      * @function
1269      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1270      * @param {Boolean} critical flag (OPTIONAL)
1271      * @return {Array} JSON object of SubjectAltName parameters or undefined
1272      * @since jsrsasign 7.2.0 x509 1.1.14
1273      * @see KJUR.asn1.x509.SubjectAltName
1274      * @see X509#getExtIssuerAltName
1275      * @description
1276      * This method will get subjectAltName value
1277      * as an array of JSON object which has properties defined
1278      * in {@link KJUR.asn1.x509.SubjectAltName}.
1279      * Result of this method can be passed to 
1280      * {@link KJUR.asn1.x509.SubjectAltName} constructor.
1281      * If there is no this extension in the certificate,
1282      * it returns undefined.
1283      * <br>
1284      * When hExtV and critical specified as arguments, return value
1285      * will be generated from them.
1286      * <br>
1287      * CAUTION: return value of JSON object format have been changed
1288      * from jsrsasign 9.0.0 x509 2.0.0 without backword compatibility.
1289      * @example
1290      * x = new X509();
1291      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1292      * x.getExtSubjectAltName() → 
1293      * { array: [
1294      *     {uri: "http://example.com/"},
1295      *     {rfc822: "user1@example.com"},
1296      *     {dns: "example.com"}
1297      *   ],
1298      *   critical: true
1299      * }
1300      *
1301      * x.getExtSubjectAltName("3026...") →
1302      * { array: [{ip: "192.168.1.1"}] }
1303      */
1304     this.getExtSubjectAltName = function(hExtV, critical) {
1305 	if (hExtV === undefined && critical === undefined) {
1306 	    var info = this.getExtInfo("subjectAltName");
1307 	    if (info === undefined) return undefined;
1308 	    hExtV = _getTLV(this.hex, info.vidx);
1309 	    critical = info.critical;
1310 	}
1311 
1312 	var result = {extname:"subjectAltName",array:[]};
1313 	if (critical) result.critical = true;
1314 
1315 	result.array = this.getGeneralNames(hExtV);
1316 
1317 	return result;
1318     };
1319 
1320     /**
1321      * get issuerAltName value as array of string in the certificate
1322      * @name getExtIssuerAltName
1323      * @memberOf X509#
1324      * @function
1325      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1326      * @param {Boolean} critical flag (OPTIONAL)
1327      * @return {Array} JSON object of IssuerAltName parameters
1328      * @since jsrsasign 9.0.0 x509 2.0.0
1329      * @see KJUR.asn1.x509.IssuerAltName
1330      * @see X509#getExtSubjectAltName
1331      * @description
1332      * This method will get issuerAltName value
1333      * as an array of JSON object which has properties defined
1334      * in {@link KJUR.asn1.x509.IssuerAltName}.
1335      * Result of this method can be passed to 
1336      * {@link KJUR.asn1.x509.IssuerAltName} constructor.
1337      * If there is no this extension in the certificate,
1338      * it returns undefined.
1339      * <br>
1340      * When hExtV and critical specified as arguments, return value
1341      * will be generated from them.
1342      * @example
1343      * x = new X509();
1344      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1345      * x.getExtIssuerAltName() → 
1346      * { array: [
1347      *     {uri: "http://example.com/"},
1348      *     {rfc822: "user1@example.com"},
1349      *     {dns: "example.com"}
1350      *   ],
1351      *   critical: true
1352      * }
1353      *
1354      * x.getExtIssuerAltName("3026...") →
1355      * { array: [{ip: "192.168.1.1"}] }
1356      */
1357     this.getExtIssuerAltName = function(hExtV, critical) {
1358 	if (hExtV === undefined && critical === undefined) {
1359 	    var info = this.getExtInfo("issuerAltName");
1360 	    if (info === undefined) return undefined;
1361 	    hExtV = _getTLV(this.hex, info.vidx);
1362 	    critical = info.critical;
1363 	}
1364 
1365 	var result = {extname:"issuerAltName",array:[]};
1366 	if (critical) result.critical = true;
1367 
1368 	result.array = this.getGeneralNames(hExtV);
1369 
1370 	return result;
1371     };
1372 
1373     /**
1374      * get GeneralNames ASN.1 structure parameter as JSON object
1375      * @name getGeneralNames
1376      * @memberOf X509#
1377      * @function
1378      * @param {String} h hexadecimal string of GeneralNames
1379      * @return {Array} array of GeneralNames parameters
1380      * @see KJUR.asn1.x509.GeneralNames
1381      * @see KJUR.asn1.x509.GeneralName
1382      * @see X509#getGeneralNames
1383      * @since jsrsasign 9.0.0 x509 2.0.0
1384      * @description
1385      * This method will get GeneralNames parameters defined in
1386      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6">
1387      * RFC 5280 4.2.1.6</a>.
1388      * <pre>
1389      * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1390      * </pre>
1391      * Result of this method can be passed to
1392      * {@link KJUR.asn1.x509.GeneralNames} constructor.
1393      * @example
1394      * x = new X509();
1395      * x.getGeneralNames("3011860f687474703a2f2f6161612e636f6d2f")
1396      * → [{uri: "http://aaa.com/"}]
1397      *
1398      * x.getGeneralNames("301ea41c30...") →
1399      * [{ dn: {
1400      *     array: [
1401      *       [{type:"C", value:"JP", ds:"prn"}],
1402      *       [{type:"O", value:"T1", ds:"utf8"}]
1403      *     ],
1404      *     str: "/C=JP/O=T1" } }]
1405      */
1406     this.getGeneralNames = function(h) {
1407 	var aIdx = _getChildIdx(h, 0);
1408 	var result = [];
1409 	for (var i = 0; i < aIdx.length; i++) {
1410 	    var gnParam = this.getGeneralName(_getTLV(h, aIdx[i]));
1411 	    if (gnParam !== undefined) result.push(gnParam);
1412 	}
1413 	return result;
1414     };
1415 
1416     /**
1417      * get GeneralName ASN.1 structure parameter as JSON object<br/>
1418      * @name getGeneralName
1419      * @memberOf X509#
1420      * @function
1421      * @param {String} h hexadecimal string of GeneralName
1422      * @return {Array} JSON object of GeneralName parameters or undefined
1423      * @since jsrsasign 9.0.0 x509 2.0.0
1424      * @see KJUR.asn1.x509.GeneralNames
1425      * @see KJUR.asn1.x509.GeneralName
1426      * @see KJUR.asn1.x509.OtherName
1427      * @see X509#getGeneralName
1428      * @see X509#getOtherName
1429      *
1430      * @description
1431      * This method will get GeneralName parameters defined in
1432      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6">
1433      * RFC 5280 4.2.1.6</a>.
1434      * <pre>
1435      * GeneralName ::= CHOICE {
1436      *      otherName                       [0]     OtherName,
1437      *      rfc822Name                      [1]     IA5String,
1438      *      dNSName                         [2]     IA5String,
1439      *      x400Address                     [3]     ORAddress,
1440      *      directoryName                   [4]     Name,
1441      *      ediPartyName                    [5]     EDIPartyName,
1442      *      uniformResourceIdentifier       [6]     IA5String,
1443      *      iPAddress                       [7]     OCTET STRING,
1444      *      registeredID                    [8]     OBJECT IDENTIFIER }
1445      * </pre>
1446      * Result of this method can be passed to
1447      * {@link KJUR.asn1.x509.GeneralName} constructor.
1448      * @example
1449      * x = new X509();
1450      * x.getGeneralName("860f687474703a2f2f6161612e636f6d2f") 
1451      * → {uri: "http://aaa.com/"}
1452      * x.getGeneralName("a41c30...") →
1453      * { dn: {
1454      *     array: [
1455      *       [{type:"C", value:"JP", ds:"prn"}],
1456      *       [{type:"O", value:"T1", ds:"utf8"}]
1457      *     ],
1458      *     str: "/C=JP/O=T1" } }
1459      */
1460     this.getGeneralName = function(h) {
1461 	var tag = h.substr(0, 2);
1462 	var hValue = _getV(h, 0);
1463 	var sValue = hextorstr(hValue);
1464 	if (tag == "81") return {rfc822: sValue};
1465 	if (tag == "82") return {dns: sValue};
1466 	if (tag == "86") return {uri: sValue};
1467 	if (tag == "87") return {ip: hextoip(hValue)};
1468 	if (tag == "a4") return {dn: this.getX500Name(hValue)};
1469 	if (tag == "a0") return {other: this.getOtherName(h)};
1470 	return undefined;
1471     };
1472 
1473     /**
1474      * get subjectAltName value as array of string in the certificate (DEPRECATED)
1475      * @name getExtSubjectAltName2
1476      * @memberOf X509#
1477      * @function
1478      * @return {Object} array of alt name array
1479      * @since jsrsasign 8.0.1 x509 1.1.17
1480      * @deprecated jsrsasign 9.0.0 x509 2.0.0
1481      * @description
1482      * This method will get subject alt name extension value
1483      * as array of type and name.
1484      * If there is this in the certificate, it returns undefined;
1485      * Type of GeneralName will be shown as following:
1486      * <ul>
1487      * <li>"MAIL" - [1]rfc822Name</li>
1488      * <li>"DNS"  - [2]dNSName</li>
1489      * <li>"DN"   - [4]directoryName</li>
1490      * <li>"URI"  - [6]uniformResourceIdentifier</li>
1491      * <li>"IP"   - [7]iPAddress</li>
1492      * </ul>
1493      * @example
1494      * x = new X509();
1495      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1496      * x.getExtSubjectAltName2() →
1497      * [["DNS",  "example.com"],
1498      *  ["DNS",  "example.org"],
1499      *  ["MAIL", "foo@example.com"],
1500      *  ["IP",   "192.168.1.1"],
1501      *  ["IP",   "2001:db8::2:1"],
1502      *  ["DN",   "/C=US/O=TEST1"]]
1503      */
1504     this.getExtSubjectAltName2 = function() {
1505 	var gnValueHex, gnValueStr, gnTag;
1506 	var info = this.getExtInfo("subjectAltName");
1507 	if (info === undefined) return info;
1508 
1509 	var result = new Array();
1510 	var h = _getTLV(this.hex, info.vidx);
1511 
1512 	var a = _getChildIdx(h, 0);
1513 	for (var i = 0; i < a.length; i++) {
1514 	    gnTag = h.substr(a[i], 2);
1515 	    gnValueHex = _getV(h, a[i]);
1516 	    
1517 	    if (gnTag === "81") { // rfc822Name [1]
1518 		gnValueStr = hextoutf8(gnValueHex);
1519 		result.push(["MAIL", gnValueStr]);
1520 	    }
1521 	    if (gnTag === "82") { // dNSName [2]
1522 		gnValueStr = hextoutf8(gnValueHex);
1523 		result.push(["DNS", gnValueStr]);
1524 	    }
1525 	    if (gnTag === "84") { // directoryName [4]
1526 		gnValueStr = X509.hex2dn(gnValueHex, 0);
1527 		result.push(["DN", gnValueStr]);
1528 	    }
1529 	    if (gnTag === "86") { // uniformResourceIdentifier [6]
1530 		gnValueStr = hextoutf8(gnValueHex);
1531 		result.push(["URI", gnValueStr]);
1532 	    }
1533 	    if (gnTag === "87") { // iPAddress [7]
1534 		gnValueStr = hextoip(gnValueHex);
1535 		result.push(["IP", gnValueStr]);
1536 	    }
1537 	}
1538 	return result;
1539     };
1540 
1541     /**
1542      * get CRLDistributionPoints extension value as JSON object
1543      * @name getExtCRLDistributionPoints
1544      * @memberOf X509#
1545      * @function
1546      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1547      * @param {Boolean} critical flag (OPTIONAL)
1548      * @return {Object} JSON object of CRLDistributionPoints parameters or undefined
1549      * @since jsrsasign 9.0.0 x509 2.0.0
1550      * @see KJUR.asn1.x509.CRLDistributionPoints
1551      * @see X509#getDistributionPoint
1552      * @see X509#getDistributionPointName
1553      * @see X509#getGeneralNames
1554      * @see X509#getGeneralName
1555      * @description
1556      * This method will get certificate policies value
1557      * as an array of JSON object which has properties defined
1558      * in {@link KJUR.asn1.x509.CRLDistributionPoints}.
1559      * Result of this method can be passed to 
1560      * {@link KJUR.asn1.x509.CRLDistributionPoints} constructor.
1561      * If there is no this extension in the certificate,
1562      * it returns undefined.
1563      * @example
1564      * x = new X509();
1565      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1566      * x.getExtCRLDistributionPoints() → 
1567      * {array: [
1568      *   {dpname: {full: [{uri: "http://example.com/"}]}},
1569      *   {dpname: {full: [{uri: "ldap://example.com/"}]}}
1570      *  ],
1571      *  critical: true}
1572      */
1573     this.getExtCRLDistributionPoints = function(hExtV, critical) {
1574 	if (hExtV === undefined && critical === undefined) {
1575 	    var info = this.getExtInfo("cRLDistributionPoints");
1576 	    if (info === undefined) return undefined;
1577 	    hExtV = _getTLV(this.hex, info.vidx);
1578 	    critical = info.critical;
1579 	}
1580 
1581 	var result = {extname:"cRLDistributionPoints",array:[]};
1582 	if (critical) result.critical = true;
1583 
1584 	var a = _getChildIdx(hExtV, 0);
1585 	for (var i = 0; i < a.length; i++) {
1586 	    var hTLV = _getTLV(hExtV, a[i]);
1587 	    result.array.push(this.getDistributionPoint(hTLV));
1588 	}
1589 
1590 	return result;
1591     };
1592 
1593     /**
1594      * get DistributionPoint ASN.1 structure parameter as JSON object
1595      * @name getDistributionPoint
1596      * @memberOf X509#
1597      * @function
1598      * @param {String} h hexadecimal string of DistributionPoint
1599      * @return {Object} JSON object of DistributionPoint parameters
1600      * @since jsrsasign 9.0.0 x509 2.0.0
1601      * @see X509#getExtCRLDistributionPoints
1602      * @see X509#getDistributionPointName
1603      * @see X509#getGeneralNames
1604      * @see X509#getGeneralName
1605      * @description
1606      * This method will get DistributionPoint parameters.
1607      * Result of this method can be passed to
1608      * {@link KJUR.asn1.x509.DistributionPoint} constructor.
1609      * <br/>
1610      * NOTE: reasons[1] and CRLIssuer[2] field not supported
1611      * @example
1612      * x = new X509();
1613      * x.getDistributionPoint("30...") →
1614      * {dpname: {full: [{uri: "http://aaa.com/"}]}}
1615      */
1616     this.getDistributionPoint = function(h) {
1617 	var result = {};
1618 	var a = _getChildIdx(h, 0);
1619 	for (var i = 0; i < a.length; i++) {
1620 	    var tag = h.substr(a[i], 2);
1621 	    var hTLV = _getTLV(h, a[i]);
1622 	    if (tag == "a0") {
1623 		result.dpname = this.getDistributionPointName(hTLV);
1624 	    }
1625 	}
1626 	return result;
1627     };
1628 
1629     /**
1630      * get DistributionPointName ASN.1 structure parameter as JSON object
1631      * @name getDistributionPointName
1632      * @memberOf X509#
1633      * @function
1634      * @param {String} h hexadecimal string of DistributionPointName
1635      * @return {Object} JSON object of DistributionPointName parameters
1636      * @since jsrsasign 9.0.0 x509 2.0.0
1637      * @see X509#getExtCRLDistributionPoints
1638      * @see X509#getDistributionPoint
1639      * @see X509#getGeneralNames
1640      * @see X509#getGeneralName
1641      * @description
1642      * This method will get DistributionPointName parameters.
1643      * Result of this method can be passed to
1644      * {@link KJUR.asn1.x509.DistributionPointName} constructor.
1645      * <br/>
1646      * NOTE: nameRelativeToCRLIssuer[1] not supported
1647      * @example
1648      * x = new X509();
1649      * x.getDistributionPointName("a0...") →
1650      * {full: [{uri: "http://aaa.com/"}]}
1651      */
1652     this.getDistributionPointName = function(h) {
1653 	var result = {};
1654 	var a = _getChildIdx(h, 0);
1655 	for (var i = 0; i < a.length; i++) {
1656 	    var tag = h.substr(a[i], 2);
1657 	    var hTLV = _getTLV(h, a[i]);
1658 	    if (tag == "a0") {
1659 		result.full = this.getGeneralNames(hTLV);
1660 	    }
1661 	}
1662 	return result;
1663     };
1664 
1665     /**
1666      * get array of string for fullName URIs in cRLDistributionPoints(CDP) in the certificate (DEPRECATED)
1667      * @name getExtCRLDistributionPointsURI
1668      * @memberOf X509#
1669      * @function
1670      * @return {Object} array of fullName URIs of CDP of the certificate
1671      * @since jsrsasign 7.2.0 x509 1.1.14
1672      * @description
1673      * This method will get all fullName URIs of cRLDistributionPoints extension
1674      * in the certificate as array of URI string.
1675      * If there is this in the certificate, it returns undefined;
1676      * <br>
1677      * NOTE: Currently this method supports only fullName URI so that
1678      * other parameters will not be returned.
1679      * @example
1680      * x = new X509();
1681      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1682      * x.getExtCRLDistributionPointsURI() →
1683      * ["http://example.com/aaa.crl", "http://example.org/aaa.crl"]
1684      */
1685     this.getExtCRLDistributionPointsURI = function() {
1686 	var p = this.getExtCRLDistributionPoints();
1687 	if (p == undefined) return p;
1688 	var a = p.array;
1689 	var result = [];
1690 	for (var i = 0; i < a.length; i++) {
1691 	    try {
1692 		if (a[i].dpname.full[0].uri != undefined) {
1693 		    result.push(a[i].dpname.full[0].uri);
1694 		}
1695 	    } catch(ex) {}
1696 	}
1697 	return result;
1698     };
1699 
1700     /**
1701      * get AuthorityInfoAccess extension value in the certificate as associative array
1702      * @name getExtAIAInfo
1703      * @memberOf X509#
1704      * @function
1705      * @return {Object} associative array of AIA extension properties
1706      * @since jsrsasign 7.2.0 x509 1.1.14
1707      * @description
1708      * This method will get authority info access value
1709      * as associate array which has following properties:
1710      * <ul>
1711      * <li>ocsp - array of string for OCSP responder URL</li>
1712      * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li>
1713      * </ul>
1714      * If there is this in the certificate, it returns undefined;
1715      * @example
1716      * x = new X509();
1717      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1718      * x.getExtAIAInfo(hCert) → 
1719      * { ocsp:     ["http://ocsp.foo.com"],
1720      *   caissuer: ["http://rep.foo.com/aaa.p8m"] }
1721      */
1722     this.getExtAIAInfo = function() {
1723 	var info = this.getExtInfo("authorityInfoAccess");
1724 	if (info === undefined) return info;
1725 
1726 	var result = { ocsp: [], caissuer: [] };
1727 	var a = _getChildIdx(this.hex, info.vidx);
1728 	for (var i = 0; i < a.length; i++) {
1729 	    var hOID = _getVbyList(this.hex, a[i], [0], "06");
1730 	    var hName = _getVbyList(this.hex, a[i], [1], "86");
1731 	    if (hOID === "2b06010505073001") {
1732 		result.ocsp.push(hextoutf8(hName));
1733 	    }
1734 	    if (hOID === "2b06010505073002") {
1735 		result.caissuer.push(hextoutf8(hName));
1736 	    }
1737 	}
1738 
1739 	return result;
1740     };
1741 
1742     /**
1743      * get AuthorityInfoAccess extension value as JSON object
1744      * @name getExtAuthorityInfoAccess
1745      * @memberOf X509#
1746      * @function
1747      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1748      * @param {Boolean} critical flag (OPTIONAL)
1749      * @return {Array} JSON object of AuthorityInfoAccess parameters or undefined
1750      * @since jsrsasign 9.0.0 x509 2.0.0
1751      * @see KJUR.asn1.x509.AuthorityInfoAccess
1752      * @description
1753      * This method parse authorityInfoAccess extension. When arguments are
1754      * not specified, its extension in X509 object will be parsed.
1755      * Result of this method can be passed to 
1756      * {@link KJUR.asn1.x509.AuthorityInfoAccess} constructor.
1757      * <br>
1758      * When hExtV and critical specified as arguments, return value
1759      * will be generated from them.
1760      * @example
1761      * x = new X509();
1762      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1763      * x.getExtAuthorityInfoAccess() →
1764      * {
1765      *   critial: true, // 
1766      *   array: [{ocsp: http://ocsp.example.com/},
1767      *           {caissuer: https://repository.example.com/}]
1768      * }
1769      *
1770      * x = new X509();
1771      * x.getExtAuthorityInfoAccesss("306230...") 
1772      * x.getExtAuthorityInfoAccesss("306230...", true) 
1773      */
1774     this.getExtAuthorityInfoAccess = function(hExtV, critical) {
1775 	if (hExtV === undefined && critical === undefined) {
1776 	    var info = this.getExtInfo("authorityInfoAccess");
1777 	    if (info === undefined) return undefined;
1778 	    hExtV = _getTLV(this.hex, info.vidx);
1779 	    critical = info.critical;
1780 	}
1781 
1782 	var result = {extname:"authorityInfoAccess",array:[]};
1783 	if (critical) result.critical = true;
1784 
1785 	var a = _getChildIdx(hExtV, 0);
1786 	for (var i = 0; i < a.length; i++) {
1787 	    var hMethod = _getVbyListEx(hExtV, a[i], [0], "06");
1788 	    var hLoc = _getVbyList(hExtV, a[i], [1], "86");
1789 	    var sLoc = hextoutf8(hLoc);
1790 	    if (hMethod == "2b06010505073001") {
1791 		result.array.push({ocsp: sLoc});
1792 	    } else if (hMethod == "2b06010505073002") {
1793 		result.array.push({caissuer: sLoc});
1794 	    } else {
1795 		throw new Error("unknown method: " + hMethod);
1796 	    }
1797 	}
1798 
1799 	return result;
1800     }
1801 
1802     /**
1803      * get CertificatePolicies extension value as JSON object
1804      * @name getExtCertificatePolicies
1805      * @memberOf X509#
1806      * @function
1807      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
1808      * @param {Boolean} critical flag (OPTIONAL)
1809      * @return {Object} JSON object of CertificatePolicies parameters or undefined
1810      * @since jsrsasign 7.2.0 x509 1.1.14
1811      * @description
1812      * This method will get certificate policies value
1813      * as an array of JSON object which has properties defined
1814      * in {@link KJUR.asn1.x509.CertificatePolicies}.
1815      * Result of this method can be passed to 
1816      * {@link KJUR.asn1.x509.CertificatePolicies} constructor.
1817      * If there is no this extension in the certificate,
1818      * it returns undefined.
1819      * <br>
1820      * CAUTION: return value of JSON object format have been changed
1821      * from jsrsasign 9.0.0 without backword compatibility.
1822      * <br>
1823      * When hExtV and critical specified as arguments, return value
1824      * will be generated from them.
1825      * @example
1826      * x = new X509();
1827      * x.readCertPEM(sCertPEM); // parseExt() will also be called internally.
1828      * x.getExtCertificatePolicies() → 
1829      * { array: [
1830      *   { policyoid: "1.2.3.4" }
1831      *   { policyoid: "1.2.3.5",
1832      *     array: [
1833      *       { cps: "https://example.com/" },
1834      *       { unotice: { exptext: { type: "bmp", str: "sample text" } } }
1835      *     ] 
1836      *   }
1837      * ]}
1838      */
1839     this.getExtCertificatePolicies = function(hExtV, critical) {
1840 	if (hExtV === undefined && critical === undefined) {
1841 	    var info = this.getExtInfo("certificatePolicies");
1842 	    if (info === undefined) return undefined;
1843 	    hExtV = _getTLV(this.hex, info.vidx);
1844 	    critical = info.critical;
1845 	}
1846 	var result = {extname:"certificatePolicies",array:[]};
1847 	if (critical) result.critical = true;
1848 
1849 	var aIdxPI = _getChildIdx(hExtV, 0); // PolicyInformation list index
1850 	for (var i = 0; i < aIdxPI.length; i++) {
1851 	    var hPolicyInformation = _getTLV(hExtV, aIdxPI[i]);
1852 	    var polinfo = this.getPolicyInformation(hPolicyInformation);
1853 	    result.array.push(polinfo);
1854 	}
1855 	return result;
1856     }
1857 
1858     /**
1859      * get PolicyInformation ASN.1 structure parameter as JSON object
1860      * @name getPolicyInformation
1861      * @memberOf X509#
1862      * @function
1863      * @param {String} h hexadecimal string of PolicyInformation
1864      * @return {Object} JSON object of PolicyInformation parameters
1865      * @since jsrsasign 9.0.0 x509 2.0.0
1866      * @description
1867      * This method will get PolicyInformation parameters defined in
1868      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
1869      * RFC 5280 4.2.1.4</a>.
1870      * <pre>
1871      * PolicyInformation ::= SEQUENCE {
1872      *      policyIdentifier   CertPolicyId,
1873      *      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
1874      *                              PolicyQualifierInfo OPTIONAL }
1875      * </pre>
1876      * Result of this method can be passed to
1877      * {@link KJUR.asn1.x509.PolicyInformation} constructor.
1878      * @example
1879      * x = new X509();
1880      * x.getPolicyInformation("30...") →
1881      * {
1882      *     policyoid: "2.16.840.1.114412.2.1",
1883      *     array: [{cps: "https://www.digicert.com/CPS"}]
1884      * }
1885      */
1886     this.getPolicyInformation = function(h) {
1887 	var result = {};
1888 
1889 	var hPOLICYOID = _getVbyList(h, 0, [0], "06");
1890 	result.policyoid = _oidname(hPOLICYOID);
1891 	
1892 	var idxPQSEQ = _getIdxbyListEx(h, 0, [1], "30");
1893 	if (idxPQSEQ != -1) {
1894 	    result.array = [];
1895 	    var aIdx = _getChildIdx(h, idxPQSEQ);
1896 	    for (var j = 0; j < aIdx.length; j++) {
1897 		var hPQI = _getTLV(h, aIdx[j]);
1898 		var pqinfo = this.getPolicyQualifierInfo(hPQI);
1899 		result.array.push(pqinfo);
1900 	    }
1901 	}
1902 
1903 	return result;
1904     };
1905 
1906     /**
1907      * getOtherName ASN.1 structure parameter as JSON object<br/>
1908      * @name getOtherName
1909      * @memberOf X509#
1910      * @param {String} h hexadecimal string of GeneralName
1911      * @return {Array} associative array of OtherName
1912      * @since jsrsasign 10.5.3 x509 2.0.12
1913      * @see KJUR.asn1.x509.GeneralNames
1914      * @see KJUR.asn1.x509.GeneralName
1915      * @see KJUR.asn1.x509.OtherName
1916      * @see X509#getGeneralName
1917      * @see ASN1HEX#parse
1918      *
1919      * @description
1920      * This method will get OtherName parameters defined in
1921      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6">
1922      * RFC 5280 4.2.1.6</a>.
1923      * <pre>
1924      * OtherName ::= SEQUENCE {
1925      *    type-id    OBJECT IDENTIFIER,
1926      *    value      [0] EXPLICIT ANY DEFINED BY type-id }
1927      * </pre>
1928      * The value of member "other" is converted by 
1929      * {@link ASN1HEX#parse}.
1930      *
1931      * @example
1932      * x = new X509();
1933      * x.getOtherName("30...") →
1934      * { oid: "1.2.3.4",
1935      *   value: {utf8str: {str: "aaa"}} }
1936      */
1937     this.getOtherName = function(h) {
1938         var result = {};
1939         var a = _getChildIdx(h, 0);
1940         var hOID = _getVbyList(h, a[0], [], "06");
1941         var hValue = _getVbyList(h, a[1], []);
1942 	result.oid = _oidname(hOID);
1943 	result.value = _ASN1HEX_parse(hValue);
1944         return result;
1945     };
1946 
1947     /**
1948      * get PolicyQualifierInfo ASN.1 structure parameter as JSON object
1949      * @name getPolicyQualifierInfo
1950      * @memberOf X509#
1951      * @function
1952      * @param {String} h hexadecimal string of PolicyQualifierInfo
1953      * @return {Object} JSON object of PolicyQualifierInfo parameters
1954      * @since jsrsasign 9.0.0 x509 2.0.0
1955      * @see X509#getExtCertificatePolicies
1956      * @see X509#getPolicyInformation
1957      * @description
1958      * This method will get 
1959      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
1960      * PolicyQualifierInfo</a> parameters.
1961      * <pre>
1962      * PolicyQualifierInfo ::= SEQUENCE {
1963      *      policyQualifierId  PolicyQualifierId,
1964      *      qualifier          ANY DEFINED BY policyQualifierId }
1965      * id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
1966      * id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
1967      * id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
1968      * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
1969      * Qualifier ::= CHOICE {
1970      *      cPSuri           CPSuri,
1971      *      userNotice       UserNotice }
1972      * CPSuri ::= IA5String
1973      * </pre>
1974      * Result of this method can be passed to 
1975      * {@link KJUR.asn1.x509.PolicyQualifierInfo} constructor.
1976      * @example
1977      * x = new X509();
1978      * x.getPolicyQualifierInfo("30...") 
1979      * → {unotice: {exptext: {type: 'utf8', str: 'aaa'}}}
1980      * x.getPolicyQualifierInfo("30...") 
1981      * → {cps: "https://repository.example.com/"}
1982      */
1983     this.getPolicyQualifierInfo = function(h) {
1984 	var result = {};
1985 	var hPQOID = _getVbyList(h, 0, [0], "06");
1986 	if (hPQOID === "2b06010505070201") { // cps
1987 	    var hCPSURI = _getVbyListEx(h, 0, [1], "16");
1988 	    result.cps = hextorstr(hCPSURI);
1989 	} else if (hPQOID === "2b06010505070202") { // unotice
1990 	    var hUserNotice = _getTLVbyList(h, 0, [1], "30");
1991 	    result.unotice = this.getUserNotice(hUserNotice);
1992 	}
1993 	return result;
1994     };
1995 
1996     /**
1997      * get UserNotice ASN.1 structure parameter as JSON object
1998      * @name getUserNotice
1999      * @memberOf X509#
2000      * @function
2001      * @param {String} h hexadecimal string of UserNotice
2002      * @return {Object} JSON object of UserNotice parameters
2003      * @since jsrsasign 9.0.0 x509 2.0.0
2004      * @see X509#getExtCertificatePolicies
2005      * @see X509#getPolicyInformation
2006      * @see X509#getPolicyQualifierInfo
2007      * @description
2008      * This method will get 
2009      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
2010      * UserNotice</a> parameters.
2011      * <pre>
2012      * UserNotice ::= SEQUENCE {
2013      *      noticeRef        NoticeReference OPTIONAL,
2014      *      explicitText     DisplayText OPTIONAL }
2015      * </pre>
2016      * Result of this method can be passed to 
2017      * {@link KJUR.asn1.x509.NoticeReference} constructor.
2018      * <br/>
2019      * NOTE: NoticeReference parsing is currently not supported and
2020      * it will be ignored.
2021      * @example
2022      * x = new X509();
2023      * x.getUserNotice("30...") → {exptext: {type: 'utf8', str: 'aaa'}}
2024      */
2025     this.getUserNotice = function(h) {
2026 	var result = {};
2027 	var a = _getChildIdx(h, 0);
2028 	for (var i = 0; i < a.length; i++) {
2029 	    var hItem = _getTLV(h, a[i]);
2030 	    if (hItem.substr(0, 2) != "30") {
2031 		result.exptext = this.getDisplayText(hItem);
2032 	    }
2033 	}
2034 	return result;
2035     };
2036 
2037     /**
2038      * get DisplayText ASN.1 structure parameter as JSON object
2039      * @name getDisplayText
2040      * @memberOf X509#
2041      * @function
2042      * @param {String} h hexadecimal string of DisplayText
2043      * @return {Object} JSON object of DisplayText parameters
2044      * @since jsrsasign 9.0.0 x509 2.0.0
2045      * @see X509#getExtCertificatePolicies
2046      * @see X509#getPolicyInformation
2047      * @description
2048      * This method will get 
2049      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
2050      * DisplayText</a> parameters.
2051      * <pre>
2052      * DisplayText ::= CHOICE {
2053      *      ia5String        IA5String      (SIZE (1..200)),
2054      *      visibleString    VisibleString  (SIZE (1..200)),
2055      *      bmpString        BMPString      (SIZE (1..200)),
2056      *      utf8String       UTF8String     (SIZE (1..200)) }     
2057      * </pre>
2058      * Result of this method can be passed to 
2059      * {@link KJUR.asn1.x509.DisplayText} constructor.
2060      * @example
2061      * x = new X509();
2062      * x.getDisplayText("0c03616161") &rarr {type: 'utf8', str: 'aaa'}
2063      * x.getDisplayText("1e03616161") &rarr {type: 'bmp',  str: 'aaa'}
2064      */
2065     this.getDisplayText = function(h) {
2066 	var _DISPLAYTEXTTAG = {"0c": "utf8", "16": "ia5", "1a": "vis" , "1e": "bmp"};
2067 	var result = {};
2068 	result.type = _DISPLAYTEXTTAG[h.substr(0, 2)];
2069 	result.str = hextorstr(_getV(h, 0));
2070 	return result;
2071     };
2072 
2073     /**
2074      * get PolicyMappings extension value as JSON object<br/>
2075      * @name getExtPolicyMappings
2076      * @memberOf X509#
2077      * @function
2078      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
2079      * @param {Boolean} critical flag (OPTIONAL)
2080      * @return {Object} JSON object of PolicyMappings parameters or undefined
2081      * @since jsrsasign 10.6.1 x509 2.1.1
2082      * @see KJUR.asn1.x509.PolicyMappings
2083      *
2084      * @description
2085      * This method will get certificate policies value
2086      * as an array of JSON object which has properties defined
2087      * in {@link KJUR.asn1.x509.PolicyMappings}.
2088      * Result of this method can be passed to 
2089      * {@link KJUR.asn1.x509.PolicyMappings} constructor.
2090      * If there is no this extension in the certificate,
2091      * it returns undefined.
2092      * <br>
2093      * When hExtV and critical specified as arguments, return value
2094      * will be generated from them.
2095      * @example
2096      * x = new X509(sCertPEM);
2097      * x.getExtPolicyMappings() → 
2098      * { extname: "policyMappings",
2099      *   critical: true,
2100      *   array: [["1.2.3", "1.4.5"],["0.1.2", "anyPolicy"]]}
2101      */
2102     this.getExtPolicyMappings = function(hExtV, critical) {
2103 	var aExtVCritical = this.getCriticalExtV("policyMappings", hExtV, critical);
2104 	hExtV = aExtVCritical[0];
2105 	critical = aExtVCritical[1];
2106 	if (hExtV == null) return undefined;
2107 	var result = {extname: "policyMappings"};
2108 	if (critical) result.critical = true;
2109 
2110 	try {
2111 	    var p = _ASN1HEX_parse(hExtV);
2112 	    //result._asn1 = p;
2113 	    var aPair = p.seq;
2114 	    var a = [];
2115 	    for (var i = 0; i < aPair.length; i++) {
2116 		var aOid = aPair[i].seq;
2117 		a.push([aOid[0].oid, aOid[1].oid]);
2118 	    }
2119 	    result.array = a;
2120 	} catch(ex) {
2121 	    throw new _Error("malformed policyMappings");
2122 	}
2123 
2124 	return result;
2125     };
2126 
2127     /**
2128      * get PolicyConstraints extension value as JSON object<br/>
2129      * @name getExtPolicyConstraints
2130      * @memberOf X509#
2131      * @function
2132      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
2133      * @param {Boolean} critical flag (OPTIONAL)
2134      * @return {Object} JSON object of PolicyConstraints parameters or undefined
2135      * @since jsrsasign 10.6.1 x509 2.1.1
2136      * @see KJUR.asn1.x509.PolicyConstraints
2137      *
2138      * @description
2139      * This method will get certificate policies value
2140      * as an array of JSON object which has properties defined
2141      * in {@link KJUR.asn1.x509.PolicyConstraints}.
2142      * Result of this method can be passed to 
2143      * {@link KJUR.asn1.x509.PolicyConstraints} constructor.
2144      * If there is no this extension in the certificate,
2145      * it returns undefined.
2146      * <br>
2147      * When hExtV and critical specified as arguments, return value
2148      * will be generated from them.
2149      * @example
2150      * x = new X509(sCertPEM);
2151      * x.getExtPolicyConstraints() → 
2152      * { extname: "policyConstraints",
2153      *   critical: true,
2154      *   reqexp: 3,
2155      *   inhibit: 3 }
2156      */
2157     this.getExtPolicyConstraints = function(hExtV, critical) {
2158 	var aExtVCritical = this.getCriticalExtV("policyConstraints", hExtV, critical);
2159 	hExtV = aExtVCritical[0];
2160 	critical = aExtVCritical[1];
2161 	if (hExtV == null) return undefined;
2162 	var result = {extname: "policyConstraints"};
2163 	if (critical) result.critical = true;
2164 
2165 	var p = _ASN1HEX_parse(hExtV);
2166 	try {
2167 	    var aItem = p.seq;
2168 	    for (var i = 0; i < aItem.length; i++) {
2169 		var pTag = aItem[i].tag;
2170 		if (pTag.explicit != false) continue;
2171 		if (pTag.tag == "80") result.reqexp = parseInt(pTag.hex, 16);
2172 		if (pTag.tag == "81") result.inhibit = parseInt(pTag.hex, 16);
2173 	    }
2174 	} catch(ex) {
2175 	    return new _Error("malformed policyConstraints value");
2176 	}
2177 	return result;
2178     };
2179 
2180     /**
2181      * get InhibitAnyPolicy extension value as JSON object<br/>
2182      * @name getExtInhibitAnyPolicy
2183      * @memberOf X509#
2184      * @function
2185      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
2186      * @param {Boolean} critical flag (OPTIONAL)
2187      * @return {Object} JSON object of InhibitAnyPolicy parameters or undefined
2188      * @since jsrsasign 10.6.1 x509 2.1.1
2189      * @see KJUR.asn1.x509.InhibitAnyPolicy
2190      *
2191      * @description
2192      * This method will get certificate policies value
2193      * as an array of JSON object which has properties defined
2194      * in {@link KJUR.asn1.x509.InhibitAnyPolicy}.
2195      * Result of this method can be passed to 
2196      * {@link KJUR.asn1.x509.InhibitAnyPolicy} constructor.
2197      * If there is no this extension in the certificate,
2198      * it returns undefined.
2199      * <br>
2200      * When hExtV and critical specified as arguments, return value
2201      * will be generated from them.
2202      * @example
2203      * x = new X509(sCertPEM);
2204      * x.getExtInhibitAnyPolicy() → 
2205      * { extname: "policyConstraints",
2206      *   critical: true,
2207      *   skip: 3 }
2208      *
2209      * x.getExtInhibitAnyPolicy("020103", true) → same as above
2210      */
2211     this.getExtInhibitAnyPolicy = function(hExtV, critical) {
2212 	var aExtVCritical = this.getCriticalExtV("inhibitAnyPolicy", hExtV, critical);
2213 	hExtV = aExtVCritical[0];
2214 	critical = aExtVCritical[1];
2215 	if (hExtV == null) return undefined;
2216 	var result = {extname: "inhibitAnyPolicy"};
2217 	if (critical) result.critical = true;
2218 
2219 	var skip = _getInt(hExtV, 0);
2220 	if (skip == -1) return new _Error("wrong value");
2221 	result.skip = skip;
2222 	return result;
2223     };
2224 
2225     /**
2226      * parse cRLNumber CRL extension as JSON object<br/>
2227      * @name getExtCRLNumber
2228      * @memberOf X509#
2229      * @function
2230      * @param {String} hExtV hexadecimal string of extension value
2231      * @param {Boolean} critical flag
2232      * @since jsrsasign 9.1.1 x509 2.0.1
2233      * @see KJUR.asn1.x509.CRLNumber
2234      * @see X509#getExtParamArray
2235      * @description
2236      * This method parses
2237      * CRLNumber CRL extension value defined in
2238      * <a href="https://tools.ietf.org/html/rfc5280#section-5.2.3">
2239      * RFC 5280 5.2.3</a> as JSON object.
2240      * <pre>
2241      * id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
2242      * CRLNumber ::= INTEGER (0..MAX)
2243      * </pre>
2244      * <br/>
2245      * Result of this method can be passed to 
2246      * {@link KJUR.asn1.x509.CRLNumber} constructor.
2247      * @example
2248      * crl = X509CRL("-----BEGIN X509 CRL...");
2249      * ... get hExtV and critical flag ...
2250      * crl.getExtCRLNumber("02...", false) →
2251      * {extname: "cRLNumber", num: {hex: "12af"}}
2252      */
2253     this.getExtCRLNumber = function(hExtV, critical) {
2254 	var result = {extname:"cRLNumber"};
2255 	if (critical) result.critical = true;
2256 
2257 	if (hExtV.substr(0, 2) == "02") {
2258 	    result.num = {hex: _getV(hExtV, 0)};
2259 	    return result;
2260 	}
2261 	throw new _Error("hExtV parse error: " + hExtV);
2262     };
2263 
2264     /**
2265      * parse cRLReason CRL entry extension as JSON object<br/>
2266      * @name getExtCRLReason
2267      * @memberOf X509#
2268      * @function
2269      * @param {String} hExtV hexadecimal string of extension value
2270      * @param {Boolean} critical flag
2271      * @since jsrsasign 9.1.1 x509 2.0.1
2272      * @see KJUR.asn1.x509.CRLReason
2273      * @see X509#getExtParamArray
2274      * @description
2275      * This method parses
2276      * CRLReason CRL entry extension value defined in
2277      * <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1">
2278      * RFC 5280 5.3.1</a> as JSON object.
2279      * <pre>
2280      * id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
2281      * -- reasonCode ::= { CRLReason }
2282      * CRLReason ::= ENUMERATED {
2283      *      unspecified             (0),
2284      *      keyCompromise           (1),
2285      *      cACompromise            (2),
2286      *      affiliationChanged      (3),
2287      *      superseded              (4),
2288      *      cessationOfOperation    (5),
2289      *      certificateHold         (6),
2290      *      removeFromCRL           (8),
2291      *      privilegeWithdrawn      (9),
2292      *      aACompromise           (10) }
2293      * </pre>
2294      * <br/>
2295      * Result of this method can be passed to 
2296      * {@link KJUR.asn1.x509.CRLReason} constructor.
2297      * @example
2298      * crl = X509CRL("-----BEGIN X509 CRL...");
2299      * ... get hExtV and critical flag ...
2300      * crl.getExtCRLReason("02...", false) →
2301      * {extname: "cRLReason", code: 3}
2302      */
2303     this.getExtCRLReason = function(hExtV, critical) {
2304 	var result = {extname:"cRLReason"};
2305 	if (critical) result.critical = true;
2306 
2307 	if (hExtV.substr(0, 2) == "0a") {
2308 	    result.code = parseInt(_getV(hExtV, 0), 16);
2309 	    return result;
2310 	}
2311 	throw new Error("hExtV parse error: " + hExtV);
2312     };
2313 
2314     /**
2315      * parse OCSPNonce OCSP extension as JSON object<br/>
2316      * @name getExtOcspNonce
2317      * @memberOf X509#
2318      * @function
2319      * @param {String} hExtV hexadecimal string of extension value
2320      * @param {Boolean} critical flag
2321      * @return {Array} JSON object of parsed OCSPNonce extension
2322      * @since jsrsasign 9.1.6 x509 2.0.3
2323      * @see KJUR.asn1.x509.OCSPNonce
2324      * @see X509#getExtParamArray
2325      * @see X509#getExtParam
2326      * @description
2327      * This method parses
2328      * Nonce OCSP extension value defined in
2329      * <a href="https://tools.ietf.org/html/rfc6960#section-4.4.1">
2330      * RFC 6960 4.4.1</a> as JSON object.
2331      * <pre>
2332      * id-pkix-ocsp           OBJECT IDENTIFIER ::= { id-ad-ocsp }
2333      * id-pkix-ocsp-nonce     OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 }
2334      * Nonce ::= OCTET STRING
2335      * </pre>
2336      * <br/>
2337      * Result of this method can be passed to 
2338      * {@link KJUR.asn1.x509.OCSPNonce} constructor.
2339      * @example
2340      * x = new X509();
2341      * x.getExtOcspNonce(<<extn hex value >>) →
2342      * { extname: "ocspNonce", hex: "1a2b..." }
2343      */
2344     this.getExtOcspNonce = function(hExtV, critical) {
2345 	var result = {extname:"ocspNonce"};
2346 	if (critical) result.critical = true;
2347 
2348 	var hNonce = _getV(hExtV, 0);
2349 	result.hex = hNonce;
2350 
2351 	return result;
2352     };
2353 
2354     /**
2355      * parse OCSPNoCheck OCSP extension as JSON object<br/>
2356      * @name getExtOcspNoCheck
2357      * @memberOf X509#
2358      * @function
2359      * @param {String} hExtV hexadecimal string of extension value
2360      * @param {Boolean} critical flag
2361      * @return {Array} JSON object of parsed OCSPNoCheck extension
2362      * @since jsrsasign 9.1.6 x509 2.0.3
2363      * @see KJUR.asn1.x509.OCSPNoCheck
2364      * @see X509#getExtParamArray
2365      * @see X509#getExtParam
2366      * @description
2367      * This method parses
2368      * OCSPNoCheck extension value defined in
2369      * <a href="https://tools.ietf.org/html/rfc6960#section-4.2.2.2.1">
2370      * RFC 6960 4.2.2.2.1</a> as JSON object.
2371      * <pre>
2372      * id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 }
2373      * </pre>
2374      * <br/>
2375      * Result of this method can be passed to 
2376      * {@link KJUR.asn1.x509.OCSPNoCheck} constructor.
2377      * @example
2378      * x = new X509();
2379      * x.getExtOcspNoCheck(<<extn hex value >>) →
2380      * { extname: "ocspNoCheck" }
2381      */
2382     this.getExtOcspNoCheck = function(hExtV, critical) {
2383 	var result = {extname:"ocspNoCheck"};
2384 	if (critical) result.critical = true;
2385 
2386 	return result;
2387     };
2388 
2389     /**
2390      * parse AdobeTimeStamp extension as JSON object<br/>
2391      * @name getExtAdobeTimeStamp
2392      * @memberOf X509#
2393      * @function
2394      * @param {String} hExtV hexadecimal string of extension value
2395      * @param {Boolean} critical flag
2396      * @return {Array} JSON object of parsed AdobeTimeStamp extension
2397      * @since jsrsasign 10.0.1 x509 2.0.5
2398      * @see KJUR.asn1.x509.AdobeTimeStamp
2399      * @see X509#getExtParamArray
2400      * @see X509#getExtParam
2401      * @description
2402      * This method parses
2403      * X.509v3 AdobeTimeStamp private extension value defined in the
2404      * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSigDC/oids.html">
2405      * Adobe site</a> as JSON object.
2406      * This extension provides the URL location for time stamp service.
2407      * <pre>
2408      * adbe- OBJECT IDENTIFIER ::=  { adbe(1.2.840.113583) acrobat(1) security(1) x509Ext(9) 1 }
2409      *  ::= SEQUENCE {
2410      *     version INTEGER  { v1(1) }, -- extension version
2411      *     location GeneralName (In v1 GeneralName can be only uniformResourceIdentifier)
2412      *     requiresAuth        boolean (default false), OPTIONAL }
2413      * </pre>
2414      * <br/>
2415      * Result of this method can be passed to 
2416      * {@link KJUR.asn1.x509.AdobeTimeStamp} constructor.
2417      * <br/>
2418      * NOTE: This extesion doesn't seem to have official name. This may be called as "pdfTimeStamp".
2419      * @example
2420      * x.getExtAdobeTimeStamp(<<extn hex value >>) →
2421      * { extname: "adobeTimeStamp", uri: "http://tsa.example.com/" reqauth: true }
2422      */
2423     this.getExtAdobeTimeStamp = function(hExtV, critical) {
2424 	if (hExtV === undefined && critical === undefined) {
2425 	    var info = this.getExtInfo("adobeTimeStamp");
2426 	    if (info === undefined) return undefined;
2427 	    hExtV = _getTLV(this.hex, info.vidx);
2428 	    critical = info.critical;
2429 	}
2430 
2431 	var result = {extname:"adobeTimeStamp"};
2432 	if (critical) result.critical = true;
2433 
2434 	var a = _getChildIdx(hExtV, 0);
2435 	if (a.length > 1) {
2436 	    var hGN = _getTLV(hExtV, a[1])
2437 	    var gnParam = this.getGeneralName(hGN);
2438 	    if (gnParam.uri != undefined) {
2439 		result.uri = gnParam.uri;
2440 	    }
2441 	}
2442 	if (a.length > 2) {
2443 	    var hBool = _getTLV(hExtV, a[2]);
2444 	    if (hBool == "0101ff") result.reqauth = true;
2445 	    if (hBool == "010100") result.reqauth = false;
2446 	}
2447 
2448 	return result;
2449     };
2450 
2451     // ===== BEGIN X500Name related =====================================
2452     /*
2453      * convert ASN.1 parsed object to attrTypeAndValue assoc array<br/>
2454      * @name _convATV
2455      * @param p associative array of parsed attrTypeAndValue object
2456      * @return attrTypeAndValue associative array
2457      * @since jsrsasign 10.5.12 x509 2.0.14
2458      * @example
2459      * _convATV({seq: [...]} &rarr: {type:"C",value:"JP",ds:"prn"}
2460      */
2461     var _convATV = function(p) {
2462 	var result = {};
2463 	try {
2464 	    var name = p.seq[0].oid;
2465 	    var oid = KJUR.asn1.x509.OID.name2oid(name);
2466 	    result.type = KJUR.asn1.x509.OID.oid2atype(oid);
2467 	    var item1 = p.seq[1];
2468 	    if (item1.utf8str != undefined) {
2469 		result.ds = "utf8";
2470 		result.value = item1.utf8str.str;
2471 	    } else if (item1.numstr != undefined) {
2472 		result.ds = "num";
2473 		result.value = item1.numstr.str;
2474 	    } else if (item1.telstr != undefined) {
2475 		result.ds = "tel";
2476 		result.value = item1.telstr.str;
2477 	    } else if (item1.prnstr != undefined) {
2478 		result.ds = "prn";
2479 		result.value = item1.prnstr.str;
2480 	    } else if (item1.ia5str != undefined) {
2481 		result.ds = "ia5";
2482 		result.value = item1.ia5str.str;
2483 	    } else if (item1.visstr != undefined) {
2484 		result.ds = "vis";
2485 		result.value = item1.visstr.str;
2486 	    } else if (item1.bmpstr != undefined) {
2487 		result.ds = "bmp";
2488 		result.value = item1.bmpstr.str;
2489 	    } else {
2490 		throw "error";
2491 	    }
2492 	    return result;
2493 	} catch(ex) {
2494 	    throw new Erorr("improper ASN.1 parsed AttrTypeAndValue");
2495 	}
2496     };
2497 
2498     /*
2499      * convert ASN.1 parsed object to RDN array<br/>
2500      * @name _convRDN
2501      * @param p associative array of parsed RDN object
2502      * @return RDN array
2503      * @since jsrsasign 10.5.12 x509 2.0.14
2504      * @example
2505      * _convRDN({set: [...]} &rarr: [{type:"C",value:"JP",ds:"prn"}]
2506      */
2507     var _convRDN = function(p) {
2508 	try {
2509 	    return p.set.map(function(pATV){return _convATV(pATV)});
2510 	} catch(ex) {
2511 	    throw new Error("improper ASN.1 parsed RDN: " + ex);
2512 	}
2513     };
2514 
2515     /*
2516      * convert ASN.1 parsed object to X500Name array<br/>
2517      * @name _convX500Name
2518      * @param p associative array of parsed X500Name array object
2519      * @return RDN array
2520      * @since jsrsasign 10.5.12 x509 2.0.14
2521      * @example
2522      * _convX500Name({seq: [...]} &rarr: [[{type:"C",value:"JP",ds:"prn"}]]
2523      */
2524     var _convX500Name = function(p) {
2525 	try {
2526 	    return p.seq.map(function(pRDN){return _convRDN(pRDN)});
2527 	} catch(ex) {
2528 	    throw new Error("improper ASN.1 parsed X500Name: " + ex);
2529 	}
2530     };
2531 
2532     this.getX500NameRule = function(aDN) {
2533 	var isPRNRule = true;
2534 	var isUTF8Rule = true;
2535 	var isMixedRule = false;
2536 	var logfull = "";
2537 	var logcheck = "";
2538 	var lasttag = null;
2539 
2540 	var a = [];
2541 	for (var i = 0; i < aDN.length; i++) {
2542 	    var aRDN = aDN[i];
2543 	    for (var j = 0; j < aRDN.length; j++) {
2544 		a.push(aRDN[j]);
2545 	    }
2546 	}
2547 
2548 	for (var i = 0; i < a.length; i++) {
2549 	    var item = a[i];
2550 	    var tag = item.ds;
2551 	    var value = item.value;
2552 	    var type = item.type;
2553 	    logfull += ":" + tag;
2554 	    
2555 	    if (tag != "prn" && tag != "utf8" && tag != "ia5") {
2556 		return "mixed";
2557 	    }
2558 	    if (tag == "ia5") {
2559 		if (type != "CN") {
2560 		    return "mixed";
2561 		} else {
2562 		    if (! KJUR.lang.String.isMail(value)) {
2563 			return "mixed";
2564 		    } else {
2565 			continue;
2566 		    }
2567 		}
2568 	    }
2569 	    if (type == "C") {
2570 		if (tag == "prn") {
2571 		    continue;
2572 		} else {
2573 		    return "mixed";
2574 		}
2575 	    }
2576 	    logcheck += ":" + tag;
2577 	    if (lasttag == null) {
2578 		lasttag = tag;
2579 	    } else {
2580 		if (lasttag !== tag) return "mixed";
2581 	    }
2582 	}
2583 	if (lasttag == null) {
2584 	    return "prn";
2585 	} else {
2586 	    return lasttag;
2587 	}
2588     };
2589 
2590     /**
2591      * get AttributeTypeAndValue ASN.1 structure parameter as JSON object<br/>
2592      * @name getAttrTypeAndValue
2593      * @memberOf X509#
2594      * @function
2595      * @param {String} h hexadecimal string of AttributeTypeAndValue
2596      * @return {Object} JSON object of AttributeTypeAndValue parameters
2597      * @since jsrsasign 9.0.0 x509 2.0.0
2598      * @see X509#getX500Name
2599      * @see X509#getRDN
2600      * @description
2601      * This method will get AttributeTypeAndValue parameters defined in
2602      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2603      * RFC 5280 4.1.2.4</a>.
2604      * <pre>
2605      * AttributeTypeAndValue ::= SEQUENCE {
2606      *   type     AttributeType,
2607      *   value    AttributeValue }
2608      * AttributeType ::= OBJECT IDENTIFIER
2609      * AttributeValue ::= ANY -- DEFINED BY AttributeType
2610      * </pre>
2611      * <ul>
2612      * <li>{String}type - AttributeType name or OID(ex. C,O,CN)</li>
2613      * <li>{String}value - raw string of ASN.1 value of AttributeValue</li>
2614      * <li>{String}ds - DirectoryString type of AttributeValue</li>
2615      * </ul>
2616      * "ds" has one of following value:
2617      * <ul>
2618      * <li>utf8 - (0x0c) UTF8String</li>
2619      * <li>num  - (0x12) NumericString</li>
2620      * <li>prn  - (0x13) PrintableString</li>
2621      * <li>tel  - (0x14) TeletexString</li>
2622      * <li>ia5  - (0x16) IA5String</li>
2623      * <li>vis  - (0x1a) VisibleString</li>
2624      * <li>bmp  - (0x1e) BMPString</li>
2625      * </ul>
2626      * @example
2627      * x = new X509();
2628      * x.getAttrTypeAndValue("30...") →
2629      * {type:"CN",value:"john.smith@example.com",ds:"ia5"} or
2630      * {type:"O",value:"Sample Corp.",ds:"prn"}
2631      */
2632     // unv  - (0x1c??) UniversalString ... for future
2633     this.getAttrTypeAndValue = function(h) {
2634 	var p = _ASN1HEX_parse(h);
2635 	return _convATV(p);
2636     };
2637 
2638     /**
2639      * get RelativeDistinguishedName ASN.1 structure parameter array<br/>
2640      * @name getRDN
2641      * @memberOf X509#
2642      * @function
2643      * @param {String} h hexadecimal string of RDN
2644      * @return {Array} array of AttrTypeAndValue parameters
2645      * @since jsrsasign 9.0.0 x509 2.0.0
2646      * @see X509#getX500Name
2647      * @see X509#getRDN
2648      * @see X509#getAttrTypeAndValue
2649      * @description
2650      * This method will get RelativeDistinguishedName parameters defined in
2651      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2652      * RFC 5280 4.1.2.4</a>.
2653      * <pre>
2654      * RelativeDistinguishedName ::=
2655      *   SET SIZE (1..MAX) OF AttributeTypeAndValue
2656      * </pre>
2657      * @example
2658      * x = new X509();
2659      * x.getRDN("31...") →
2660      * [{type:"C",value:"US",ds:"prn"}] or
2661      * [{type:"O",value:"Sample Corp.",ds:"prn"}] or
2662      * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]
2663      */
2664     this.getRDN = function(h) {
2665 	var p = _ASN1HEX_parse(h);
2666 	return _convRDN(p);
2667     };
2668 
2669     /**
2670      * get X.500 Name ASN.1 structure parameter array<br/>
2671      * @name getX500NameArray
2672      * @memberOf X509#
2673      * @function
2674      * @param {String} h hexadecimal string of Name
2675      * @return {Array} array of RDN parameter array
2676      * @since jsrsasign 10.0.6 x509 2.0.9
2677      * @see X509#getX500Name
2678      * @see X509#getRDN
2679      * @see X509#getAttrTypeAndValue
2680      * @description
2681      * This method will get Name parameter defined in
2682      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2683      * RFC 5280 4.1.2.4</a>.
2684      * <pre>
2685      * Name ::= CHOICE { -- only one possibility for now --
2686      *   rdnSequence  RDNSequence }
2687      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
2688      * </pre>
2689      * @example
2690      * x = new X509();
2691      * x.getX500NameArray("30...") →
2692      * [[{type:"C",value:"US",ds:"prn"}],
2693      *  [{type:"O",value:"Sample Corp.",ds:"utf8"}],
2694      *  [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]]
2695      */
2696     this.getX500NameArray = function(h) {
2697 	var p = _ASN1HEX_parse(h);
2698 	return _convX500Name(p);
2699     };
2700 
2701     /**
2702      * get Name ASN.1 structure parameter array<br/>
2703      * @name getX500Name
2704      * @memberOf X509#
2705      * @function
2706      * @param {String} h hexadecimal string of Name
2707      * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false)
2708      * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false)
2709      * @return {Array} array of RDN parameter array
2710      * @since jsrsasign 9.0.0 x509 2.0.0
2711      * @see X509#getX500NameArray
2712      * @see X509#getRDN
2713      * @see X509#getAttrTypeAndValue
2714      * @see X509#c14nRDNArray
2715      * @see KJUR.asn1.x509.X500Name
2716      * @see KJUR.asn1.x509.GeneralName
2717      * @see KJUR.asn1.x509.GeneralNames
2718      *
2719      * @description
2720      * This method will get Name parameter defined in
2721      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2722      * RFC 5280 4.1.2.4</a>.
2723      * <pre>
2724      * Name ::= CHOICE { -- only one possibility for now --
2725      *   rdnSequence  RDNSequence }
2726      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
2727      * </pre>
2728      * <br>
2729      * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 
2730      * supported to conclude a canonicalized name for caseIgnoreMatch
2731      * desribed in <a href="https://tools.ietf.org/html/rfc4518">
2732      * RFC 4518</a>.
2733      *
2734      * @example
2735      * x = new X509();
2736      * x.getX500Name("30...") →
2737      * { array: [
2738      *     [{type:"C",value:"US",ds:"prn"}],
2739      *     [{type:"O",value:"Sample Corp.",ds:"utf8"}],
2740      *     [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]
2741      *   ],
2742      *   str: "/C=US/O=Sample Corp./CN=john.smith@example.com",
2743      *   hex: "30..." }
2744      *
2745      * x.getX500Name("30...", true) →
2746      * { array: [
2747      *     [{type:"C",value:"US",ds:"prn"}],
2748      *     [{type:"O",value:"Sample    Corp.",ds:"utf8"}]
2749      *   ],
2750      *   str: "/C=US/O=Sample    Corp.",
2751      *   canon: "/c=us/o=sample corp.",
2752      *   hex: "30..." }
2753      */
2754     this.getX500Name = function(h, flagCanon, flagHex) {
2755 	var a = this.getX500NameArray(h);
2756 	var s = this.dnarraytostr(a);
2757 	var result = { str: s };
2758 
2759 	result.array = a;
2760 	if (flagHex == true) result.hex = h;
2761 	if (flagCanon == true) result.canon = this.c14nRDNArray(a);
2762 	return result;
2763     };
2764 
2765     // ===== END X500Name related =====================================
2766 
2767     // ===== BEGIN read certificate =====================================
2768     /**
2769      * read PEM formatted X.509 certificate from string.<br/>
2770      * @name readCertPEM
2771      * @memberOf X509#
2772      * @function
2773      * @param {String} sCertPEM string for PEM formatted X.509 certificate
2774      * @example
2775      * x = new X509();
2776      * x.readCertPEM(sCertPEM); // read certificate
2777      */
2778     this.readCertPEM = function(sCertPEM) {
2779         this.readCertHex(_pemtohex(sCertPEM));
2780     };
2781 
2782     /**
2783      * read a hexadecimal string of X.509 certificate<br/>
2784      * @name readCertHex
2785      * @memberOf X509#
2786      * @function
2787      * @param {String} sCertHex hexadecimal string of X.509 certificate
2788      * @since jsrsasign 7.1.4 x509 1.1.13
2789      * @description
2790      * NOTE: {@link X509#parseExt} will called internally since jsrsasign 7.2.0.
2791      * @example
2792      * x = new X509();
2793      * x.readCertHex("3082..."); // read certificate
2794      */
2795     this.readCertHex = function(sCertHex) {
2796         this.hex = sCertHex;
2797 	this.getVersion(); // set version parameter
2798 
2799 	try {
2800 	    _getIdxbyList(this.hex, 0, [0, 7], "a3"); // has [3] v3ext
2801 	    this.parseExt();
2802 	} catch(ex) {};
2803     };
2804 
2805     // ===== END read certificate =====================================
2806 
2807     /**
2808      * get JSON object of certificate parameters<br/>
2809      * @name getParam
2810      * @memberOf X509#
2811      * @function
2812      * @param {Object} option optional setting for return object
2813      * @return {Object} JSON object of certificate parameters
2814      * @since jsrsasign 9.0.0 x509 2.0.0
2815      * @see KJUR.asn1.x509.X509Util.newCertPEM
2816      *
2817      * @description
2818      * This method returns a JSON object of the certificate
2819      * parameters. Return value can be passed to
2820      * {@link KJUR.asn1.x509.X509Util.newCertPEM}.
2821      * <br/>
2822      * NOTE1: From jsrsasign 10.5.16, optional argument can be applied.
2823      * It can have following members:
2824      * <ul>
2825      * <li>tbshex - (boolean) tbshex member with hex value of 
2826      * tbsCertificate will be added if true (DEFAULT undefined)</li>
2827      * <li>nodnarray - (boolean) array member for subject and
2828      * issuer will be deleted to simplify it if true (DEFAULT undefined)<li>
2829      * <li>dncanon - (boolean) add canon member to subject and issuer for DN StringPrep if true(DEFAULT undefined)</li>
2830      * <li>dnhex - (boolean) add hex member to subject and issuer if true(DEFAULT undefined)</li>
2831      * </ul>
2832      * <br/>
2833      * NOTE2: From jsrsasign 10.6.0, member "dncanon" and "dnhex" supported
2834      * in the "option" argument.
2835      *
2836      * @example
2837      * x = new X509();
2838      * x.readCertPEM("-----BEGIN CERTIFICATE...");
2839      * x.getParam() →
2840      * {version:3,
2841      *  serial:{hex:"12ab"},
2842      *  sigalg:"SHA256withRSA",
2843      *  issuer: {array:[[{type:'CN',value:'CA1',ds:'prn'}]],str:"/O=CA1"},
2844      *  notbefore:"160403023700Z",
2845      *  notafter:"160702023700Z",
2846      *  subject: {array:[[{type:'CN',value:'Test1',ds:'prn'}]],str:"/CN=Test1"},
2847      *  sbjpubkey:"-----BEGIN PUBLIC KEY...",
2848      *  ext:[
2849      *   {extname:"keyUsage",critical:true,names:["digitalSignature"]},
2850      *   {extname:"basicConstraints",critical:true},
2851      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
2852      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
2853      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
2854      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}
2855      *  ],
2856      *  sighex:"0b76...8"
2857      * };
2858      *
2859      * x.getParam({tbshex: true}) → { ... , tbshex: "30..." }
2860      * x.getParam({nodnarray: true}) → {issuer: {str: "/C=JP"}, ...}
2861      * x.getParam({dncanon: true}) → {... {issuer: {canon: "/c=jp/o=..."} ...} ...}
2862      * x.getParam({dnhex: true}) → {... {issuer: {hex: "30..."} ...} ...}
2863      */
2864     this.getParam = function(option) {
2865 	var result = {};
2866 	if (option == undefined) option = {};
2867 
2868 	result.version = this.getVersion();
2869 	result.serial = {hex: this.getSerialNumberHex()};
2870 	result.sigalg = this.getSignatureAlgorithmField();
2871 	result.issuer = this.getIssuer(option.dncanon, option.dnhex);
2872 	result.notbefore = this.getNotBefore();
2873 	result.notafter = this.getNotAfter();
2874 	result.subject = this.getSubject(option.dncanon, option.dnhex);
2875 	result.sbjpubkey = hextopem(this.getPublicKeyHex(), "PUBLIC KEY");
2876 	if (this.aExtInfo != undefined &&
2877 	    this.aExtInfo.length > 0) {
2878 	    result.ext = this.getExtParamArray();
2879 	}
2880 	result.sighex = this.getSignatureValueHex();
2881 
2882 	// for options
2883 	if (option.tbshex == true) {
2884 	    result.tbshex = _getTLVbyList(this.hex, 0, [0]);
2885 	}
2886 	if (option.nodnarray == true) {
2887 	    delete result.issuer.array;
2888 	    delete result.subject.array;
2889 	}
2890 
2891 	return result;
2892     };
2893 
2894     /** 
2895      * get array of certificate extension parameter JSON object<br/>
2896      * @name getExtParamArray
2897      * @memberOf X509#
2898      * @function
2899      * @param {String} hExtSeq hexadecimal string of SEQUENCE of Extension
2900      * @return {Array} array of certificate extension parameter JSON object
2901      * @since jsrsasign 9.0.0 x509 2.0.0
2902      * @see KJUR.asn1.x509.X509Util.newCertPEM
2903      * @see X509#getParam
2904      * @see X509#getExtParam
2905      * @see X509CRL#getParam
2906      * @see KJUR.asn1.csr.CSRUtil.getParam
2907      *
2908      * @description
2909      * This method returns an array of certificate extension
2910      * parameters. 
2911      * <br/>
2912      * NOTE: Argument "hExtSeq" have been supported since jsrsasign 9.1.1.
2913      *
2914      * @example
2915      * x = new X509();
2916      * x.readCertPEM("-----BEGIN CERTIFICATE...");
2917      * x.getExtParamArray() →
2918      * [ {extname:"keyUsage",critical:true,names:["digitalSignature"]},
2919      *   {extname:"basicConstraints",critical:true},
2920      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
2921      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
2922      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
2923      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}]
2924      */
2925     this.getExtParamArray = function(hExtSeq) {
2926 	if (hExtSeq == undefined) {
2927 	    // for X.509v3 certificate
2928 	    var idx1 = _getIdxbyListEx(this.hex, 0, [0, "[3]"]);
2929 	    if (idx1 != -1) {
2930 		hExtSeq = _getTLVbyListEx(this.hex, 0, [0, "[3]", 0], "30");
2931 	    }
2932 	}
2933 	var result = [];
2934 	var aIdx = _getChildIdx(hExtSeq, 0);
2935 
2936 	for (var i = 0; i < aIdx.length; i++) {
2937 	    var hExt = _getTLV(hExtSeq, aIdx[i]);
2938 	    var extParam = this.getExtParam(hExt);
2939 	    if (extParam != null) result.push(extParam);
2940 	}
2941 
2942 	return result;
2943     };
2944 
2945     /** 
2946      * get a extension parameter JSON object<br/>
2947      * @name getExtParam
2948      * @memberOf X509#
2949      * @function
2950      * @param {String} hExt hexadecimal string of Extension
2951      * @return {Array} Extension parameter JSON object
2952      * @since jsrsasign 9.1.1 x509 2.0.1
2953      * @see KJUR.asn1.x509.X509Util.newCertPEM
2954      * @see X509#getParam
2955      * @see X509#getExtParamArray
2956      * @see X509CRL#getParam
2957      * @see KJUR.asn1.csr.CSRUtil.getParam
2958      *
2959      * @description
2960      * This method returns a extension parameters as JSON object. 
2961      *
2962      * @example
2963      * x = new X509();
2964      * ...
2965      * x.getExtParam("30...") →
2966      * {extname:"keyUsage",critical:true,names:["digitalSignature"]}
2967      */
2968     this.getExtParam = function(hExt) {
2969 	var result = {};
2970 	var aIdx = _getChildIdx(hExt, 0);
2971 	var aIdxLen = aIdx.length;
2972 	if (aIdxLen != 2 && aIdxLen != 3)
2973 	    throw new Error("wrong number elements in Extension: " + 
2974 			    aIdxLen + " " + hExt);
2975 
2976 	var oid = _hextooidstr(_getVbyList(hExt, 0, [0], "06"));
2977 
2978 	var critical = false;
2979 	if (aIdxLen == 3 && _getTLVbyList(hExt, 0, [1]) == "0101ff")
2980 	    critical = true;
2981 
2982 	var hExtV = _getTLVbyList(hExt, 0, [aIdxLen - 1, 0]);
2983 
2984 	var extParam = undefined;
2985 	if (oid == "2.5.29.14") {
2986 	    extParam = this.getExtSubjectKeyIdentifier(hExtV, critical);
2987 	} else if (oid == "2.5.29.15") {
2988 	    extParam = this.getExtKeyUsage(hExtV, critical);
2989 	} else if (oid == "2.5.29.17") {
2990 	    extParam = this.getExtSubjectAltName(hExtV, critical);
2991 	} else if (oid == "2.5.29.18") {
2992 	    extParam = this.getExtIssuerAltName(hExtV, critical);
2993 	} else if (oid == "2.5.29.19") {
2994 	    extParam = this.getExtBasicConstraints(hExtV, critical);
2995 	} else if (oid == "2.5.29.30") {
2996 	    extParam = this.getExtNameConstraints(hExtV, critical);
2997 	} else if (oid == "2.5.29.31") {
2998 	    extParam = this.getExtCRLDistributionPoints(hExtV, critical);
2999 	} else if (oid == "2.5.29.32") {
3000 	    extParam = this.getExtCertificatePolicies(hExtV, critical);
3001 	} else if (oid == "2.5.29.33") {
3002 	    extParam = this.getExtPolicyMappings(hExtV, critical);
3003 	} else if (oid == "2.5.29.35") {
3004 	    extParam = this.getExtAuthorityKeyIdentifier(hExtV, critical);
3005 	} else if (oid == "2.5.29.36") {
3006 	    extParam = this.getExtPolicyConstraints(hExtV, critical);
3007 	} else if (oid == "2.5.29.37") {
3008 	    extParam = this.getExtExtKeyUsage(hExtV, critical);
3009 	} else if (oid == "2.5.29.54") {
3010 	    extParam = this.getExtInhibitAnyPolicy(hExtV, critical);
3011 	} else if (oid == "1.3.6.1.5.5.7.1.1") {
3012 	    extParam = this.getExtAuthorityInfoAccess(hExtV, critical);
3013 	} else if (oid == "2.5.29.20") {
3014 	    extParam = this.getExtCRLNumber(hExtV, critical);
3015 	} else if (oid == "2.5.29.21") {
3016 	    extParam = this.getExtCRLReason(hExtV, critical);
3017 	} else if (oid == "1.3.6.1.5.5.7.48.1.2") {
3018 	    extParam = this.getExtOcspNonce(hExtV, critical);
3019 	} else if (oid == "1.3.6.1.5.5.7.48.1.5") {
3020 	    extParam = this.getExtOcspNoCheck(hExtV, critical);
3021 	} else if (oid == "1.2.840.113583.1.1.9.1") {
3022 	    extParam = this.getExtAdobeTimeStamp(hExtV, critical);
3023 	}
3024 	if (extParam != undefined) return extParam;
3025 
3026 	var privateParam = { extname: oid, extn: hExtV };
3027 	if (critical) privateParam.critical = true;
3028 	return privateParam;
3029     };
3030 
3031     /**
3032      * find extension parameter in array<br/>
3033      * @name findExt
3034      * @memberOf X509#
3035      * @function
3036      * @param {Array} aExt array of extension parameters
3037      * @param {String} extname extension name
3038      * @return {Array} extension parameter in the array or null
3039      * @since jsrsasign 10.0.3 x509 2.0.7
3040      * @see X509#getParam
3041      *
3042      * @description
3043      * This method returns an extension parameter for
3044      * specified extension name in the array.
3045      * This method is useful to update extension parameter value.
3046      * When there is no such extension with the extname,
3047      * this returns "null".
3048      *
3049      * @example
3050      * // (1) 
3051      * x = new X509(CERTPEM);
3052      * params = x.getParam();
3053      * pSKID = x.findExt(params.ext, "subjectKeyIdentifier");
3054      * pSKID.kid = "1234abced..."; // skid in the params is updated.
3055      *   // then params was updated
3056      *
3057      * // (2) another example
3058      * aExt = [
3059      *   {extname:"keyUsage",critical:true,names:["digitalSignature"]},
3060      *   {extname:"basicConstraints",critical:true},
3061      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
3062      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3063      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
3064      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}
3065      * ];
3066      * var x = new X509();
3067      * x.findExt(aExt, "authorityKeyInfoAccess").array[0].ocsp = "http://aaa.com";
3068      * pKU = x.findExt(aExt, "keyUsage");
3069      * delete pKU["critical"]; // clear criticla flag
3070      * pKU.names = ["keyCertSign", "cRLSign"];
3071      *   // then aExt was updated
3072      */
3073     this.findExt = function(aExt, extname) {
3074 	for (var i = 0; i < aExt.length; i++) {
3075 	    if (aExt[i].extname == extname) return aExt[i];
3076 	}
3077 	return null;
3078 
3079     };
3080 
3081     /**
3082      * update CRLDistributionPoints Full URI in parameter<br/>
3083      * @name updateCDPFullURI
3084      * @memberOf X509#
3085      * @function
3086      * @param {Array} aExt array of extension parameters
3087      * @param {String} newURI string of new uri
3088      * @since jsrsasign 10.0.4 x509 2.0.8
3089      * @see X509#findExt
3090      * @see KJUR.asn1.x509.CRLDistributionPoints
3091      *
3092      * @description
3093      * This method updates Full URI of CRLDistributionPoints extension
3094      * in the extension parameter array if it exists.
3095      *
3096      * @example
3097      * aExt = [
3098      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3099      *   {extname:"cRLDistributionPoints",
3100      *    array:[{dpname:{full:[{uri:"http://example.com/a.crl"}]}}]},
3101      * ];
3102      * x = new X509();
3103      * x.updateCDPFullURI(aExt, "http://crl2.example.new/b.crl");
3104      */
3105     this.updateExtCDPFullURI = function(aExt, newURI) {
3106 	var pExt = this.findExt(aExt, "cRLDistributionPoints");
3107 	if (pExt == null) return;
3108 	if (pExt.array == undefined) return;
3109 	var aDP = pExt.array;
3110 	for (var i = 0; i < aDP.length; i++) {
3111 	    if (aDP[i].dpname == undefined) continue;
3112 	    if (aDP[i].dpname.full == undefined) continue;
3113 	    var aURI = aDP[i].dpname.full;
3114 	    for (var j = 0; j < aURI.length; j++) {
3115 		var pURI = aURI[i];
3116 		if (pURI.uri == undefined) continue;
3117 		pURI.uri = newURI;
3118 	    }
3119 	}
3120     };
3121 
3122     /**
3123      * update authorityInfoAccess ocsp in parameter<br/>
3124      * @name updateAIAOCSP
3125      * @memberOf X509#
3126      * @function
3127      * @param {Array} aExt array of extension parameters
3128      * @param {String} newURI string of new uri
3129      * @since jsrsasign 10.0.4 x509 2.0.8
3130      * @see X509#findExt
3131      * @see KJUR.asn1.x509.AuthorityInfoAccess
3132      *
3133      * @description
3134      * This method updates "ocsp" accessMethod URI of 
3135      * AuthorityInfoAccess extension
3136      * in the extension parameter array if it exists.
3137      *
3138      * @example
3139      * aExt = [
3140      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3141      *   {extname:"authoriyInfoAccess",
3142      *    array:[
3143      *      {ocsp: "http://ocsp1.example.com"},
3144      *      {caissuer: "http://example.com/a.crt"}
3145      *    ]}
3146      * ];
3147      * x = new X509();
3148      * x.updateAIAOCSP(aExt, "http://ocsp2.example.net");
3149      */
3150     this.updateExtAIAOCSP = function(aExt, newURI) {
3151 	var pExt = this.findExt(aExt, "authorityInfoAccess");
3152 	if (pExt == null) return;
3153 	if (pExt.array == undefined) return;
3154 	var a = pExt.array;
3155 	for (var i = 0; i < a.length; i++) {
3156 	    if (a[i].ocsp != undefined) a[i].ocsp = newURI;
3157 	}
3158     };
3159 
3160     /**
3161      * update authorityInfoAccess caIssuer in parameter<br/>
3162      * @name updateAIACAIssuer
3163      * @memberOf X509#
3164      * @function
3165      * @param {Array} aExt array of extension parameters
3166      * @param {String} newURI string of new uri
3167      * @since jsrsasign 10.0.4 x509 2.0.8
3168      * @see X509#findExt
3169      * @see KJUR.asn1.x509.AuthorityInfoAccess
3170      *
3171      * @description
3172      * This method updates "caIssuer" accessMethod URI of 
3173      * AuthorityInfoAccess extension
3174      * in the extension parameter array if it exists.
3175      *
3176      * @example
3177      * aExt = [
3178      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3179      *   {extname:"authoriyInfoAccess",
3180      *    array:[
3181      *      {ocsp: "http://ocsp1.example.com"},
3182      *      {caissuer: "http://example.com/a.crt"}
3183      *    ]}
3184      * ];
3185      * x = new X509();
3186      * x.updateAIACAIssuer(aExt, "http://example.net/b.crt");
3187      */
3188     this.updateExtAIACAIssuer = function(aExt, newURI) {
3189 	var pExt = this.findExt(aExt, "authorityInfoAccess");
3190 	if (pExt == null) return;
3191 	if (pExt.array == undefined) return;
3192 	var a = pExt.array;
3193 	for (var i = 0; i < a.length; i++) {
3194 	    if (a[i].caissuer != undefined) a[i].caissuer = newURI;
3195 	}
3196     };
3197 
3198     /**
3199      * convert array for X500 distinguish name to distinguish name string<br/>
3200      * @name dnarraytostr
3201      * @memberOf X509#
3202      * @function
3203      * @param {Array} aDN array for X500 distinguish name
3204      * @return {String} distinguish name
3205      * @since jsrsasign 10.0.6 x509 2.0.8
3206      * @see X509#getX500Name
3207      * @see X509#getX500NameArray
3208      * @see KJUR.asn1.x509.X500Name
3209      *
3210      * @description
3211      * This method converts from an array representation of 
3212      * X.500 distinguished name to X.500 name string.
3213      * This supports multi-valued RDN.
3214      * 
3215      * @example
3216      * var x = new X509();
3217      * x.dnarraytostr(
3218      *   [[{type:"C",value:"JP",ds:"prn"}],
3219      *   [{type:"O",value:"T1",ds:"prn"}]]) → "/C=JP/O=T1"
3220      * x.dnarraytostr(
3221      *   [[{type:"C",value:"JP",ds:"prn"}],
3222      *   [{type:"O",value:"T1",ds:"prn"}
3223      *    {type:"CN",value:"Bob",ds:"prn"}]]) → "/C=JP/O=T1+CN=Bob"
3224      */
3225     this.dnarraytostr = function(aDN) {
3226 	function rdnarraytostr(aRDN) {
3227 	    return aRDN.map(function(x){return atvtostr(x).replace(/\+/,"\\+");}).join("+");
3228 	};
3229 
3230 	function atvtostr(pATV) {
3231 	    return pATV.type + "=" + pATV.value;
3232 	};
3233 
3234 	return "/" + aDN.map(function(x){return rdnarraytostr(x).replace(/\//, "\\/");}).join("/");
3235     };
3236 
3237     /**
3238      * set canonicalized DN to a DN parameter<br/>
3239      * @name setCanonicalizedDN
3240      * @memberOf X509#
3241      * @function
3242      * @param {object} pDN DN parameter associative array
3243      * @since jsrsasign 10.6.0 x509 2.1.0
3244      * 
3245      * @description
3246      * This method canonicalizes a DN string as following:
3247      * <ul>
3248      * <li>convert to lower case</li>
3249      * <li>convert from all multiple spaces to a space</li>
3250      * </ul>
3251      * 
3252      * @example
3253      * var x = new X509();
3254      * var pDN = {
3255      *   array: [
3256      *     [{type:'C',value:'JP',ds:'prn'}],
3257      *     [{type:'O',value:'Test    1',ds:'prn'}] ],
3258      *   str: "/C=JP/O=Test    1" };
3259      * x.setCanonicalizedDN(pDN);
3260 
3261      * // pDN will become following
3262      * pDN = {
3263      *   array: [
3264      *     [{type:'C',value:'JP',ds:'prn'}],
3265      *     [{type:'O',value:'Test    1',ds:'prn'}] ],
3266      *   str: "/C=JP/O=Test    1",
3267      *   canon: "/c=jp/o=test 1" };
3268      */
3269     this.setCanonicalizedDN = function(pDN) {
3270 	var aRDN;
3271 	if (pDN.str != undefined && pDN.array == undefined) {
3272 	    var dDN = new KJUR.asn1.x509.X500Name({str: pDN.str});
3273 	    var hDN = dDN.tohex();
3274 	    aRDN = this.getX500NameArray(hDN);
3275 	} else {
3276 	    aRDN = pDN.array;
3277 	}
3278 	if (pDN.canon == undefined) {
3279 	    pDN.canon = this.c14nRDNArray(aRDN);
3280 	}
3281     };
3282 
3283     /**
3284      * simple canonicalization(c14n) for RDN array<br/>
3285      * @name c14nRDNArray
3286      * @memberOf X509#
3287      * @function
3288      * @param {array} aRDN array of RDN parameters
3289      * @return {string} canonicalized distinguish name (ex. "/c=jp/o=test ca")
3290      * @since jsrsasign 10.6.0 x509 2.1.0
3291      * 
3292      * @description
3293      * This method canonicalizes a DN string according to
3294      * <a href="https://datatracker.ietf.org/doc/html/rfc4518#appendix-B">
3295      * "RFC 4518 StringPrep Appendix B Substring Matching"</a> as following:
3296      * <ul>
3297      * <li>convert to lower case</li>
3298      * <li>convert from all sequence of spaces to a space</li>
3299      * <li>remove leading and trailing spaces</li>
3300      * </ul>
3301      * 
3302      * @example
3303      * var x = new X509();
3304      * x.c14nRDNArray([
3305      *   [{type:"C", value:"JP", ds: "prn"}],
3306      *   [{type:"O", value:"    Test    1234     ", ds: "utf8"}],
3307      *   [{type:"OU", value:"HR   45", ds: "utf8"}]
3308      * ]) → "/c=jp/o=test 1234/ou=hr 45"
3309      */
3310     this.c14nRDNArray = function(aRDN) {
3311 	var a = [];
3312 	for (var i = 0; i < aRDN.length; i++) {
3313 	    var aAVA = aRDN[i];
3314 	    var a2 = [];
3315 	    for (var j = 0; j < aAVA.length; j++) {
3316 		var pAVA = aAVA[j];
3317 		var value = pAVA.value;
3318 		value = value.replace(/^\s*/, '');
3319 		value = value.replace(/\s*$/, '');
3320 		value = value.replace(/\s+/g, ' ');
3321 		value = value.toLowerCase();
3322 		a2.push(pAVA.type.toLowerCase() + "=" + value);
3323 	    }
3324 	    a.push(a2.join("+"));
3325 	}
3326 	return "/" + a.join("/");
3327     };
3328 
3329     /**
3330      * get certificate information as string.<br/>
3331      * @name getInfo
3332      * @memberOf X509#
3333      * @function
3334      * @return {String} certificate information string
3335      * @since jsrsasign 5.0.10 x509 1.1.8
3336      * @example
3337      * x = new X509();
3338      * x.readCertPEM(certPEM);
3339      * console.log(x.getInfo());
3340      * // this shows as following
3341      * Basic Fields
3342      *   serial number: 02ac5c266a0b409b8f0b79f2ae462577
3343      *   signature algorithm: SHA1withRSA
3344      *   issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
3345      *   notBefore: 061110000000Z
3346      *   notAfter: 311110000000Z
3347      *   subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
3348      *   subject public key info:
3349      *     key algorithm: RSA
3350      *     n=c6cce573e6fbd4bb...
3351      *     e=10001
3352      * X509v3 Extensions:
3353      *   keyUsage CRITICAL:
3354      *     digitalSignature,keyCertSign,cRLSign
3355      *   basicConstraints CRITICAL:
3356      *     cA=true
3357      *   subjectKeyIdentifier :
3358      *     b13ec36903f8bf4701d498261a0802ef63642bc3
3359      *   authorityKeyIdentifier :
3360      *     kid=b13ec36903f8bf4701d498261a0802ef63642bc3
3361      * signature algorithm: SHA1withRSA
3362      * signature: 1c1a0697dcd79c9f...
3363      */
3364     this.getInfo = function() {
3365 	var _getSubjectAltNameStr = function(params) {
3366 	    var s = "";
3367 	    var indent = "    ";
3368 	    var NL = "\n";
3369 	    var a = params.array;
3370 	    for (var i = 0; i < a.length; i++) {
3371 		var pGN = a[i];
3372 		if (pGN.dn != undefined)	s += indent + "dn: " + pGN.dn.str + NL;
3373 		if (pGN.ip != undefined)	s += indent + "ip: " + pGN.ip + NL;
3374 		if (pGN.rfc822 != undefined)	s += indent + "rfc822: " + pGN.rfc822 + NL;
3375 		if (pGN.dns != undefined)	s += indent + "dns: " + pGN.dns + NL;
3376 		if (pGN.uri != undefined)	s += indent + "uri: " + pGN.uri + NL;
3377 		if (pGN.other != undefined) {
3378 		    var oidname = pGN.other.oid;
3379 		    var value = JSON.stringify(pGN.other.value).replace(/\"/g, '');
3380 		    s += indent + "other: " + oidname + "=" + value + NL;
3381 		}
3382 	    }
3383 	    s = s.replace(/\n$/, '');
3384 	    return s;
3385 	};
3386 	var _getCertificatePoliciesStr = function(params) {
3387 	    var s = "";
3388 	    var a = params.array;
3389 	    for (var i = 0; i < a.length; i++) {
3390 		var pi = a[i];
3391 		s += "    policy oid: " + pi.policyoid + "\n";
3392 		if (pi.array === undefined) continue;
3393 		for (var j = 0; j < pi.array.length; j++) {
3394 		    var pqi = pi.array[j];
3395 		    if (pqi.cps !== undefined) {
3396 			s += "    cps: " + pqi.cps + "\n";
3397 		    }
3398 		}
3399 	    }
3400 	    return s;
3401 	};
3402 	var _getCRLDistributionPointsStr = function(params) {
3403 	    var s = "";
3404 	    var a = params.array;
3405 	    for (var i = 0; i < a.length; i++) {
3406 		var dp = a[i];
3407 		try {
3408 		    if (dp.dpname.full[0].uri !== undefined)
3409 			s += "    " + dp.dpname.full[0].uri + "\n";
3410 		} catch(ex) {};
3411 		try {
3412 		    if (dp.dname.full[0].dn.hex !== undefined)
3413 			s += "    " + X509.hex2dn(dp.dpname.full[0].dn.hex) + "\n";
3414 		} catch(ex) {};
3415 	    }
3416 	    return s;
3417 	}
3418 	var _getAuthorityInfoAccessStr = function(params) {
3419 	    var s = "";
3420 	    var a = params.array;
3421 	    for (var i = 0; i < a.length; i++) {
3422 		var ad = a[i];
3423 
3424 		if (ad.caissuer !== undefined)
3425 		    s += "    caissuer: " + ad.caissuer + "\n";
3426 		if (ad.ocsp !== undefined)
3427 		    s += "    ocsp: " + ad.ocsp + "\n";
3428 	    }
3429 	    return s;
3430 	};
3431 	var _X509 = X509;
3432 	var s, pubkey, aExt;
3433 	s  = "Basic Fields\n";
3434         s += "  serial number: " + this.getSerialNumberHex() + "\n";
3435 	s += "  signature algorithm: " + this.getSignatureAlgorithmField() + "\n";
3436 	s += "  issuer: " + this.getIssuerString() + "\n";
3437 	s += "  notBefore: " + this.getNotBefore() + "\n";
3438 	s += "  notAfter: " + this.getNotAfter() + "\n";
3439 	s += "  subject: " + this.getSubjectString() + "\n";
3440 	s += "  subject public key info: " + "\n";
3441 
3442 	// subject public key info
3443 	pubkey = this.getPublicKey();
3444 	s += "    key algorithm: " + pubkey.type + "\n";
3445 
3446 	if (pubkey.type === "RSA") {
3447 	    s += "    n=" + hextoposhex(pubkey.n.toString(16)).substr(0, 16) + "...\n";
3448 	    s += "    e=" + hextoposhex(pubkey.e.toString(16)) + "\n";
3449 	}
3450 
3451 	// X.509v3 Extensions
3452         aExt = this.aExtInfo;
3453 
3454 	if (aExt !== undefined && aExt !== null) {
3455             s += "X509v3 Extensions:\n";
3456 	    
3457             for (var i = 0; i < aExt.length; i++) {
3458 		var info = aExt[i];
3459 
3460 		// show extension name and critical flag
3461 		var extName = KJUR.asn1.x509.OID.oid2name(info["oid"]);
3462 		if (extName === '') extName = info["oid"];
3463 
3464 		var critical = '';
3465 		if (info["critical"] === true) critical = "CRITICAL";
3466 
3467 		s += "  " + extName + " " + critical + ":\n";
3468 
3469 		// show extension value if supported
3470 		if (extName === "basicConstraints") {
3471 		    var bc = this.getExtBasicConstraints();
3472 		    if (bc.cA === undefined) {
3473 			s += "    {}\n";
3474 		    } else {
3475 			s += "    cA=true";
3476 			if (bc.pathLen !== undefined)
3477 			    s += ", pathLen=" + bc.pathLen;
3478 			s += "\n";
3479 		    }
3480 		} else if (extName == "policyMappings") {
3481 		    var a = this.getExtPolicyMappings().array;
3482 		    var sMap = a.map(function(item){
3483 			var aPolicy = item;
3484 			return aPolicy[0] + ":" + aPolicy[1];
3485 		    }).join(", ");
3486 		    s += "    " + sMap + "\n";
3487 		} else if (extName == "policyConstraints") {
3488 		    var p = this.getExtPolicyConstraints();
3489 		    s += "    ";
3490 		    if (p.reqexp != undefined) s += " reqexp=" + p.reqexp;
3491 		    if (p.inhibit != undefined) s += " inhibit=" + p.inhibit;
3492 		    s += "\n";
3493 		} else if (extName == "inhibitAnyPolicy") {
3494 		    var p = this.getExtInhibitAnyPolicy();
3495 		    s += "    skip=" + p.skip + "\n";
3496 		} else if (extName == "keyUsage") {
3497 		    s += "    " + this.getExtKeyUsageString() + "\n";
3498 		} else if (extName == "subjectKeyIdentifier") {
3499 		    s += "    " + this.getExtSubjectKeyIdentifier().kid.hex + "\n";
3500 		} else if (extName == "authorityKeyIdentifier") {
3501 		    var akid = this.getExtAuthorityKeyIdentifier();
3502 		    if (akid.kid !== undefined)
3503 			s += "    kid=" + akid.kid.hex + "\n";
3504 		} else if (extName == "extKeyUsage") {
3505 		    var eku = this.getExtExtKeyUsage().array;
3506 		    s += "    " + eku.join(", ") + "\n";
3507 		} else if (extName == "subjectAltName") {
3508 		    var san = _getSubjectAltNameStr(this.getExtSubjectAltName());
3509 		    s += san + "\n";
3510 		} else if (extName == "cRLDistributionPoints") {
3511 		    var cdp = this.getExtCRLDistributionPoints();
3512 		    s += _getCRLDistributionPointsStr(cdp);
3513 		} else if (extName == "authorityInfoAccess") {
3514 		    var aia = this.getExtAuthorityInfoAccess();
3515 		    s += _getAuthorityInfoAccessStr(aia);
3516 		} else if (extName == "certificatePolicies") {
3517 		    s += _getCertificatePoliciesStr(this.getExtCertificatePolicies());
3518 		}
3519 	    }
3520         }
3521 
3522 	s += "signature algorithm: " + this.getSignatureAlgorithmName() + "\n";
3523 	s += "signature: " + this.getSignatureValueHex().substr(0, 16) + "...\n";
3524 	return s;
3525     };
3526 
3527     if (typeof params == "string") {
3528 	if (params.indexOf("-----BEGIN") != -1) {
3529 	    this.readCertPEM(params);
3530 	} else if (KJUR.lang.String.isHex(params)) {
3531 	    this.readCertHex(params);
3532 	}
3533     }
3534 };
3535 // ----- END of X509 class -----
3536 
3537 /**
3538  * get distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER X.500 name<br/>
3539  * @name hex2dn
3540  * @memberOf X509
3541  * @function
3542  * @param {String} hex hexadecimal string of ASN.1 DER distinguished name
3543  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
3544  * @return {String} OpenSSL online format distinguished name
3545  * @description
3546  * This static method converts from a hexadecimal string of 
3547  * distinguished name (DN)
3548  * specified by 'hex' and 'idx' to OpenSSL oneline string representation (ex. /C=US/O=a).
3549  * @example
3550  * X509.hex2dn("3031310b3...") → /C=US/O=a/CN=b2+OU=b1
3551  */
3552 X509.hex2dn = function(hex, idx) {
3553     if (idx === undefined) idx = 0;
3554     var x = new X509();
3555     var hDN = ASN1HEX.getTLV(hex, idx);
3556     var pDN = x.getX500Name(hex);
3557     return pDN.str;
3558 };
3559 
3560 /**
3561  * get relative distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER RDN<br/>
3562  * @name hex2rdn
3563  * @memberOf X509
3564  * @function
3565  * @param {String} hex hexadecimal string of ASN.1 DER concludes relative distinguished name
3566  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
3567  * @return {String} OpenSSL online format relative distinguished name
3568  * @description
3569  * This static method converts from a hexadecimal string of 
3570  * relative distinguished name (RDN)
3571  * specified by 'hex' and 'idx' to LDAP string representation (ex. O=test+CN=test).<br/>
3572  * NOTE: Multi-valued RDN is supported since jsnrsasign 6.2.2 x509 1.1.10.
3573  * @example
3574  * X509.hex2rdn("310a3008060355040a0c0161") → O=a
3575  * X509.hex2rdn("31143008060355040a0c01613008060355040a0c0162") → O=a+O=b
3576  */
3577 X509.hex2rdn = function(hex, idx) {
3578     if (idx === undefined) idx = 0;
3579     if (hex.substr(idx, 2) !== "31") throw new Error("malformed RDN");
3580 
3581     var a = new Array();
3582 
3583     var aIdx = ASN1HEX.getChildIdx(hex, idx);
3584     for (var i = 0; i < aIdx.length; i++) {
3585 	a.push(X509.hex2attrTypeValue(hex, aIdx[i]));
3586     }
3587 
3588     a = a.map(function(s) { return s.replace("+", "\\+"); });
3589     return a.join("+");
3590 };
3591 
3592 /**
3593  * get string from hexadecimal string of ASN.1 DER AttributeTypeAndValue<br/>
3594  * @name hex2attrTypeValue
3595  * @memberOf X509
3596  * @function
3597  * @param {String} hex hexadecimal string of ASN.1 DER concludes AttributeTypeAndValue
3598  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
3599  * @return {String} string representation of AttributeTypeAndValue (ex. C=US)
3600  * @description
3601  * This static method converts from a hexadecimal string of AttributeTypeAndValue
3602  * specified by 'hex' and 'idx' to LDAP string representation (ex. C=US).
3603  * @example
3604  * X509.hex2attrTypeValue("3008060355040a0c0161") → O=a
3605  * X509.hex2attrTypeValue("300806035504060c0161") → C=a
3606  * X509.hex2attrTypeValue("...3008060355040a0c0161...", 128) → O=a
3607  */
3608 X509.hex2attrTypeValue = function(hex, idx) {
3609     var _ASN1HEX = ASN1HEX;
3610     var _getV = _ASN1HEX.getV;
3611 
3612     if (idx === undefined) idx = 0;
3613     if (hex.substr(idx, 2) !== "30") 
3614 	throw new Error("malformed attribute type and value");
3615 
3616     var aIdx = _ASN1HEX.getChildIdx(hex, idx);
3617     if (aIdx.length !== 2 || hex.substr(aIdx[0], 2) !== "06")
3618 	"malformed attribute type and value";
3619 
3620     var oidHex = _getV(hex, aIdx[0]);
3621     var oidInt = KJUR.asn1.ASN1Util.oidHexToInt(oidHex);
3622     var atype = KJUR.asn1.x509.OID.oid2atype(oidInt);
3623 
3624     var hV = _getV(hex, aIdx[1]);
3625     var rawV = hextorstr(hV);
3626 
3627     return atype + "=" + rawV;
3628 };
3629 
3630 /**
3631  * get RSA/DSA/ECDSA public key object from X.509 certificate hexadecimal string<br/>
3632  * @name getPublicKeyFromCertHex
3633  * @memberOf X509
3634  * @function
3635  * @param {String} h hexadecimal string of X.509 certificate for RSA/ECDSA/DSA public key
3636  * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
3637  * @since jsrasign 7.1.0 x509 1.1.11
3638  */
3639 X509.getPublicKeyFromCertHex = function(h) {
3640     var x = new X509();
3641     x.readCertHex(h);
3642     return x.getPublicKey();
3643 };
3644 
3645 /**
3646  * get RSA/DSA/ECDSA public key object from PEM certificate string
3647  * @name getPublicKeyFromCertPEM
3648  * @memberOf X509
3649  * @function
3650  * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
3651  * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
3652  * @since x509 1.1.1
3653  * @description
3654  * NOTE: DSA is also supported since x509 1.1.2.
3655  */
3656 X509.getPublicKeyFromCertPEM = function(sCertPEM) {
3657     var x = new X509();
3658     x.readCertPEM(sCertPEM);
3659     return x.getPublicKey();
3660 };
3661 
3662 /**
3663  * get public key information from PEM certificate
3664  * @name getPublicKeyInfoPropOfCertPEM
3665  * @memberOf X509
3666  * @function
3667  * @param {String} sCertPEM string of PEM formatted certificate
3668  * @return {Hash} hash of information for public key
3669  * @since x509 1.1.1
3670  * @description
3671  * Resulted associative array has following properties:<br/>
3672  * <ul>
3673  * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li>
3674  * <li>algparam - hexadecimal string of OID of ECC curve name or null</li>
3675  * <li>keyhex - hexadecimal string of key in the certificate</li>
3676  * </ul>
3677  * NOTE: X509v1 certificate is also supported since x509.js 1.1.9.
3678  */
3679 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
3680     var _ASN1HEX = ASN1HEX;
3681     var _getVbyList = _ASN1HEX.getVbyList;
3682 
3683     var result = {};
3684     var x, hSPKI, pubkey;
3685     result.algparam = null;
3686 
3687     x = new X509();
3688     x.readCertPEM(sCertPEM);
3689 
3690     hSPKI = x.getPublicKeyHex();
3691     result.keyhex = _getVbyList(hSPKI, 0, [1], "03").substr(2);
3692     result.algoid = _getVbyList(hSPKI, 0, [0, 0], "06");
3693 
3694     if (result.algoid === "2a8648ce3d0201") { // ecPublicKey
3695 	result.algparam = _getVbyList(hSPKI, 0, [0, 1], "06");
3696     };
3697 
3698     return result;
3699 };
3700 
3701 /* ======================================================================
3702  *   Specific V3 Extensions
3703  * ====================================================================== */
3704 
3705 X509.KEYUSAGE_NAME = [
3706     "digitalSignature",
3707     "nonRepudiation",
3708     "keyEncipherment",
3709     "dataEncipherment",
3710     "keyAgreement",
3711     "keyCertSign",
3712     "cRLSign",
3713     "encipherOnly",
3714     "decipherOnly"
3715 ];
3716