1 /* x509-2.1.6.js (c) 2012-2023 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-2023 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.8.6 x509 2.1.6 (2023-Apr-26)
 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      * @see KJUR.asn1.x509.UserNotice
2008      *
2009      * @description
2010      * This method will get 
2011      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
2012      * UserNotice</a> parameters.
2013      * <pre>
2014      * UserNotice ::= SEQUENCE {
2015      *      noticeRef        NoticeReference OPTIONAL,
2016      *      explicitText     DisplayText OPTIONAL }
2017      * NoticeReference ::= SEQUENCE {
2018      *      organization     DisplayText,
2019      *      noticeNumbers    SEQUENCE OF INTEGER }
2020      * </pre>
2021      * Result of this method can be passed to 
2022      * {@link KJUR.asn1.x509.UserNotice} constructor.
2023      * <br/>
2024      * NOTE: NoticeReference supported from jsrsasign 10.8.0.
2025      *
2026      * @example
2027      * x = new X509();
2028      * x.getUserNotice("30...") → { 
2029      *   noticeref: {
2030      *     org: {type: 'utf8', str: 'test org'},
2031      *     noticenum: [1]
2032      *   },
2033      *   exptext: {type: 'utf8', str: 'test text'}
2034      * }
2035      */
2036     this.getUserNotice = function(h) {
2037 	var pASN1 = null;
2038 	var result = {};
2039 	try { 
2040 	    pASN1 = _ASN1HEX.parse(h);
2041 	    var pUnotice = this._asn1ToUnotice(pASN1);
2042 	    return pUnotice;
2043 	} catch(ex) {
2044 	    return undefined;
2045 	}
2046     };
2047 
2048     this._asn1ToUnotice = function(p) {
2049 	try {
2050 	    var result = {};
2051 	    var a = aryval(p, "seq");
2052 	    for (var i = 0; i < a.length; i++) {
2053 		var pNoticeRef = this._asn1ToNoticeRef(a[i]);
2054 		if (pNoticeRef != undefined) result.noticeref = pNoticeRef;
2055 		var pExpText = this.asn1ToDisplayText(a[i]);
2056 		if (pExpText != undefined) result.exptext = pExpText;
2057 	    }
2058 	    if (Object.keys(result).length > 0) return result;
2059 	    return undefined;
2060 	} catch(ex) {
2061 	    return undefined;
2062 	}
2063     }
2064 
2065     this._asn1ToNoticeRef = function(p) {
2066 	try {
2067 	    var result = {};
2068 	    var a = aryval(p, "seq");
2069 	    for (var i = 0; i < a.length; i++) {
2070 		var pNoticeNum = this._asn1ToNoticeNum(a[i]);
2071 		if (pNoticeNum != undefined) result.noticenum = pNoticeNum;
2072 		var pOrg = this.asn1ToDisplayText(a[i]);
2073 		if (pOrg != undefined) result.org = pOrg;
2074 	    }
2075 	    if (Object.keys(result).length > 0) return result;
2076 	    return undefined;
2077 	} catch(ex) {
2078 	    return undefined;
2079 	}
2080     }
2081 
2082     this._asn1ToNoticeNum = function(p) {
2083 	try {
2084 	    var a = aryval(p, "seq");
2085 	    var result = [];
2086 	    for (var i = 0; i < a.length; i++) {
2087 		var item = a[i];
2088 		result.push(parseInt(aryval(item, "int.hex"), 16));
2089 	    }
2090 	    return result;
2091 	} catch(ex) {
2092 	    return undefined;
2093 	}
2094     }
2095 
2096     /**
2097      * get DisplayText ASN.1 structure parameter as JSON object
2098      * @name getDisplayText
2099      * @memberOf X509#
2100      * @function
2101      * @param {String} h hexadecimal string of DisplayText
2102      * @return {Object} JSON object of DisplayText parameters
2103      * @since jsrsasign 9.0.0 x509 2.0.0
2104      * @see X509#getExtCertificatePolicies
2105      * @see X509#getPolicyInformation
2106      * @description
2107      * This method will get 
2108      * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
2109      * DisplayText</a> parameters.
2110      * <pre>
2111      * DisplayText ::= CHOICE {
2112      *      ia5String        IA5String      (SIZE (1..200)),
2113      *      visibleString    VisibleString  (SIZE (1..200)),
2114      *      bmpString        BMPString      (SIZE (1..200)),
2115      *      utf8String       UTF8String     (SIZE (1..200)) }     
2116      * </pre>
2117      * Result of this method can be passed to 
2118      * {@link KJUR.asn1.x509.DisplayText} constructor.
2119      * @example
2120      * x = new X509();
2121      * x.getDisplayText("0c03616161") &rarr {type: 'utf8', str: 'aaa'}
2122      * x.getDisplayText("1e03616161") &rarr {type: 'bmp',  str: 'aaa'}
2123      */
2124     this.getDisplayText = function(h) {
2125 	var _DISPLAYTEXTTAG = {"0c": "utf8", "16": "ia5", "1a": "vis" , "1e": "bmp"};
2126 	var result = {};
2127 	result.type = _DISPLAYTEXTTAG[h.substr(0, 2)];
2128 	result.str = hextorstr(_getV(h, 0));
2129 	return result;
2130     };
2131 
2132     /**
2133      * convert ASN1Object parameter to DisplayText parameter
2134      * @name asn1ToDisplayText
2135      * @memberOf X509#
2136      * @function
2137      * @param {Object} pASN1 ASN1Object paramter for DisplayText
2138      * @return {Object} DisplayText paramter
2139      * @since jsrsasign 10.8.0 x509 2.1.3
2140      * @see X509#getDisplayText
2141      * @see KJUR.asn1.x509.DisplayText
2142      * @see KJUR.asn1.ASN1Util#newObject
2143      *
2144      * @description
2145      * This method converts from {@link KJUR.asn1.ASN1Util#newObject} paramter to
2146      * {@link KJUR.asn1.x509.DisplayText} paramter
2147      * for <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4">
2148      * DisplayText</a> ASN.1 structure.
2149      * <pre>
2150      * DisplayText ::= CHOICE {
2151      *      ia5String        IA5String      (SIZE (1..200)),
2152      *      visibleString    VisibleString  (SIZE (1..200)),
2153      *      bmpString        BMPString      (SIZE (1..200)),
2154      *      utf8String       UTF8String     (SIZE (1..200)) }     
2155      * </pre>
2156      * Result of this method can be passed to 
2157      * {@link KJUR.asn1.x509.DisplayText} constructor.
2158      *
2159      * @example
2160      * x = new X509();
2161      * x.asn1ToDisplayText({utf8str: {str: "aaa"}}) &rarr {type: 'utf8', str: 'aaa'}
2162      * x.asn1ToDisplayText({bmpstr: {str: "aaa"}}) &rarr {type: 'bmp',  str: 'aaa'}
2163      */
2164     this.asn1ToDisplayText = function(pASN1) {
2165 	if (pASN1.utf8str != undefined) return { type: "utf8", str: pASN1.utf8str.str };
2166 	if (pASN1.ia5str != undefined)  return { type: "ia5", str: pASN1.ia5str.str };
2167 	if (pASN1.visstr != undefined)  return { type: "vis", str: pASN1.visstr.str };
2168 	if (pASN1.bmpstr != undefined)  return { type: "bmp", str: pASN1.bmpstr.str };
2169 	if (pASN1.prnstr != undefined)  return { type: "prn", str: pASN1.prnstr.str };
2170 	return undefined;
2171     }
2172 
2173     /**
2174      * get PolicyMappings extension value as JSON object<br/>
2175      * @name getExtPolicyMappings
2176      * @memberOf X509#
2177      * @function
2178      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
2179      * @param {Boolean} critical flag (OPTIONAL)
2180      * @return {Object} JSON object of PolicyMappings parameters or undefined
2181      * @since jsrsasign 10.6.1 x509 2.1.1
2182      * @see KJUR.asn1.x509.PolicyMappings
2183      *
2184      * @description
2185      * This method will get certificate policies value
2186      * as an array of JSON object which has properties defined
2187      * in {@link KJUR.asn1.x509.PolicyMappings}.
2188      * Result of this method can be passed to 
2189      * {@link KJUR.asn1.x509.PolicyMappings} constructor.
2190      * If there is no this extension in the certificate,
2191      * it returns undefined.
2192      * <br>
2193      * When hExtV and critical specified as arguments, return value
2194      * will be generated from them.
2195      * @example
2196      * x = new X509(sCertPEM);
2197      * x.getExtPolicyMappings() → 
2198      * { extname: "policyMappings",
2199      *   critical: true,
2200      *   array: [["1.2.3", "1.4.5"],["0.1.2", "anyPolicy"]]}
2201      */
2202     this.getExtPolicyMappings = function(hExtV, critical) {
2203 	var aExtVCritical = this.getCriticalExtV("policyMappings", hExtV, critical);
2204 	hExtV = aExtVCritical[0];
2205 	critical = aExtVCritical[1];
2206 	if (hExtV == null) return undefined;
2207 	var result = {extname: "policyMappings"};
2208 	if (critical) result.critical = true;
2209 
2210 	try {
2211 	    var p = _ASN1HEX_parse(hExtV);
2212 	    //result._asn1 = p;
2213 	    var aPair = p.seq;
2214 	    var a = [];
2215 	    for (var i = 0; i < aPair.length; i++) {
2216 		var aOid = aPair[i].seq;
2217 		a.push([aOid[0].oid, aOid[1].oid]);
2218 	    }
2219 	    result.array = a;
2220 	} catch(ex) {
2221 	    throw new _Error("malformed policyMappings");
2222 	}
2223 
2224 	return result;
2225     };
2226 
2227     /**
2228      * get PolicyConstraints extension value as JSON object<br/>
2229      * @name getExtPolicyConstraints
2230      * @memberOf X509#
2231      * @function
2232      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
2233      * @param {Boolean} critical flag (OPTIONAL)
2234      * @return {Object} JSON object of PolicyConstraints parameters or undefined
2235      * @since jsrsasign 10.6.1 x509 2.1.1
2236      * @see KJUR.asn1.x509.PolicyConstraints
2237      *
2238      * @description
2239      * This method will get certificate policies value
2240      * as an array of JSON object which has properties defined
2241      * in {@link KJUR.asn1.x509.PolicyConstraints}.
2242      * Result of this method can be passed to 
2243      * {@link KJUR.asn1.x509.PolicyConstraints} constructor.
2244      * If there is no this extension in the certificate,
2245      * it returns undefined.
2246      * <br>
2247      * When hExtV and critical specified as arguments, return value
2248      * will be generated from them.
2249      * @example
2250      * x = new X509(sCertPEM);
2251      * x.getExtPolicyConstraints() → 
2252      * { extname: "policyConstraints",
2253      *   critical: true,
2254      *   reqexp: 3,
2255      *   inhibit: 3 }
2256      */
2257     this.getExtPolicyConstraints = function(hExtV, critical) {
2258 	var aExtVCritical = this.getCriticalExtV("policyConstraints", hExtV, critical);
2259 	hExtV = aExtVCritical[0];
2260 	critical = aExtVCritical[1];
2261 	if (hExtV == null) return undefined;
2262 	var result = {extname: "policyConstraints"};
2263 	if (critical) result.critical = true;
2264 
2265 	var p = _ASN1HEX_parse(hExtV);
2266 	try {
2267 	    var aItem = p.seq;
2268 	    for (var i = 0; i < aItem.length; i++) {
2269 		var pTag = aItem[i].tag;
2270 		if (pTag.explicit != false) continue;
2271 		if (pTag.tag == "80") result.reqexp = parseInt(pTag.hex, 16);
2272 		if (pTag.tag == "81") result.inhibit = parseInt(pTag.hex, 16);
2273 	    }
2274 	} catch(ex) {
2275 	    return new _Error("malformed policyConstraints value");
2276 	}
2277 	return result;
2278     };
2279 
2280     /**
2281      * get InhibitAnyPolicy extension value as JSON object<br/>
2282      * @name getExtInhibitAnyPolicy
2283      * @memberOf X509#
2284      * @function
2285      * @param {String} hExtV hexadecimal string of extension value (OPTIONAL)
2286      * @param {Boolean} critical flag (OPTIONAL)
2287      * @return {Object} JSON object of InhibitAnyPolicy parameters or undefined
2288      * @since jsrsasign 10.6.1 x509 2.1.1
2289      * @see KJUR.asn1.x509.InhibitAnyPolicy
2290      *
2291      * @description
2292      * This method will get certificate policies value
2293      * as an array of JSON object which has properties defined
2294      * in {@link KJUR.asn1.x509.InhibitAnyPolicy}.
2295      * Result of this method can be passed to 
2296      * {@link KJUR.asn1.x509.InhibitAnyPolicy} constructor.
2297      * If there is no this extension in the certificate,
2298      * it returns undefined.
2299      * <br>
2300      * When hExtV and critical specified as arguments, return value
2301      * will be generated from them.
2302      * @example
2303      * x = new X509(sCertPEM);
2304      * x.getExtInhibitAnyPolicy() → 
2305      * { extname: "policyConstraints",
2306      *   critical: true,
2307      *   skip: 3 }
2308      *
2309      * x.getExtInhibitAnyPolicy("020103", true) → same as above
2310      */
2311     this.getExtInhibitAnyPolicy = function(hExtV, critical) {
2312 	var aExtVCritical = this.getCriticalExtV("inhibitAnyPolicy", hExtV, critical);
2313 	hExtV = aExtVCritical[0];
2314 	critical = aExtVCritical[1];
2315 	if (hExtV == null) return undefined;
2316 	var result = {extname: "inhibitAnyPolicy"};
2317 	if (critical) result.critical = true;
2318 
2319 	var skip = _getInt(hExtV, 0);
2320 	if (skip == -1) return new _Error("wrong value");
2321 	result.skip = skip;
2322 	return result;
2323     };
2324 
2325     /**
2326      * parse cRLNumber CRL extension as JSON object<br/>
2327      * @name getExtCRLNumber
2328      * @memberOf X509#
2329      * @function
2330      * @param {String} hExtV hexadecimal string of extension value
2331      * @param {Boolean} critical flag
2332      * @since jsrsasign 9.1.1 x509 2.0.1
2333      * @see KJUR.asn1.x509.CRLNumber
2334      * @see X509#getExtParamArray
2335      * @description
2336      * This method parses
2337      * CRLNumber CRL extension value defined in
2338      * <a href="https://tools.ietf.org/html/rfc5280#section-5.2.3">
2339      * RFC 5280 5.2.3</a> as JSON object.
2340      * <pre>
2341      * id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
2342      * CRLNumber ::= INTEGER (0..MAX)
2343      * </pre>
2344      * <br/>
2345      * Result of this method can be passed to 
2346      * {@link KJUR.asn1.x509.CRLNumber} constructor.
2347      * @example
2348      * crl = X509CRL("-----BEGIN X509 CRL...");
2349      * ... get hExtV and critical flag ...
2350      * crl.getExtCRLNumber("02...", false) →
2351      * {extname: "cRLNumber", num: {hex: "12af"}}
2352      */
2353     this.getExtCRLNumber = function(hExtV, critical) {
2354 	var result = {extname:"cRLNumber"};
2355 	if (critical) result.critical = true;
2356 
2357 	if (hExtV.substr(0, 2) == "02") {
2358 	    result.num = {hex: _getV(hExtV, 0)};
2359 	    return result;
2360 	}
2361 	throw new _Error("hExtV parse error: " + hExtV);
2362     };
2363 
2364     /**
2365      * parse cRLReason CRL entry extension as JSON object<br/>
2366      * @name getExtCRLReason
2367      * @memberOf X509#
2368      * @function
2369      * @param {String} hExtV hexadecimal string of extension value
2370      * @param {Boolean} critical flag
2371      * @since jsrsasign 9.1.1 x509 2.0.1
2372      * @see KJUR.asn1.x509.CRLReason
2373      * @see X509#getExtParamArray
2374      * @description
2375      * This method parses
2376      * CRLReason CRL entry extension value defined in
2377      * <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1">
2378      * RFC 5280 5.3.1</a> as JSON object.
2379      * <pre>
2380      * id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
2381      * -- reasonCode ::= { CRLReason }
2382      * CRLReason ::= ENUMERATED {
2383      *      unspecified             (0),
2384      *      keyCompromise           (1),
2385      *      cACompromise            (2),
2386      *      affiliationChanged      (3),
2387      *      superseded              (4),
2388      *      cessationOfOperation    (5),
2389      *      certificateHold         (6),
2390      *      removeFromCRL           (8),
2391      *      privilegeWithdrawn      (9),
2392      *      aACompromise           (10) }
2393      * </pre>
2394      * <br/>
2395      * Result of this method can be passed to 
2396      * {@link KJUR.asn1.x509.CRLReason} constructor.
2397      * @example
2398      * crl = X509CRL("-----BEGIN X509 CRL...");
2399      * ... get hExtV and critical flag ...
2400      * crl.getExtCRLReason("02...", false) →
2401      * {extname: "cRLReason", code: 3}
2402      */
2403     this.getExtCRLReason = function(hExtV, critical) {
2404 	var result = {extname:"cRLReason"};
2405 	if (critical) result.critical = true;
2406 
2407 	if (hExtV.substr(0, 2) == "0a") {
2408 	    result.code = parseInt(_getV(hExtV, 0), 16);
2409 	    return result;
2410 	}
2411 	throw new Error("hExtV parse error: " + hExtV);
2412     };
2413 
2414     /**
2415      * parse OCSPNonce OCSP extension as JSON object<br/>
2416      * @name getExtOcspNonce
2417      * @memberOf X509#
2418      * @function
2419      * @param {String} hExtV hexadecimal string of extension value
2420      * @param {Boolean} critical flag
2421      * @return {Array} JSON object of parsed OCSPNonce extension
2422      * @since jsrsasign 9.1.6 x509 2.0.3
2423      * @see KJUR.asn1.x509.OCSPNonce
2424      * @see X509#getExtParamArray
2425      * @see X509#getExtParam
2426      * @description
2427      * This method parses
2428      * Nonce OCSP extension value defined in
2429      * <a href="https://tools.ietf.org/html/rfc6960#section-4.4.1">
2430      * RFC 6960 4.4.1</a> as JSON object.
2431      * <pre>
2432      * id-pkix-ocsp           OBJECT IDENTIFIER ::= { id-ad-ocsp }
2433      * id-pkix-ocsp-nonce     OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 }
2434      * Nonce ::= OCTET STRING
2435      * </pre>
2436      * <br/>
2437      * Result of this method can be passed to 
2438      * {@link KJUR.asn1.x509.OCSPNonce} constructor.
2439      * @example
2440      * x = new X509();
2441      * x.getExtOcspNonce(<<extn hex value >>) →
2442      * { extname: "ocspNonce", hex: "1a2b..." }
2443      */
2444     this.getExtOcspNonce = function(hExtV, critical) {
2445 	var result = {extname:"ocspNonce"};
2446 	if (critical) result.critical = true;
2447 
2448 	var hNonce = _getV(hExtV, 0);
2449 	result.hex = hNonce;
2450 
2451 	return result;
2452     };
2453 
2454     /**
2455      * parse OCSPNoCheck OCSP extension as JSON object<br/>
2456      * @name getExtOcspNoCheck
2457      * @memberOf X509#
2458      * @function
2459      * @param {String} hExtV hexadecimal string of extension value
2460      * @param {Boolean} critical flag
2461      * @return {Array} JSON object of parsed OCSPNoCheck extension
2462      * @since jsrsasign 9.1.6 x509 2.0.3
2463      * @see KJUR.asn1.x509.OCSPNoCheck
2464      * @see X509#getExtParamArray
2465      * @see X509#getExtParam
2466      * @description
2467      * This method parses
2468      * OCSPNoCheck extension value defined in
2469      * <a href="https://tools.ietf.org/html/rfc6960#section-4.2.2.2.1">
2470      * RFC 6960 4.2.2.2.1</a> as JSON object.
2471      * <pre>
2472      * id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 }
2473      * </pre>
2474      * <br/>
2475      * Result of this method can be passed to 
2476      * {@link KJUR.asn1.x509.OCSPNoCheck} constructor.
2477      * @example
2478      * x = new X509();
2479      * x.getExtOcspNoCheck(<<extn hex value >>) →
2480      * { extname: "ocspNoCheck" }
2481      */
2482     this.getExtOcspNoCheck = function(hExtV, critical) {
2483 	var result = {extname:"ocspNoCheck"};
2484 	if (critical) result.critical = true;
2485 
2486 	return result;
2487     };
2488 
2489     /**
2490      * parse AdobeTimeStamp extension as JSON object<br/>
2491      * @name getExtAdobeTimeStamp
2492      * @memberOf X509#
2493      * @function
2494      * @param {String} hExtV hexadecimal string of extension value
2495      * @param {Boolean} critical flag
2496      * @return {Array} JSON object of parsed AdobeTimeStamp extension
2497      * @since jsrsasign 10.0.1 x509 2.0.5
2498      * @see KJUR.asn1.x509.AdobeTimeStamp
2499      * @see X509#getExtParamArray
2500      * @see X509#getExtParam
2501      * @description
2502      * This method parses
2503      * X.509v3 AdobeTimeStamp private extension value defined in the
2504      * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSigDC/oids.html">
2505      * Adobe site</a> as JSON object.
2506      * This extension provides the URL location for time stamp service.
2507      * <pre>
2508      * adbe- OBJECT IDENTIFIER ::=  { adbe(1.2.840.113583) acrobat(1) security(1) x509Ext(9) 1 }
2509      *  ::= SEQUENCE {
2510      *     version INTEGER  { v1(1) }, -- extension version
2511      *     location GeneralName (In v1 GeneralName can be only uniformResourceIdentifier)
2512      *     requiresAuth        boolean (default false), OPTIONAL }
2513      * </pre>
2514      * <br/>
2515      * Result of this method can be passed to 
2516      * {@link KJUR.asn1.x509.AdobeTimeStamp} constructor.
2517      * <br/>
2518      * NOTE: This extesion doesn't seem to have official name. This may be called as "pdfTimeStamp".
2519      * @example
2520      * x.getExtAdobeTimeStamp(<<extn hex value >>) →
2521      * { extname: "adobeTimeStamp", uri: "http://tsa.example.com/" reqauth: true }
2522      */
2523     this.getExtAdobeTimeStamp = function(hExtV, critical) {
2524 	if (hExtV === undefined && critical === undefined) {
2525 	    var info = this.getExtInfo("adobeTimeStamp");
2526 	    if (info === undefined) return undefined;
2527 	    hExtV = _getTLV(this.hex, info.vidx);
2528 	    critical = info.critical;
2529 	}
2530 
2531 	var result = {extname:"adobeTimeStamp"};
2532 	if (critical) result.critical = true;
2533 
2534 	var a = _getChildIdx(hExtV, 0);
2535 	if (a.length > 1) {
2536 	    var hGN = _getTLV(hExtV, a[1])
2537 	    var gnParam = this.getGeneralName(hGN);
2538 	    if (gnParam.uri != undefined) {
2539 		result.uri = gnParam.uri;
2540 	    }
2541 	}
2542 	if (a.length > 2) {
2543 	    var hBool = _getTLV(hExtV, a[2]);
2544 	    if (hBool == "0101ff") result.reqauth = true;
2545 	    if (hBool == "010100") result.reqauth = false;
2546 	}
2547 
2548 	return result;
2549     };
2550 
2551     /**
2552      * parse SubjectDirectoryAttributes extension as JSON object<br/>
2553      * @name getExtSubjectDirectoryAttributes
2554      * @memberOf X509#
2555      * @function
2556      * @param {String} hExtV hexadecimal string of extension value
2557      * @param {Boolean} critical flag
2558      * @return {Array} JSON object of parsed SubjectDirectoryAttributes extension
2559      * @since jsrsasign 10.8.4 x509 2.1.4
2560      * @see KJUR.asn1.x509.SubjectDirectoryAttributes
2561      * @see X509#getExtParamArray
2562      * @see X509#getExtParam
2563      *
2564      * @description
2565      * This method parses
2566      * SubjectDirectoryAttributes extension value defined in the
2567      * defined in <a href="https://tools.ietf.org/html/rfc3739#section-3.3.2">
2568      * RFC 3739 Qualified Certificate Profile section 3.3.2</a> as JSON object.
2569      * <pre>
2570      * SubjectDirectoryAttributes ::= Attributes
2571      * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
2572      * Attribute ::= SEQUENCE {
2573      *   type AttributeType 
2574      *   values SET OF AttributeValue }
2575      * AttributeType ::= OBJECT IDENTIFIER
2576      * AttributeValue ::= ANY DEFINED BY AttributeType
2577      * </pre>
2578      * <br/>
2579      * Result of this method can be passed to 
2580      * {@link KJUR.asn1.x509.SubjectDirectoryAttributes} constructor.
2581      *
2582      * @example
2583      * x.getExtSubjectDirectoryAttributes(<<extn hex value >>) →
2584      * { "extname": "SubjectDirectoryAttributes",
2585      *   "array": [
2586      *     { "attr": "gender", "array": [{"prnstr": {"str": "female"}}] },
2587      *     { "attr": "1.2.3.4.5", "array": [{"prnstr": {"str": "aaa"}}, {"utf8str": {"str": "bbb"}}] }
2588      *   ] }
2589      */
2590     this.getExtSubjectDirectoryAttributes = function(hExtV, critical) {
2591 	if (hExtV === undefined && critical === undefined) {
2592 	    var info = this.getExtInfo("subjectDirectoryAttributes");
2593 	    if (info === undefined) return undefined;
2594 	    hExtV = _getTLV(this.hex, info.vidx);
2595 	    critical = info.critical;
2596 	}
2597 
2598 	var result = { extname: "subjectDirectoryAttributes" };
2599 	if (critical) result.critical = true;
2600 	try {
2601 	    var pASN1 = _ASN1HEX_parse(hExtV);
2602 	    var aValue = [];
2603 	    for (var i = 0; i < pASN1.seq.length; i++) {
2604 		var aASN1Attribute = pASN1.seq[i];
2605 		var attrType = aryval(aASN1Attribute, "seq.0.oid");
2606 		var attrValue = aryval(aASN1Attribute, "seq.1.set");
2607 		if (attrType == undefined || attrValue == undefined) throw "error";
2608 		aValue.push({ attr: attrType, array: attrValue });
2609 	    }
2610 	    result.array = aValue;
2611 	    return result;
2612 	} catch(ex) {
2613 	    throw new Error("malformed subjectDirectoryAttributes extension value");
2614 	}
2615     }
2616 
2617     // ===== BEGIN X500Name related =====================================
2618     /*
2619      * convert ASN.1 parsed object to attrTypeAndValue assoc array<br/>
2620      * @name _convATV
2621      * @param p associative array of parsed attrTypeAndValue object
2622      * @return attrTypeAndValue associative array
2623      * @since jsrsasign 10.5.12 x509 2.0.14
2624      * @example
2625      * _convATV({seq: [...]} &rarr: {type:"C",value:"JP",ds:"prn"}
2626      */
2627     var _convATV = function(p) {
2628 	var result = {};
2629 	try {
2630 	    var name = p.seq[0].oid;
2631 	    var oid = KJUR.asn1.x509.OID.name2oid(name);
2632 	    result.type = KJUR.asn1.x509.OID.oid2atype(oid);
2633 	    var item1 = p.seq[1];
2634 	    if (item1.utf8str != undefined) {
2635 		result.ds = "utf8";
2636 		result.value = item1.utf8str.str;
2637 	    } else if (item1.numstr != undefined) {
2638 		result.ds = "num";
2639 		result.value = item1.numstr.str;
2640 	    } else if (item1.telstr != undefined) {
2641 		result.ds = "tel";
2642 		result.value = item1.telstr.str;
2643 	    } else if (item1.prnstr != undefined) {
2644 		result.ds = "prn";
2645 		result.value = item1.prnstr.str;
2646 	    } else if (item1.ia5str != undefined) {
2647 		result.ds = "ia5";
2648 		result.value = item1.ia5str.str;
2649 	    } else if (item1.visstr != undefined) {
2650 		result.ds = "vis";
2651 		result.value = item1.visstr.str;
2652 	    } else if (item1.bmpstr != undefined) {
2653 		result.ds = "bmp";
2654 		result.value = item1.bmpstr.str;
2655 	    } else {
2656 		throw "error";
2657 	    }
2658 	    return result;
2659 	} catch(ex) {
2660 	    throw new Erorr("improper ASN.1 parsed AttrTypeAndValue");
2661 	}
2662     };
2663 
2664     /*
2665      * convert ASN.1 parsed object to RDN array<br/>
2666      * @name _convRDN
2667      * @param p associative array of parsed RDN object
2668      * @return RDN array
2669      * @since jsrsasign 10.5.12 x509 2.0.14
2670      * @example
2671      * _convRDN({set: [...]} &rarr: [{type:"C",value:"JP",ds:"prn"}]
2672      */
2673     var _convRDN = function(p) {
2674 	try {
2675 	    return p.set.map(function(pATV){return _convATV(pATV)});
2676 	} catch(ex) {
2677 	    throw new Error("improper ASN.1 parsed RDN: " + ex);
2678 	}
2679     };
2680 
2681     /*
2682      * convert ASN.1 parsed object to X500Name array<br/>
2683      * @name _convX500Name
2684      * @param p associative array of parsed X500Name array object
2685      * @return RDN array
2686      * @since jsrsasign 10.5.12 x509 2.0.14
2687      * @example
2688      * _convX500Name({seq: [...]} &rarr: [[{type:"C",value:"JP",ds:"prn"}]]
2689      */
2690     var _convX500Name = function(p) {
2691 	try {
2692 	    return p.seq.map(function(pRDN){return _convRDN(pRDN)});
2693 	} catch(ex) {
2694 	    throw new Error("improper ASN.1 parsed X500Name: " + ex);
2695 	}
2696     };
2697 
2698     this.getX500NameRule = function(aDN) {
2699 	var isPRNRule = true;
2700 	var isUTF8Rule = true;
2701 	var isMixedRule = false;
2702 	var logfull = "";
2703 	var logcheck = "";
2704 	var lasttag = null;
2705 
2706 	var a = [];
2707 	for (var i = 0; i < aDN.length; i++) {
2708 	    var aRDN = aDN[i];
2709 	    for (var j = 0; j < aRDN.length; j++) {
2710 		a.push(aRDN[j]);
2711 	    }
2712 	}
2713 
2714 	for (var i = 0; i < a.length; i++) {
2715 	    var item = a[i];
2716 	    var tag = item.ds;
2717 	    var value = item.value;
2718 	    var type = item.type;
2719 	    logfull += ":" + tag;
2720 	    
2721 	    if (tag != "prn" && tag != "utf8" && tag != "ia5") {
2722 		return "mixed";
2723 	    }
2724 	    if (tag == "ia5") {
2725 		if (type != "CN") {
2726 		    return "mixed";
2727 		} else {
2728 		    if (! KJUR.lang.String.isMail(value)) {
2729 			return "mixed";
2730 		    } else {
2731 			continue;
2732 		    }
2733 		}
2734 	    }
2735 	    if (type == "C") {
2736 		if (tag == "prn") {
2737 		    continue;
2738 		} else {
2739 		    return "mixed";
2740 		}
2741 	    }
2742 	    logcheck += ":" + tag;
2743 	    if (lasttag == null) {
2744 		lasttag = tag;
2745 	    } else {
2746 		if (lasttag !== tag) return "mixed";
2747 	    }
2748 	}
2749 	if (lasttag == null) {
2750 	    return "prn";
2751 	} else {
2752 	    return lasttag;
2753 	}
2754     };
2755 
2756     /**
2757      * get AttributeTypeAndValue ASN.1 structure parameter as JSON object<br/>
2758      * @name getAttrTypeAndValue
2759      * @memberOf X509#
2760      * @function
2761      * @param {String} h hexadecimal string of AttributeTypeAndValue
2762      * @return {Object} JSON object of AttributeTypeAndValue parameters
2763      * @since jsrsasign 9.0.0 x509 2.0.0
2764      * @see X509#getX500Name
2765      * @see X509#getRDN
2766      * @description
2767      * This method will get AttributeTypeAndValue parameters defined in
2768      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2769      * RFC 5280 4.1.2.4</a>.
2770      * <pre>
2771      * AttributeTypeAndValue ::= SEQUENCE {
2772      *   type     AttributeType,
2773      *   value    AttributeValue }
2774      * AttributeType ::= OBJECT IDENTIFIER
2775      * AttributeValue ::= ANY -- DEFINED BY AttributeType
2776      * </pre>
2777      * <ul>
2778      * <li>{String}type - AttributeType name or OID(ex. C,O,CN)</li>
2779      * <li>{String}value - raw string of ASN.1 value of AttributeValue</li>
2780      * <li>{String}ds - DirectoryString type of AttributeValue</li>
2781      * </ul>
2782      * "ds" has one of following value:
2783      * <ul>
2784      * <li>utf8 - (0x0c) UTF8String</li>
2785      * <li>num  - (0x12) NumericString</li>
2786      * <li>prn  - (0x13) PrintableString</li>
2787      * <li>tel  - (0x14) TeletexString</li>
2788      * <li>ia5  - (0x16) IA5String</li>
2789      * <li>vis  - (0x1a) VisibleString</li>
2790      * <li>bmp  - (0x1e) BMPString</li>
2791      * </ul>
2792      * @example
2793      * x = new X509();
2794      * x.getAttrTypeAndValue("30...") →
2795      * {type:"CN",value:"john.smith@example.com",ds:"ia5"} or
2796      * {type:"O",value:"Sample Corp.",ds:"prn"}
2797      */
2798     // unv  - (0x1c??) UniversalString ... for future
2799     this.getAttrTypeAndValue = function(h) {
2800 	var p = _ASN1HEX_parse(h);
2801 	return _convATV(p);
2802     };
2803 
2804     /**
2805      * get RelativeDistinguishedName ASN.1 structure parameter array<br/>
2806      * @name getRDN
2807      * @memberOf X509#
2808      * @function
2809      * @param {String} h hexadecimal string of RDN
2810      * @return {Array} array of AttrTypeAndValue parameters
2811      * @since jsrsasign 9.0.0 x509 2.0.0
2812      * @see X509#getX500Name
2813      * @see X509#getRDN
2814      * @see X509#getAttrTypeAndValue
2815      * @description
2816      * This method will get RelativeDistinguishedName parameters defined in
2817      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2818      * RFC 5280 4.1.2.4</a>.
2819      * <pre>
2820      * RelativeDistinguishedName ::=
2821      *   SET SIZE (1..MAX) OF AttributeTypeAndValue
2822      * </pre>
2823      * @example
2824      * x = new X509();
2825      * x.getRDN("31...") →
2826      * [{type:"C",value:"US",ds:"prn"}] or
2827      * [{type:"O",value:"Sample Corp.",ds:"prn"}] or
2828      * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]
2829      */
2830     this.getRDN = function(h) {
2831 	var p = _ASN1HEX_parse(h);
2832 	return _convRDN(p);
2833     };
2834 
2835     /**
2836      * get X.500 Name ASN.1 structure parameter array<br/>
2837      * @name getX500NameArray
2838      * @memberOf X509#
2839      * @function
2840      * @param {String} h hexadecimal string of Name
2841      * @return {Array} array of RDN parameter array
2842      * @since jsrsasign 10.0.6 x509 2.0.9
2843      * @see X509#getX500Name
2844      * @see X509#getRDN
2845      * @see X509#getAttrTypeAndValue
2846      * @description
2847      * This method will get Name parameter defined in
2848      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2849      * RFC 5280 4.1.2.4</a>.
2850      * <pre>
2851      * Name ::= CHOICE { -- only one possibility for now --
2852      *   rdnSequence  RDNSequence }
2853      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
2854      * </pre>
2855      * @example
2856      * x = new X509();
2857      * x.getX500NameArray("30...") →
2858      * [[{type:"C",value:"US",ds:"prn"}],
2859      *  [{type:"O",value:"Sample Corp.",ds:"utf8"}],
2860      *  [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]]
2861      */
2862     this.getX500NameArray = function(h) {
2863 	var p = _ASN1HEX_parse(h);
2864 	return _convX500Name(p);
2865     };
2866 
2867     /**
2868      * get Name ASN.1 structure parameter array<br/>
2869      * @name getX500Name
2870      * @memberOf X509#
2871      * @function
2872      * @param {String} h hexadecimal string of Name
2873      * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false)
2874      * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false)
2875      * @return {Array} array of RDN parameter array
2876      * @since jsrsasign 9.0.0 x509 2.0.0
2877      * @see X509#getX500NameArray
2878      * @see X509#getRDN
2879      * @see X509#getAttrTypeAndValue
2880      * @see X509#c14nRDNArray
2881      * @see KJUR.asn1.x509.X500Name
2882      * @see KJUR.asn1.x509.GeneralName
2883      * @see KJUR.asn1.x509.GeneralNames
2884      *
2885      * @description
2886      * This method will get Name parameter defined in
2887      * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4">
2888      * RFC 5280 4.1.2.4</a>.
2889      * <pre>
2890      * Name ::= CHOICE { -- only one possibility for now --
2891      *   rdnSequence  RDNSequence }
2892      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
2893      * </pre>
2894      * <br>
2895      * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 
2896      * supported to conclude a canonicalized name for caseIgnoreMatch
2897      * desribed in <a href="https://tools.ietf.org/html/rfc4518">
2898      * RFC 4518</a>.
2899      *
2900      * @example
2901      * x = new X509();
2902      * x.getX500Name("30...") →
2903      * { array: [
2904      *     [{type:"C",value:"US",ds:"prn"}],
2905      *     [{type:"O",value:"Sample Corp.",ds:"utf8"}],
2906      *     [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]
2907      *   ],
2908      *   str: "/C=US/O=Sample Corp./CN=john.smith@example.com",
2909      *   hex: "30..." }
2910      *
2911      * x.getX500Name("30...", true) →
2912      * { array: [
2913      *     [{type:"C",value:"US",ds:"prn"}],
2914      *     [{type:"O",value:"Sample    Corp.",ds:"utf8"}]
2915      *   ],
2916      *   str: "/C=US/O=Sample    Corp.",
2917      *   canon: "/c=us/o=sample corp.",
2918      *   hex: "30..." }
2919      */
2920     this.getX500Name = function(h, flagCanon, flagHex) {
2921 	var a = this.getX500NameArray(h);
2922 	var s = this.dnarraytostr(a);
2923 	var result = { str: s };
2924 
2925 	result.array = a;
2926 	if (flagHex == true) result.hex = h;
2927 	if (flagCanon == true) result.canon = this.c14nRDNArray(a);
2928 	return result;
2929     };
2930 
2931     // ===== END X500Name related =====================================
2932 
2933     // ===== BEGIN read certificate =====================================
2934     /**
2935      * read PEM formatted X.509 certificate from string.<br/>
2936      * @name readCertPEM
2937      * @memberOf X509#
2938      * @function
2939      * @param {String} sCertPEM string for PEM formatted X.509 certificate
2940      * @example
2941      * x = new X509();
2942      * x.readCertPEM(sCertPEM); // read certificate
2943      */
2944     this.readCertPEM = function(sCertPEM) {
2945         this.readCertHex(_pemtohex(sCertPEM));
2946     };
2947 
2948     /**
2949      * read a hexadecimal string of X.509 certificate<br/>
2950      * @name readCertHex
2951      * @memberOf X509#
2952      * @function
2953      * @param {String} sCertHex hexadecimal string of X.509 certificate
2954      * @since jsrsasign 7.1.4 x509 1.1.13
2955      * @description
2956      * NOTE: {@link X509#parseExt} will called internally since jsrsasign 7.2.0.
2957      * @example
2958      * x = new X509();
2959      * x.readCertHex("3082..."); // read certificate
2960      */
2961     this.readCertHex = function(sCertHex) {
2962         this.hex = sCertHex;
2963 	this.getVersion(); // set version parameter
2964 
2965 	try {
2966 	    _getIdxbyList(this.hex, 0, [0, 7], "a3"); // has [3] v3ext
2967 	    this.parseExt();
2968 	} catch(ex) {};
2969     };
2970 
2971     // ===== END read certificate =====================================
2972 
2973     /**
2974      * get JSON object of certificate parameters<br/>
2975      * @name getParam
2976      * @memberOf X509#
2977      * @function
2978      * @param {Object} option optional setting for return object
2979      * @return {Object} JSON object of certificate parameters
2980      * @since jsrsasign 9.0.0 x509 2.0.0
2981      * @see KJUR.asn1.x509.X509Util.newCertPEM
2982      *
2983      * @description
2984      * This method returns a JSON object of the certificate
2985      * parameters. Return value can be passed to
2986      * {@link KJUR.asn1.x509.X509Util.newCertPEM}.
2987      * <br/>
2988      * NOTE1: From jsrsasign 10.5.16, optional argument can be applied.
2989      * It can have following members:
2990      * <ul>
2991      * <li>tbshex - (boolean) tbshex member with hex value of 
2992      * tbsCertificate will be added if true (DEFAULT undefined)</li>
2993      * <li>nodnarray - (boolean) array member for subject and
2994      * issuer will be deleted to simplify it if true (DEFAULT undefined)<li>
2995      * <li>dncanon - (boolean) add canon member to subject and issuer for DN StringPrep if true(DEFAULT undefined)</li>
2996      * <li>dnhex - (boolean) add hex member to subject and issuer if true(DEFAULT undefined)</li>
2997      * </ul>
2998      * <br/>
2999      * NOTE2: From jsrsasign 10.6.0, member "dncanon" and "dnhex" supported
3000      * in the "option" argument.
3001      *
3002      * @example
3003      * x = new X509();
3004      * x.readCertPEM("-----BEGIN CERTIFICATE...");
3005      * x.getParam() →
3006      * {version:3,
3007      *  serial:{hex:"12ab"},
3008      *  sigalg:"SHA256withRSA",
3009      *  issuer: {array:[[{type:'CN',value:'CA1',ds:'prn'}]],str:"/O=CA1"},
3010      *  notbefore:"160403023700Z",
3011      *  notafter:"160702023700Z",
3012      *  subject: {array:[[{type:'CN',value:'Test1',ds:'prn'}]],str:"/CN=Test1"},
3013      *  sbjpubkey:"-----BEGIN PUBLIC KEY...",
3014      *  ext:[
3015      *   {extname:"keyUsage",critical:true,names:["digitalSignature"]},
3016      *   {extname:"basicConstraints",critical:true},
3017      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
3018      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3019      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
3020      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}
3021      *  ],
3022      *  sighex:"0b76...8"
3023      * };
3024      *
3025      * x.getParam({tbshex: true}) → { ... , tbshex: "30..." }
3026      * x.getParam({nodnarray: true}) → {issuer: {str: "/C=JP"}, ...}
3027      * x.getParam({dncanon: true}) → {... {issuer: {canon: "/c=jp/o=..."} ...} ...}
3028      * x.getParam({dnhex: true}) → {... {issuer: {hex: "30..."} ...} ...}
3029      */
3030     this.getParam = function(option) {
3031 	var result = {};
3032 	if (option == undefined) option = {};
3033 
3034 	result.version = this.getVersion();
3035 	result.serial = {hex: this.getSerialNumberHex()};
3036 	result.sigalg = this.getSignatureAlgorithmField();
3037 	result.issuer = this.getIssuer(option.dncanon, option.dnhex);
3038 	result.notbefore = this.getNotBefore();
3039 	result.notafter = this.getNotAfter();
3040 	result.subject = this.getSubject(option.dncanon, option.dnhex);
3041 	result.sbjpubkey = hextopem(this.getPublicKeyHex(), "PUBLIC KEY");
3042 	if (this.aExtInfo != undefined &&
3043 	    this.aExtInfo.length > 0) {
3044 	    result.ext = this.getExtParamArray();
3045 	}
3046 	result.sighex = this.getSignatureValueHex();
3047 
3048 	// for options
3049 	if (option.tbshex == true) {
3050 	    result.tbshex = _getTLVbyList(this.hex, 0, [0]);
3051 	}
3052 	if (option.nodnarray == true) {
3053 	    delete result.issuer.array;
3054 	    delete result.subject.array;
3055 	}
3056 
3057 	return result;
3058     };
3059 
3060     /** 
3061      * get array of certificate extension parameter JSON object<br/>
3062      * @name getExtParamArray
3063      * @memberOf X509#
3064      * @function
3065      * @param {String} hExtSeq hexadecimal string of SEQUENCE of Extension
3066      * @return {Array} array of certificate extension parameter JSON object
3067      * @since jsrsasign 9.0.0 x509 2.0.0
3068      * @see KJUR.asn1.x509.X509Util.newCertPEM
3069      * @see X509#getParam
3070      * @see X509#getExtParam
3071      * @see X509CRL#getParam
3072      * @see KJUR.asn1.csr.CSRUtil.getParam
3073      *
3074      * @description
3075      * This method returns an array of certificate extension
3076      * parameters. 
3077      * <br/>
3078      * NOTE: Argument "hExtSeq" have been supported since jsrsasign 9.1.1.
3079      *
3080      * @example
3081      * x = new X509();
3082      * x.readCertPEM("-----BEGIN CERTIFICATE...");
3083      * x.getExtParamArray() →
3084      * [ {extname:"keyUsage",critical:true,names:["digitalSignature"]},
3085      *   {extname:"basicConstraints",critical:true},
3086      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
3087      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3088      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
3089      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}]
3090      */
3091     this.getExtParamArray = function(hExtSeq) {
3092 	if (hExtSeq == undefined) {
3093 	    // for X.509v3 certificate
3094 	    var idx1 = _getIdxbyListEx(this.hex, 0, [0, "[3]"]);
3095 	    if (idx1 != -1) {
3096 		hExtSeq = _getTLVbyListEx(this.hex, 0, [0, "[3]", 0], "30");
3097 	    }
3098 	}
3099 	var result = [];
3100 	var aIdx = _getChildIdx(hExtSeq, 0);
3101 
3102 	for (var i = 0; i < aIdx.length; i++) {
3103 	    var hExt = _getTLV(hExtSeq, aIdx[i]);
3104 	    var extParam = this.getExtParam(hExt);
3105 	    if (extParam != null) result.push(extParam);
3106 	}
3107 
3108 	return result;
3109     };
3110 
3111     /** 
3112      * get a extension parameter JSON object<br/>
3113      * @name getExtParam
3114      * @memberOf X509#
3115      * @function
3116      * @param {String} hExt hexadecimal string of Extension
3117      * @return {Array} Extension parameter JSON object
3118      * @since jsrsasign 9.1.1 x509 2.0.1
3119      * @see KJUR.asn1.x509.X509Util.newCertPEM
3120      * @see X509#getParam
3121      * @see X509#getExtParamArray
3122      * @see X509CRL#getParam
3123      * @see KJUR.asn1.csr.CSRUtil.getParam
3124      *
3125      * @description
3126      * This method returns a extension parameters as JSON object. 
3127      *
3128      * @example
3129      * x = new X509();
3130      * ...
3131      * x.getExtParam("30...") →
3132      * {extname:"keyUsage",critical:true,names:["digitalSignature"]}
3133      */
3134     this.getExtParam = function(hExt) {
3135 	var result = {};
3136 	var aIdx = _getChildIdx(hExt, 0);
3137 	var aIdxLen = aIdx.length;
3138 	if (aIdxLen != 2 && aIdxLen != 3)
3139 	    throw new Error("wrong number elements in Extension: " + 
3140 			    aIdxLen + " " + hExt);
3141 
3142 	var oid = _hextooidstr(_getVbyList(hExt, 0, [0], "06"));
3143 
3144 	var critical = false;
3145 	if (aIdxLen == 3 && _getTLVbyList(hExt, 0, [1]) == "0101ff")
3146 	    critical = true;
3147 
3148 	var hExtV = _getTLVbyList(hExt, 0, [aIdxLen - 1, 0]);
3149 
3150 	var extParam = undefined;
3151 	if (oid == "2.5.29.14") {
3152 	    extParam = this.getExtSubjectKeyIdentifier(hExtV, critical);
3153 	} else if (oid == "2.5.29.15") {
3154 	    extParam = this.getExtKeyUsage(hExtV, critical);
3155 	} else if (oid == "2.5.29.17") {
3156 	    extParam = this.getExtSubjectAltName(hExtV, critical);
3157 	} else if (oid == "2.5.29.18") {
3158 	    extParam = this.getExtIssuerAltName(hExtV, critical);
3159 	} else if (oid == "2.5.29.19") {
3160 	    extParam = this.getExtBasicConstraints(hExtV, critical);
3161 	} else if (oid == "2.5.29.30") {
3162 	    extParam = this.getExtNameConstraints(hExtV, critical);
3163 	} else if (oid == "2.5.29.31") {
3164 	    extParam = this.getExtCRLDistributionPoints(hExtV, critical);
3165 	} else if (oid == "2.5.29.32") {
3166 	    extParam = this.getExtCertificatePolicies(hExtV, critical);
3167 	} else if (oid == "2.5.29.33") {
3168 	    extParam = this.getExtPolicyMappings(hExtV, critical);
3169 	} else if (oid == "2.5.29.35") {
3170 	    extParam = this.getExtAuthorityKeyIdentifier(hExtV, critical);
3171 	} else if (oid == "2.5.29.36") {
3172 	    extParam = this.getExtPolicyConstraints(hExtV, critical);
3173 	} else if (oid == "2.5.29.37") {
3174 	    extParam = this.getExtExtKeyUsage(hExtV, critical);
3175 	} else if (oid == "2.5.29.54") {
3176 	    extParam = this.getExtInhibitAnyPolicy(hExtV, critical);
3177 	} else if (oid == "1.3.6.1.5.5.7.1.1") {
3178 	    extParam = this.getExtAuthorityInfoAccess(hExtV, critical);
3179 	} else if (oid == "2.5.29.20") {
3180 	    extParam = this.getExtCRLNumber(hExtV, critical);
3181 	} else if (oid == "2.5.29.21") {
3182 	    extParam = this.getExtCRLReason(hExtV, critical);
3183 	} else if (oid == "2.5.29.9") {
3184 	    extParam = this.getExtSubjectDirectoryAttributes(hExtV, critical);
3185 	} else if (oid == "1.3.6.1.5.5.7.48.1.2") {
3186 	    extParam = this.getExtOcspNonce(hExtV, critical);
3187 	} else if (oid == "1.3.6.1.5.5.7.48.1.5") {
3188 	    extParam = this.getExtOcspNoCheck(hExtV, critical);
3189 	} else if (oid == "1.2.840.113583.1.1.9.1") {
3190 	    extParam = this.getExtAdobeTimeStamp(hExtV, critical);
3191 	} else if (X509.EXT_PARSER[oid] != undefined) {
3192 	    extParam = X509.EXT_PARSER[oid](oid, critical, hExtV);
3193 	}
3194 	if (extParam != undefined) return extParam;
3195 
3196 	// for private or unsupported extension
3197 	var privateParam = { extname: oid, extn: hExtV };
3198 	try {
3199 	    privateParam.extn = _ASN1HEX_parse(hExtV);
3200 	} catch(ex) {}
3201 	if (critical) privateParam.critical = true;
3202 	return privateParam;
3203     };
3204 
3205     /**
3206      * find extension parameter in array<br/>
3207      * @name findExt
3208      * @memberOf X509#
3209      * @function
3210      * @param {Array} aExt array of extension parameters
3211      * @param {String} extname extension name
3212      * @return {Array} extension parameter in the array or null
3213      * @since jsrsasign 10.0.3 x509 2.0.7
3214      * @see X509#getParam
3215      *
3216      * @description
3217      * This method returns an extension parameter for
3218      * specified extension name in the array.
3219      * This method is useful to update extension parameter value.
3220      * When there is no such extension with the extname,
3221      * this returns "null".
3222      *
3223      * @example
3224      * // (1) 
3225      * x = new X509(CERTPEM);
3226      * params = x.getParam();
3227      * pSKID = x.findExt(params.ext, "subjectKeyIdentifier");
3228      * pSKID.kid = "1234abced..."; // skid in the params is updated.
3229      *   // then params was updated
3230      *
3231      * // (2) another example
3232      * aExt = [
3233      *   {extname:"keyUsage",critical:true,names:["digitalSignature"]},
3234      *   {extname:"basicConstraints",critical:true},
3235      *   {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}},
3236      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3237      *   {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]},
3238      *   {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}
3239      * ];
3240      * var x = new X509();
3241      * x.findExt(aExt, "authorityKeyInfoAccess").array[0].ocsp = "http://aaa.com";
3242      * pKU = x.findExt(aExt, "keyUsage");
3243      * delete pKU["critical"]; // clear criticla flag
3244      * pKU.names = ["keyCertSign", "cRLSign"];
3245      *   // then aExt was updated
3246      */
3247     this.findExt = function(aExt, extname) {
3248 	for (var i = 0; i < aExt.length; i++) {
3249 	    if (aExt[i].extname == extname) return aExt[i];
3250 	}
3251 	return null;
3252 
3253     };
3254 
3255     /**
3256      * update CRLDistributionPoints Full URI in parameter<br/>
3257      * @name updateCDPFullURI
3258      * @memberOf X509#
3259      * @function
3260      * @param {Array} aExt array of extension parameters
3261      * @param {String} newURI string of new uri
3262      * @since jsrsasign 10.0.4 x509 2.0.8
3263      * @see X509#findExt
3264      * @see KJUR.asn1.x509.CRLDistributionPoints
3265      *
3266      * @description
3267      * This method updates Full URI of CRLDistributionPoints extension
3268      * in the extension parameter array if it exists.
3269      *
3270      * @example
3271      * aExt = [
3272      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3273      *   {extname:"cRLDistributionPoints",
3274      *    array:[{dpname:{full:[{uri:"http://example.com/a.crl"}]}}]},
3275      * ];
3276      * x = new X509();
3277      * x.updateCDPFullURI(aExt, "http://crl2.example.new/b.crl");
3278      */
3279     this.updateExtCDPFullURI = function(aExt, newURI) {
3280 	var pExt = this.findExt(aExt, "cRLDistributionPoints");
3281 	if (pExt == null) return;
3282 	if (pExt.array == undefined) return;
3283 	var aDP = pExt.array;
3284 	for (var i = 0; i < aDP.length; i++) {
3285 	    if (aDP[i].dpname == undefined) continue;
3286 	    if (aDP[i].dpname.full == undefined) continue;
3287 	    var aURI = aDP[i].dpname.full;
3288 	    for (var j = 0; j < aURI.length; j++) {
3289 		var pURI = aURI[i];
3290 		if (pURI.uri == undefined) continue;
3291 		pURI.uri = newURI;
3292 	    }
3293 	}
3294     };
3295 
3296     /**
3297      * update authorityInfoAccess ocsp in parameter<br/>
3298      * @name updateAIAOCSP
3299      * @memberOf X509#
3300      * @function
3301      * @param {Array} aExt array of extension parameters
3302      * @param {String} newURI string of new uri
3303      * @since jsrsasign 10.0.4 x509 2.0.8
3304      * @see X509#findExt
3305      * @see KJUR.asn1.x509.AuthorityInfoAccess
3306      *
3307      * @description
3308      * This method updates "ocsp" accessMethod URI of 
3309      * AuthorityInfoAccess extension
3310      * in the extension parameter array if it exists.
3311      *
3312      * @example
3313      * aExt = [
3314      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3315      *   {extname:"authoriyInfoAccess",
3316      *    array:[
3317      *      {ocsp: "http://ocsp1.example.com"},
3318      *      {caissuer: "http://example.com/a.crt"}
3319      *    ]}
3320      * ];
3321      * x = new X509();
3322      * x.updateAIAOCSP(aExt, "http://ocsp2.example.net");
3323      */
3324     this.updateExtAIAOCSP = function(aExt, newURI) {
3325 	var pExt = this.findExt(aExt, "authorityInfoAccess");
3326 	if (pExt == null) return;
3327 	if (pExt.array == undefined) return;
3328 	var a = pExt.array;
3329 	for (var i = 0; i < a.length; i++) {
3330 	    if (a[i].ocsp != undefined) a[i].ocsp = newURI;
3331 	}
3332     };
3333 
3334     /**
3335      * update authorityInfoAccess caIssuer in parameter<br/>
3336      * @name updateAIACAIssuer
3337      * @memberOf X509#
3338      * @function
3339      * @param {Array} aExt array of extension parameters
3340      * @param {String} newURI string of new uri
3341      * @since jsrsasign 10.0.4 x509 2.0.8
3342      * @see X509#findExt
3343      * @see KJUR.asn1.x509.AuthorityInfoAccess
3344      *
3345      * @description
3346      * This method updates "caIssuer" accessMethod URI of 
3347      * AuthorityInfoAccess extension
3348      * in the extension parameter array if it exists.
3349      *
3350      * @example
3351      * aExt = [
3352      *   {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}},
3353      *   {extname:"authoriyInfoAccess",
3354      *    array:[
3355      *      {ocsp: "http://ocsp1.example.com"},
3356      *      {caissuer: "http://example.com/a.crt"}
3357      *    ]}
3358      * ];
3359      * x = new X509();
3360      * x.updateAIACAIssuer(aExt, "http://example.net/b.crt");
3361      */
3362     this.updateExtAIACAIssuer = function(aExt, newURI) {
3363 	var pExt = this.findExt(aExt, "authorityInfoAccess");
3364 	if (pExt == null) return;
3365 	if (pExt.array == undefined) return;
3366 	var a = pExt.array;
3367 	for (var i = 0; i < a.length; i++) {
3368 	    if (a[i].caissuer != undefined) a[i].caissuer = newURI;
3369 	}
3370     };
3371 
3372     /**
3373      * convert array for X500 distinguish name to distinguish name string<br/>
3374      * @name dnarraytostr
3375      * @memberOf X509#
3376      * @function
3377      * @param {Array} aDN array for X500 distinguish name
3378      * @return {String} distinguish name
3379      * @since jsrsasign 10.0.6 x509 2.0.8
3380      * @see X509#getX500Name
3381      * @see X509#getX500NameArray
3382      * @see KJUR.asn1.x509.X500Name
3383      *
3384      * @description
3385      * This method converts from an array representation of 
3386      * X.500 distinguished name to X.500 name string.
3387      * This supports multi-valued RDN.
3388      * 
3389      * @example
3390      * var x = new X509();
3391      * x.dnarraytostr(
3392      *   [[{type:"C",value:"JP",ds:"prn"}],
3393      *   [{type:"O",value:"T1",ds:"prn"}]]) → "/C=JP/O=T1"
3394      * x.dnarraytostr(
3395      *   [[{type:"C",value:"JP",ds:"prn"}],
3396      *   [{type:"O",value:"T1",ds:"prn"}
3397      *    {type:"CN",value:"Bob",ds:"prn"}]]) → "/C=JP/O=T1+CN=Bob"
3398      */
3399     this.dnarraytostr = function(aDN) {
3400 	function rdnarraytostr(aRDN) {
3401 	    return aRDN.map(function(x){return atvtostr(x).replace(/\+/,"\\+");}).join("+");
3402 	};
3403 
3404 	function atvtostr(pATV) {
3405 	    return pATV.type + "=" + pATV.value;
3406 	};
3407 
3408 	return "/" + aDN.map(function(x){return rdnarraytostr(x).replace(/\//, "\\/");}).join("/");
3409     };
3410 
3411     /**
3412      * set canonicalized DN to a DN parameter<br/>
3413      * @name setCanonicalizedDN
3414      * @memberOf X509#
3415      * @function
3416      * @param {object} pDN DN parameter associative array
3417      * @since jsrsasign 10.6.0 x509 2.1.0
3418      * 
3419      * @description
3420      * This method canonicalizes a DN string as following:
3421      * <ul>
3422      * <li>convert to lower case</li>
3423      * <li>convert from all multiple spaces to a space</li>
3424      * </ul>
3425      * 
3426      * @example
3427      * var x = new X509();
3428      * var pDN = {
3429      *   array: [
3430      *     [{type:'C',value:'JP',ds:'prn'}],
3431      *     [{type:'O',value:'Test    1',ds:'prn'}] ],
3432      *   str: "/C=JP/O=Test    1" };
3433      * x.setCanonicalizedDN(pDN);
3434 
3435      * // pDN will become following
3436      * pDN = {
3437      *   array: [
3438      *     [{type:'C',value:'JP',ds:'prn'}],
3439      *     [{type:'O',value:'Test    1',ds:'prn'}] ],
3440      *   str: "/C=JP/O=Test    1",
3441      *   canon: "/c=jp/o=test 1" };
3442      */
3443     this.setCanonicalizedDN = function(pDN) {
3444 	var aRDN;
3445 	if (pDN.str != undefined && pDN.array == undefined) {
3446 	    var dDN = new KJUR.asn1.x509.X500Name({str: pDN.str});
3447 	    var hDN = dDN.tohex();
3448 	    aRDN = this.getX500NameArray(hDN);
3449 	} else {
3450 	    aRDN = pDN.array;
3451 	}
3452 	if (pDN.canon == undefined) {
3453 	    pDN.canon = this.c14nRDNArray(aRDN);
3454 	}
3455     };
3456 
3457     /**
3458      * simple canonicalization(c14n) for RDN array<br/>
3459      * @name c14nRDNArray
3460      * @memberOf X509#
3461      * @function
3462      * @param {array} aRDN array of RDN parameters
3463      * @return {string} canonicalized distinguish name (ex. "/c=jp/o=test ca")
3464      * @since jsrsasign 10.6.0 x509 2.1.0
3465      * 
3466      * @description
3467      * This method canonicalizes a DN string according to
3468      * <a href="https://datatracker.ietf.org/doc/html/rfc4518#appendix-B">
3469      * "RFC 4518 StringPrep Appendix B Substring Matching"</a> as following:
3470      * <ul>
3471      * <li>convert to lower case</li>
3472      * <li>convert from all sequence of spaces to a space</li>
3473      * <li>remove leading and trailing spaces</li>
3474      * </ul>
3475      * 
3476      * @example
3477      * var x = new X509();
3478      * x.c14nRDNArray([
3479      *   [{type:"C", value:"JP", ds: "prn"}],
3480      *   [{type:"O", value:"    Test    1234     ", ds: "utf8"}],
3481      *   [{type:"OU", value:"HR   45", ds: "utf8"}]
3482      * ]) → "/c=jp/o=test 1234/ou=hr 45"
3483      */
3484     this.c14nRDNArray = function(aRDN) {
3485 	var a = [];
3486 	for (var i = 0; i < aRDN.length; i++) {
3487 	    var aAVA = aRDN[i];
3488 	    var a2 = [];
3489 	    for (var j = 0; j < aAVA.length; j++) {
3490 		var pAVA = aAVA[j];
3491 		var value = pAVA.value;
3492 		value = value.replace(/^\s*/, '');
3493 		value = value.replace(/\s*$/, '');
3494 		value = value.replace(/\s+/g, ' ');
3495 		value = value.toLowerCase();
3496 		a2.push(pAVA.type.toLowerCase() + "=" + value);
3497 	    }
3498 	    a.push(a2.join("+"));
3499 	}
3500 	return "/" + a.join("/");
3501     };
3502 
3503     /**
3504      * get certificate information as string.<br/>
3505      * @name getInfo
3506      * @memberOf X509#
3507      * @function
3508      * @return {String} certificate information string
3509      * @since jsrsasign 5.0.10 x509 1.1.8
3510      * @example
3511      * x = new X509();
3512      * x.readCertPEM(certPEM);
3513      * console.log(x.getInfo());
3514      * // this shows as following
3515      * Basic Fields
3516      *   serial number: 02ac5c266a0b409b8f0b79f2ae462577
3517      *   signature algorithm: SHA1withRSA
3518      *   issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
3519      *   notBefore: 061110000000Z
3520      *   notAfter: 311110000000Z
3521      *   subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
3522      *   subject public key info:
3523      *     key algorithm: RSA
3524      *     n=c6cce573e6fbd4bb...
3525      *     e=10001
3526      * X509v3 Extensions:
3527      *   keyUsage CRITICAL:
3528      *     digitalSignature,keyCertSign,cRLSign
3529      *   basicConstraints CRITICAL:
3530      *     cA=true
3531      *   subjectKeyIdentifier :
3532      *     b13ec36903f8bf4701d498261a0802ef63642bc3
3533      *   authorityKeyIdentifier :
3534      *     kid=b13ec36903f8bf4701d498261a0802ef63642bc3
3535      * signature algorithm: SHA1withRSA
3536      * signature: 1c1a0697dcd79c9f...
3537      */
3538     this.getInfo = function() {
3539 	var _getSubjectAltNameStr = function(params) {
3540 	    var s = "";
3541 	    var indent = "    ";
3542 	    var NL = "\n";
3543 	    var a = params.array;
3544 	    for (var i = 0; i < a.length; i++) {
3545 		var pGN = a[i];
3546 		if (pGN.dn != undefined)	s += indent + "dn: " + pGN.dn.str + NL;
3547 		if (pGN.ip != undefined)	s += indent + "ip: " + pGN.ip + NL;
3548 		if (pGN.rfc822 != undefined)	s += indent + "rfc822: " + pGN.rfc822 + NL;
3549 		if (pGN.dns != undefined)	s += indent + "dns: " + pGN.dns + NL;
3550 		if (pGN.uri != undefined)	s += indent + "uri: " + pGN.uri + NL;
3551 		if (pGN.other != undefined) {
3552 		    var oidname = pGN.other.oid;
3553 		    var value = JSON.stringify(pGN.other.value).replace(/\"/g, '');
3554 		    s += indent + "other: " + oidname + "=" + value + NL;
3555 		}
3556 	    }
3557 	    s = s.replace(/\n$/, '');
3558 	    return s;
3559 	};
3560 	var _getCertificatePoliciesStr = function(params) {
3561 	    var s = "";
3562 	    var a = params.array;
3563 	    for (var i = 0; i < a.length; i++) {
3564 		var pi = a[i];
3565 		s += "    policy oid: " + pi.policyoid + "\n";
3566 		if (pi.array === undefined) continue;
3567 		for (var j = 0; j < pi.array.length; j++) {
3568 		    var pqi = pi.array[j];
3569 		    if (pqi.cps !== undefined) {
3570 			s += "    cps: " + pqi.cps + "\n";
3571 		    }
3572 		}
3573 	    }
3574 	    return s;
3575 	};
3576 	var _getCRLDistributionPointsStr = function(params) {
3577 	    var s = "";
3578 	    var a = params.array;
3579 	    for (var i = 0; i < a.length; i++) {
3580 		var dp = a[i];
3581 		try {
3582 		    if (dp.dpname.full[0].uri !== undefined)
3583 			s += "    " + dp.dpname.full[0].uri + "\n";
3584 		} catch(ex) {};
3585 		try {
3586 		    if (dp.dname.full[0].dn.hex !== undefined)
3587 			s += "    " + X509.hex2dn(dp.dpname.full[0].dn.hex) + "\n";
3588 		} catch(ex) {};
3589 	    }
3590 	    return s;
3591 	}
3592 	var _getAuthorityInfoAccessStr = function(params) {
3593 	    var s = "";
3594 	    var a = params.array;
3595 	    for (var i = 0; i < a.length; i++) {
3596 		var ad = a[i];
3597 
3598 		if (ad.caissuer !== undefined)
3599 		    s += "    caissuer: " + ad.caissuer + "\n";
3600 		if (ad.ocsp !== undefined)
3601 		    s += "    ocsp: " + ad.ocsp + "\n";
3602 	    }
3603 	    return s;
3604 	};
3605 	var _X509 = X509;
3606 	var s, pubkey, aExt;
3607 	s  = "Basic Fields\n";
3608         s += "  serial number: " + this.getSerialNumberHex() + "\n";
3609 	s += "  signature algorithm: " + this.getSignatureAlgorithmField() + "\n";
3610 	s += "  issuer: " + this.getIssuerString() + "\n";
3611 	s += "  notBefore: " + this.getNotBefore() + "\n";
3612 	s += "  notAfter: " + this.getNotAfter() + "\n";
3613 	s += "  subject: " + this.getSubjectString() + "\n";
3614 	s += "  subject public key info: " + "\n";
3615 
3616 	// subject public key info
3617 	pubkey = this.getPublicKey();
3618 	s += "    key algorithm: " + pubkey.type + "\n";
3619 
3620 	if (pubkey.type === "RSA") {
3621 	    s += "    n=" + hextoposhex(pubkey.n.toString(16)).substr(0, 16) + "...\n";
3622 	    s += "    e=" + hextoposhex(pubkey.e.toString(16)) + "\n";
3623 	}
3624 
3625 	// X.509v3 Extensions
3626         aExt = this.aExtInfo;
3627 
3628 	if (aExt !== undefined && aExt !== null) {
3629             s += "X509v3 Extensions:\n";
3630 	    
3631             for (var i = 0; i < aExt.length; i++) {
3632 		var info = aExt[i];
3633 
3634 		// show extension name and critical flag
3635 		var extName = KJUR.asn1.x509.OID.oid2name(info["oid"]);
3636 		if (extName === '') extName = info["oid"];
3637 
3638 		var critical = '';
3639 		if (info["critical"] === true) critical = "CRITICAL";
3640 
3641 		s += "  " + extName + " " + critical + ":\n";
3642 
3643 		// show extension value if supported
3644 		if (extName === "basicConstraints") {
3645 		    var bc = this.getExtBasicConstraints();
3646 		    if (bc.cA === undefined) {
3647 			s += "    {}\n";
3648 		    } else {
3649 			s += "    cA=true";
3650 			if (bc.pathLen !== undefined)
3651 			    s += ", pathLen=" + bc.pathLen;
3652 			s += "\n";
3653 		    }
3654 		} else if (extName == "policyMappings") {
3655 		    var a = this.getExtPolicyMappings().array;
3656 		    var sMap = a.map(function(item){
3657 			var aPolicy = item;
3658 			return aPolicy[0] + ":" + aPolicy[1];
3659 		    }).join(", ");
3660 		    s += "    " + sMap + "\n";
3661 		} else if (extName == "policyConstraints") {
3662 		    var p = this.getExtPolicyConstraints();
3663 		    s += "    ";
3664 		    if (p.reqexp != undefined) s += " reqexp=" + p.reqexp;
3665 		    if (p.inhibit != undefined) s += " inhibit=" + p.inhibit;
3666 		    s += "\n";
3667 		} else if (extName == "inhibitAnyPolicy") {
3668 		    var p = this.getExtInhibitAnyPolicy();
3669 		    s += "    skip=" + p.skip + "\n";
3670 		} else if (extName == "keyUsage") {
3671 		    s += "    " + this.getExtKeyUsageString() + "\n";
3672 		} else if (extName == "subjectKeyIdentifier") {
3673 		    s += "    " + this.getExtSubjectKeyIdentifier().kid.hex + "\n";
3674 		} else if (extName == "authorityKeyIdentifier") {
3675 		    var akid = this.getExtAuthorityKeyIdentifier();
3676 		    if (akid.kid !== undefined)
3677 			s += "    kid=" + akid.kid.hex + "\n";
3678 		} else if (extName == "extKeyUsage") {
3679 		    var eku = this.getExtExtKeyUsage().array;
3680 		    s += "    " + eku.join(", ") + "\n";
3681 		} else if (extName == "subjectAltName") {
3682 		    var san = _getSubjectAltNameStr(this.getExtSubjectAltName());
3683 		    s += san + "\n";
3684 		} else if (extName == "cRLDistributionPoints") {
3685 		    var cdp = this.getExtCRLDistributionPoints();
3686 		    s += _getCRLDistributionPointsStr(cdp);
3687 		} else if (extName == "authorityInfoAccess") {
3688 		    var aia = this.getExtAuthorityInfoAccess();
3689 		    s += _getAuthorityInfoAccessStr(aia);
3690 		} else if (extName == "certificatePolicies") {
3691 		    s += _getCertificatePoliciesStr(this.getExtCertificatePolicies());
3692 		}
3693 	    }
3694         }
3695 
3696 	s += "signature algorithm: " + this.getSignatureAlgorithmName() + "\n";
3697 	s += "signature: " + this.getSignatureValueHex().substr(0, 16) + "...\n";
3698 	return s;
3699     };
3700 
3701     if (typeof params == "string") {
3702 	if (params.indexOf("-----BEGIN") != -1) {
3703 	    this.readCertPEM(params);
3704 	} else if (KJUR.lang.String.isHex(params)) {
3705 	    this.readCertHex(params);
3706 	}
3707     }
3708 };
3709 // ----- END of X509 class -----
3710 
3711 /**
3712  * additional definition for X.509 extension parsers<br/>
3713  * @see X509.registExtParser
3714  */
3715 X509.EXT_PARSER = {
3716 };
3717 
3718 /**
3719  * define X.509 extension parser for specified OID<br/>
3720  * @name registExtParser
3721  * @memberOf X509
3722  * @function
3723  * @param {string} oid extension OID string (ex. "1.2.3.4")
3724  * @param {function} func registering func extension value parsing function
3725  * @return unspecified
3726  * @since jsrsasign 10.7.0 x509 2.1.2
3727  * 
3728  * @description
3729  * <p>
3730  * This static method specifies a X.509 extension value parsing function
3731  * for specified an extension OID.
3732  * </p>
3733  * <p>
3734  * Extension parser function must have following three arguments:
3735  * <ul>
3736  * <li>{string} oid - OID for extension (ex. "1.2.3.4")</li>
3737  * <li>{boolean} critical - critical flag of extension</li>
3738  * <li>{string} hExtV - hexadecimal string of extension value</li>
3739  * </ul>
3740  * The funcition must return an associative array for the extension
3741  * when hExtV can be parsed properly. Otherwise it must return
3742  * value "undefined".
3743  * </p>
3744  *
3745  * @example
3746  * function _extparser1(oid, critical, hExtV) {
3747  *   try {
3748  *     var result = { extname: oid, value: ASN1HEX.parse(hExtV).utf8str.str };
3749  *     if (critical) result.critical = true;
3750  *     return result;
3751  *   } catch(ex) {
3752  *     return undefined;
3753  *   }
3754  * }
3755  * X509.registExtParser("1.2.3.4", _extparser1);
3756  */
3757 X509.registExtParser = function(oid, func) {
3758     X509.EXT_PARSER[oid] = func;
3759 };
3760 
3761 /**
3762  * get distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER X.500 name<br/>
3763  * @name hex2dn
3764  * @memberOf X509
3765  * @function
3766  * @param {String} hex hexadecimal string of ASN.1 DER distinguished name
3767  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
3768  * @return {String} OpenSSL online format distinguished name
3769  * @description
3770  * This static method converts from a hexadecimal string of 
3771  * distinguished name (DN)
3772  * specified by 'hex' and 'idx' to OpenSSL oneline string representation (ex. /C=US/O=a).
3773  * @example
3774  * X509.hex2dn("3031310b3...") → /C=US/O=a/CN=b2+OU=b1
3775  */
3776 X509.hex2dn = function(hex, idx) {
3777     if (idx === undefined) idx = 0;
3778     var x = new X509();
3779     var hDN = ASN1HEX.getTLV(hex, idx);
3780     var pDN = x.getX500Name(hex);
3781     return pDN.str;
3782 };
3783 
3784 /**
3785  * get relative distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER RDN<br/>
3786  * @name hex2rdn
3787  * @memberOf X509
3788  * @function
3789  * @param {String} hex hexadecimal string of ASN.1 DER concludes relative distinguished name
3790  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
3791  * @return {String} OpenSSL online format relative distinguished name
3792  * @description
3793  * This static method converts from a hexadecimal string of 
3794  * relative distinguished name (RDN)
3795  * specified by 'hex' and 'idx' to LDAP string representation (ex. O=test+CN=test).<br/>
3796  * NOTE: Multi-valued RDN is supported since jsnrsasign 6.2.2 x509 1.1.10.
3797  * @example
3798  * X509.hex2rdn("310a3008060355040a0c0161") → O=a
3799  * X509.hex2rdn("31143008060355040a0c01613008060355040a0c0162") → O=a+O=b
3800  */
3801 X509.hex2rdn = function(hex, idx) {
3802     if (idx === undefined) idx = 0;
3803     if (hex.substr(idx, 2) !== "31") throw new Error("malformed RDN");
3804 
3805     var a = new Array();
3806 
3807     var aIdx = ASN1HEX.getChildIdx(hex, idx);
3808     for (var i = 0; i < aIdx.length; i++) {
3809 	a.push(X509.hex2attrTypeValue(hex, aIdx[i]));
3810     }
3811 
3812     a = a.map(function(s) { return s.replace("+", "\\+"); });
3813     return a.join("+");
3814 };
3815 
3816 /**
3817  * get string from hexadecimal string of ASN.1 DER AttributeTypeAndValue<br/>
3818  * @name hex2attrTypeValue
3819  * @memberOf X509
3820  * @function
3821  * @param {String} hex hexadecimal string of ASN.1 DER concludes AttributeTypeAndValue
3822  * @param {Integer} idx index of hexadecimal string (DEFAULT=0)
3823  * @return {String} string representation of AttributeTypeAndValue (ex. C=US)
3824  * @description
3825  * This static method converts from a hexadecimal string of AttributeTypeAndValue
3826  * specified by 'hex' and 'idx' to LDAP string representation (ex. C=US).
3827  * @example
3828  * X509.hex2attrTypeValue("3008060355040a0c0161") → O=a
3829  * X509.hex2attrTypeValue("300806035504060c0161") → C=a
3830  * X509.hex2attrTypeValue("...3008060355040a0c0161...", 128) → O=a
3831  */
3832 X509.hex2attrTypeValue = function(hex, idx) {
3833     var _ASN1HEX = ASN1HEX;
3834     var _getV = _ASN1HEX.getV;
3835 
3836     if (idx === undefined) idx = 0;
3837     if (hex.substr(idx, 2) !== "30") 
3838 	throw new Error("malformed attribute type and value");
3839 
3840     var aIdx = _ASN1HEX.getChildIdx(hex, idx);
3841     if (aIdx.length !== 2 || hex.substr(aIdx[0], 2) !== "06")
3842 	"malformed attribute type and value";
3843 
3844     var oidHex = _getV(hex, aIdx[0]);
3845     var oidInt = KJUR.asn1.ASN1Util.oidHexToInt(oidHex);
3846     var atype = KJUR.asn1.x509.OID.oid2atype(oidInt);
3847 
3848     var hV = _getV(hex, aIdx[1]);
3849     var rawV = hextorstr(hV);
3850 
3851     return atype + "=" + rawV;
3852 };
3853 
3854 /**
3855  * get RSA/DSA/ECDSA public key object from X.509 certificate hexadecimal string<br/>
3856  * @name getPublicKeyFromCertHex
3857  * @memberOf X509
3858  * @function
3859  * @param {String} h hexadecimal string of X.509 certificate for RSA/ECDSA/DSA public key
3860  * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
3861  * @since jsrasign 7.1.0 x509 1.1.11
3862  */
3863 X509.getPublicKeyFromCertHex = function(h) {
3864     var x = new X509();
3865     x.readCertHex(h);
3866     return x.getPublicKey();
3867 };
3868 
3869 /**
3870  * get RSA/DSA/ECDSA public key object from PEM certificate string
3871  * @name getPublicKeyFromCertPEM
3872  * @memberOf X509
3873  * @function
3874  * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
3875  * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
3876  * @since x509 1.1.1
3877  * @description
3878  * NOTE: DSA is also supported since x509 1.1.2.
3879  */
3880 X509.getPublicKeyFromCertPEM = function(sCertPEM) {
3881     var x = new X509();
3882     x.readCertPEM(sCertPEM);
3883     return x.getPublicKey();
3884 };
3885 
3886 /**
3887  * get public key information from PEM certificate
3888  * @name getPublicKeyInfoPropOfCertPEM
3889  * @memberOf X509
3890  * @function
3891  * @param {String} sCertPEM string of PEM formatted certificate
3892  * @return {Hash} hash of information for public key
3893  * @since x509 1.1.1
3894  * @description
3895  * Resulted associative array has following properties:<br/>
3896  * <ul>
3897  * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li>
3898  * <li>algparam - hexadecimal string of OID of ECC curve name or null</li>
3899  * <li>keyhex - hexadecimal string of key in the certificate</li>
3900  * </ul>
3901  * NOTE: X509v1 certificate is also supported since x509.js 1.1.9.
3902  */
3903 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
3904     var _ASN1HEX = ASN1HEX;
3905     var _getVbyList = _ASN1HEX.getVbyList;
3906 
3907     var result = {};
3908     var x, hSPKI, pubkey;
3909     result.algparam = null;
3910 
3911     x = new X509();
3912     x.readCertPEM(sCertPEM);
3913 
3914     hSPKI = x.getPublicKeyHex();
3915     result.keyhex = _getVbyList(hSPKI, 0, [1], "03").substr(2);
3916     result.algoid = _getVbyList(hSPKI, 0, [0, 0], "06");
3917 
3918     if (result.algoid === "2a8648ce3d0201") { // ecPublicKey
3919 	result.algparam = _getVbyList(hSPKI, 0, [0, 1], "06");
3920     };
3921 
3922     return result;
3923 };
3924 
3925 /* ======================================================================
3926  *   Specific V3 Extensions
3927  * ====================================================================== */
3928 
3929 X509.KEYUSAGE_NAME = [
3930     "digitalSignature",
3931     "nonRepudiation",
3932     "keyEncipherment",
3933     "dataEncipherment",
3934     "keyAgreement",
3935     "keyCertSign",
3936     "cRLSign",
3937     "encipherOnly",
3938     "decipherOnly"
3939 ];
3940