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