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