1 /*! x509-1.1.9.js (c) 2012-2016 Kenji Urushima | kjur.github.com/jsrsasign/license
  2  */
  3 /* 
  4  * x509.js - X509 class to read subject public key from certificate.
  5  *
  6  * Copyright (c) 2010-2016 Kenji Urushima (kenji.urushima@gmail.com)
  7  *
  8  * This software is licensed under the terms of the MIT License.
  9  * http://kjur.github.com/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 x509 1.1.9 (2016-May-10)
 20  * @since jsrsasign 1.x.x
 21  * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 22  */
 23 
 24 /*
 25  * Depends:
 26  *   base64.js
 27  *   rsa.js
 28  *   asn1hex.js
 29  */
 30 
 31 /**
 32  * hexadecimal X.509 certificate ASN.1 parser class.<br/>
 33  * @class hexadecimal X.509 certificate ASN.1 parser class
 34  * @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object
 35  * @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key
 36  * @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key
 37  * @property {String} hex hexacedimal string for X.509 certificate.
 38  * @author Kenji Urushima
 39  * @version 1.0.1 (08 May 2012)
 40  * @see <a href="http://kjur.github.com/jsrsasigns/">'jsrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
 41  * @description
 42  * X509 class provides following functionality:
 43  * <ul>
 44  * <li>parse X.509 certificate ASN.1 structure</li>
 45  * <li>get basic fields, extensions, signature algorithms and signature values</li>
 46  * <li>read PEM certificate</li>
 47  * </ul>
 48  * 
 49  * <ul>
 50  * <li><b>TO GET FIELDS</b>
 51  *   <ul>
 52  *   <li>serial - {@link X509#getSerialNumberHex}</li>
 53  *   <li>issuer - {@link X509#getIssuerHex}</li>
 54  *   <li>issuer - {@link X509#getIssuerString}</li>
 55  *   <li>notBefore - {@link X509#getNotBefore}</li>
 56  *   <li>notAfter - {@link X509#getNotAfter}</li>
 57  *   <li>subject - {@link X509#getSubjectHex}</li>
 58  *   <li>subject - {@link X509#getSubjectString}</li>
 59  *   <li>subjectPublicKeyInfo - {@link X509.getSubjectPublicKeyPosFromCertHex}</li>
 60  *   <li>subjectPublicKeyInfo - {@link X509.getSubjectPublicKeyInfoPosFromCertHex}</li>
 61  *   <li>subjectPublicKeyInfo - {@link X509.getPublicKeyFromCertPEM}</li>
 62  *   <li>signature algorithm - {@link X509.getSignatureAlgorithmName}</li>
 63  *   <li>signature value - {@link X509.getSignatureValueHex}</li>
 64  *   </ul>
 65  * </li>
 66  * <li><b>TO GET EXTENSIONS</b>
 67  *   <ul>
 68  *   <li>basicConstraints - {@link X509.getExtBasicConstraints}</li>
 69  *   <li>keyUsage - {@link X509.getExtKeyUsageBin}</li>
 70  *   <li>keyUsage - {@link X509.getExtKeyUsageString}</li>
 71  *   <li>subjectKeyIdentifier - {@link X509.getExtSubjectKeyIdentifier}</li>
 72  *   <li>authorityKeyIdentifier - {@link X509.getExtAuthorityKeyIdentifier}</li>
 73  *   <li>extKeyUsage - {@link X509.getExtExtKeyUsageName}</li>
 74  *   <li>subjectAltName - {@link X509.getExtSubjectAltName}</li>
 75  *   <li>cRLDistributionPoints - {@link X509.getExtCRLDistributionPointsURI}</li>
 76  *   <li>authorityInfoAccess - {@link X509.getExtAIAInfo}</li>
 77  *   </ul>
 78  * </li>
 79  * <li><b>UTILITIES</b>
 80  *   <ul>
 81  *   <li>reading PEM certificate - {@link X509#readCertPEM}</li>
 82  *   <li>get all certificate information - {@link X509#getInfo}</li>
 83  *   <li>get Base64 from PEM certificate - {@link X509.pemToBase64}</li>
 84  *   <li>get hexadecimal string from PEM certificate - {@link X509.pemToHex}</li>
 85  *   </ul>
 86  * </li>
 87  * </ul>
 88  */
 89 function X509() {
 90     this.subjectPublicKeyRSA = null;
 91     this.subjectPublicKeyRSA_hN = null;
 92     this.subjectPublicKeyRSA_hE = null;
 93     this.hex = null;
 94 
 95     // ===== get basic fields from hex =====================================
 96 
 97     /**
 98      * get hexadecimal string of serialNumber field of certificate.<br/>
 99      * @name getSerialNumberHex
100      * @memberOf X509#
101      * @function
102      * @return {String} hexadecimal string of certificate serial number
103      * @example
104      * var x = new X509();
105      * x.readCertPEM(sCertPEM);
106      * var sn = x.getSerialNumberHex(); // return string like "01ad..."
107      */
108     this.getSerialNumberHex = function() {
109         return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
110     };
111 
112 
113     /**
114      * get signature algorithm name in basic field
115      * @name getSignatureAlgorithmField
116      * @memberOf X509#
117      * @function
118      * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA)
119      * @since x509 1.1.8
120      * @description
121      * This method will get a name of signature algorithm field of certificate:
122      * @example
123      * var x = new X509();
124      * x.readCertPEM(sCertPEM);
125      * algName = x.getSignatureAlgorithmField();
126      */
127     this.getSignatureAlgorithmField = function() {
128 	var sigAlgOidHex = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 2, 0]);
129 	var sigAlgOidInt = KJUR.asn1.ASN1Util.oidHexToInt(sigAlgOidHex);
130 	var sigAlgName = KJUR.asn1.x509.OID.oid2name(sigAlgOidInt);
131 	return sigAlgName;
132     };
133 
134     /**
135      * get hexadecimal string of issuer field TLV of certificate.<br/>
136      * @name getIssuerHex
137      * @memberOf X509#
138      * @function
139      * @return {String} hexadecial string of issuer DN ASN.1
140      * @example
141      * var x = new X509();
142      * x.readCertPEM(sCertPEM);
143      * var issuer = x.getIssuerHex(); // return string like "3013..."
144      */
145     this.getIssuerHex = function() {
146         return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
147     };
148 
149     /**
150      * get string of issuer field of certificate.<br/>
151      * @name getIssuerString
152      * @memberOf X509#
153      * @function
154      * @return {String} issuer DN string
155      * @example
156      * var x = new X509();
157      * x.readCertPEM(sCertPEM);
158      * var issuer = x.getIssuerString(); // return string like "/C=US/O=TEST"
159      */
160     this.getIssuerString = function() {
161         return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
162     };
163 
164     /**
165      * get hexadecimal string of subject field of certificate.<br/>
166      * @name getSubjectHex
167      * @memberOf X509#
168      * @function
169      * @return {String} hexadecial string of subject DN ASN.1
170      * @example
171      * var x = new X509();
172      * x.readCertPEM(sCertPEM);
173      * var subject = x.getSubjectHex(); // return string like "3013..."
174      */
175     this.getSubjectHex = function() {
176         return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
177     };
178 
179     /**
180      * get string of subject field of certificate.<br/>
181      * @name getSubjectString
182      * @memberOf X509#
183      * @function
184      * @return {String} subject DN string
185      * @example
186      * var x = new X509();
187      * x.readCertPEM(sCertPEM);
188      * var subject = x.getSubjectString(); // return string like "/C=US/O=TEST"
189      */
190     this.getSubjectString = function() {
191         return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
192     };
193 
194     /**
195      * get notBefore field string of certificate.<br/>
196      * @name getNotBefore
197      * @memberOf X509#
198      * @function
199      * @return {String} not before time value (ex. "151231235959Z")
200      * @example
201      * var x = new X509();
202      * x.readCertPEM(sCertPEM);
203      * var notBefore = x.getNotBefore(); // return string like "151231235959Z"
204      */
205     this.getNotBefore = function() {
206         var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
207         s = s.replace(/(..)/g, "%$1");
208         s = decodeURIComponent(s);
209         return s;
210     };
211 
212     /**
213      * get notAfter field string of certificate.<br/>
214      * @name getNotAfter
215      * @memberOf X509#
216      * @function
217      * @return {String} not after time value (ex. "151231235959Z")
218      * @example
219      * var x = new X509();
220      * x.readCertPEM(sCertPEM);
221      * var notAfter = x.getNotAfter(); // return string like "151231235959Z"
222      */
223     this.getNotAfter = function() {
224         var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
225         s = s.replace(/(..)/g, "%$1");
226         s = decodeURIComponent(s);
227         return s;
228     };
229 
230     // ===== read certificate public key ==========================
231 
232     // ===== read certificate =====================================
233     /**
234      * read PEM formatted X.509 certificate from string.<br/>
235      * @name readCertPEM
236      * @memberOf X509#
237      * @function
238      * @param {String} sCertPEM string for PEM formatted X.509 certificate
239      * @example
240      * x = new X509();
241      * x.readCertPEM(sCertPEM); // read certificate
242      */
243     this.readCertPEM = function(sCertPEM) {
244         var hCert = X509.pemToHex(sCertPEM);
245         var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
246         var rsa = new RSAKey();
247         rsa.setPublic(a[0], a[1]);
248         this.subjectPublicKeyRSA = rsa;
249         this.subjectPublicKeyRSA_hN = a[0];
250         this.subjectPublicKeyRSA_hE = a[1];
251         this.hex = hCert;
252     };
253 
254     this.readCertPEMWithoutRSAInit = function(sCertPEM) {
255         var hCert = X509.pemToHex(sCertPEM);
256         var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
257         this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
258         this.subjectPublicKeyRSA_hN = a[0];
259         this.subjectPublicKeyRSA_hE = a[1];
260         this.hex = hCert;
261     };
262 
263     /**
264      * get certificate information as string.<br/>
265      * @name getInfo
266      * @memberOf X509#
267      * @function
268      * @return {String} certificate information string
269      * @since jsrsasign 5.0.10 x509 1.1.8
270      * @example
271      * x = new X509();
272      * x.readCertPEM(certPEM);
273      * console.log(x.getInfo());
274      * // this shows as following
275      * Basic Fields
276      *   serial number: 02ac5c266a0b409b8f0b79f2ae462577
277      *   signature algorithm: SHA1withRSA
278      *   issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
279      *   notBefore: 061110000000Z
280      *   notAfter: 311110000000Z
281      *   subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
282      *   subject public key info: 
283      *     key algorithm: RSA
284      *     n=c6cce573e6fbd4bb...
285      *     e=10001
286      * X509v3 Extensions:
287      *   keyUsage CRITICAL:
288      *     digitalSignature,keyCertSign,cRLSign
289      *   basicConstraints CRITICAL:
290      *     cA=true
291      *   subjectKeyIdentifier :
292      *     b13ec36903f8bf4701d498261a0802ef63642bc3
293      *   authorityKeyIdentifier :
294      *     kid=b13ec36903f8bf4701d498261a0802ef63642bc3
295      * signature algorithm: SHA1withRSA
296      * signature: 1c1a0697dcd79c9f...
297      */
298     this.getInfo = function() {
299 	var s = "Basic Fields\n";
300         s += "  serial number: " + this.getSerialNumberHex() + "\n";
301 	s += "  signature algorithm: " + this.getSignatureAlgorithmField() + "\n";
302 	s += "  issuer: " + this.getIssuerString() + "\n";
303 	s += "  notBefore: " + this.getNotBefore() + "\n";
304 	s += "  notAfter: " + this.getNotAfter() + "\n";
305 	s += "  subject: " + this.getSubjectString() + "\n";
306 	s += "  subject public key info: " + "\n";
307 
308 	// subject public key info
309 	var pSPKI = X509.getSubjectPublicKeyInfoPosFromCertHex(this.hex);
310 	var hSPKI = ASN1HEX.getHexOfTLV_AtObj(this.hex, pSPKI);
311 	var keyObj = KEYUTIL.getKey(hSPKI, null, "pkcs8pub");
312 	//s += "    " + JSON.stringify(keyObj) + "\n";
313 	if (keyObj instanceof RSAKey) {
314 	    s += "    key algorithm: RSA\n";
315 	    s += "    n=" + keyObj.n.toString(16).substr(0, 16) + "...\n";
316 	    s += "    e=" + keyObj.e.toString(16) + "\n";
317 	}
318 
319         s += "X509v3 Extensions:\n";
320 
321 	var aExt = X509.getV3ExtInfoListOfCertHex(this.hex);
322         for (var i = 0; i < aExt.length; i++) {
323 	    var info = aExt[i];
324 
325 	    // show extension name and critical flag
326 	    var extName = KJUR.asn1.x509.OID.oid2name(info["oid"]);
327 	    if (extName === '') extName = info["oid"];
328 
329 	    var critical = '';
330 	    if (info["critical"] === true) critical = "CRITICAL";
331 
332 	    s += "  " + extName + " " + critical + ":\n";
333 
334 	    // show extension value if supported
335 	    if (extName === "basicConstraints") {
336 		var bc = X509.getExtBasicConstraints(this.hex);
337 		if (bc.cA === undefined) {
338 		    s += "    {}\n";
339 		} else {
340 		    s += "    cA=true";
341 		    if (bc.pathLen !== undefined) 
342 			s += ", pathLen=" + bc.pathLen;
343 		    s += "\n";
344 		}
345 	    } else if (extName === "keyUsage") {
346 		s += "    " + X509.getExtKeyUsageString(this.hex) + "\n";
347 	    } else if (extName === "subjectKeyIdentifier") {
348 		s += "    " + X509.getExtSubjectKeyIdentifier(this.hex) + "\n";
349 	    } else if (extName === "authorityKeyIdentifier") {
350 		var akid = X509.getExtAuthorityKeyIdentifier(this.hex);
351 		if (akid.kid !== undefined)
352 		    s += "    kid=" + akid.kid + "\n";
353 	    } else if (extName === "extKeyUsage") {
354 		var eku = X509.getExtExtKeyUsageName(this.hex);
355 		s += "    " + eku.join(", ") + "\n";
356 	    } else if (extName === "subjectAltName") {
357 		var san = X509.getExtSubjectAltName(this.hex);
358 		s += "    " + san.join(", ") + "\n";
359 	    } else if (extName === "cRLDistributionPoints") {
360 		var cdp = X509.getExtCRLDistributionPointsURI(this.hex);
361 		s += "    " + cdp + "\n";
362 	    } else if (extName === "authorityInfoAccess") {
363 		var aia = X509.getExtAIAInfo(this.hex);
364 		if (aia.ocsp !== undefined)
365 		    s += "    ocsp: " + aia.ocsp.join(",") + "\n";
366 		if (aia.caissuer !== undefined)
367 		    s += "    caissuer: " + aia.caissuer.join(",") + "\n";
368 	    }
369         }
370 
371 	s += "signature algorithm: " + X509.getSignatureAlgorithmName(this.hex) + "\n";
372 	s += "signature: " + X509.getSignatureValueHex(this.hex).substr(0, 16) + "...\n";
373 	return s;
374     };
375 };
376 
377 /**
378  * get Base64 string from PEM certificate string
379  * @name pemToBase64
380  * @memberOf X509
381  * @function
382  * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
383  * @return {String} Base64 string of PEM certificate
384  * @example
385  * b64 = X509.pemToBase64(certPEM);
386  */
387 X509.pemToBase64 = function(sCertPEM) {
388     var s = sCertPEM;
389     s = s.replace("-----BEGIN CERTIFICATE-----", "");
390     s = s.replace("-----END CERTIFICATE-----", "");
391     s = s.replace(/[ \n]+/g, "");
392     return s;
393 };
394 
395 /**
396  * get a hexa decimal string from PEM certificate string
397  * @name pemToHex
398  * @memberOf X509
399  * @function
400  * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
401  * @return {String} hexadecimal string of PEM certificate
402  * @example
403  * hex = X509.pemToHex(certPEM);
404  */
405 X509.pemToHex = function(sCertPEM) {
406     var b64Cert = X509.pemToBase64(sCertPEM);
407     var hCert = b64tohex(b64Cert);
408     return hCert;
409 };
410 
411 // NOTE: Without BITSTRING encapsulation.
412 X509.getSubjectPublicKeyPosFromCertHex = function(hCert) {
413     var pInfo = X509.getSubjectPublicKeyInfoPosFromCertHex(hCert);
414     if (pInfo == -1) return -1;    
415     var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 
416     if (a.length != 2) return -1;
417     var pBitString = a[1];
418     if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
419     var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
420     
421     if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
422     return pBitStringV + 2;
423 };
424 
425 // NOTE: privateKeyUsagePeriod field of X509v2 not supported.
426 // NOTE: v1 and v3 supported
427 X509.getSubjectPublicKeyInfoPosFromCertHex = function(hCert) {
428     var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
429     var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 
430     if (a.length < 1) return -1;
431     if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
432         if (a.length < 6) return -1;
433         return a[6];
434     } else {
435         if (a.length < 5) return -1;
436         return a[5];
437     }
438 };
439 
440 X509.getPublicKeyHexArrayFromCertHex = function(hCert) {
441     var p = X509.getSubjectPublicKeyPosFromCertHex(hCert);
442     var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 
443     if (a.length != 2) return [];
444     var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
445     var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
446     if (hN != null && hE != null) {
447         return [hN, hE];
448     } else {
449         return [];
450     }
451 };
452 
453 X509.getHexTbsCertificateFromCert = function(hCert) {
454     var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
455     return pTbsCert;
456 };
457 
458 X509.getPublicKeyHexArrayFromCertPEM = function(sCertPEM) {
459     var hCert = X509.pemToHex(sCertPEM);
460     var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
461     return a;
462 };
463 
464 X509.hex2dn = function(hDN) {
465     var s = "";
466     var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
467     for (var i = 0; i < a.length; i++) {
468         var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
469         s = s + "/" + X509.hex2rdn(hRDN);
470     }
471     return s;
472 };
473 
474 X509.hex2rdn = function(hRDN) {
475     var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
476     var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
477     var type = "";
478     try { type = X509.DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
479     hValue = hValue.replace(/(..)/g, "%$1");
480     var value = decodeURIComponent(hValue);
481     return type + "=" + value;
482 };
483 
484 X509.DN_ATTRHEX = {
485     "0603550406": "C",
486     "060355040a": "O",
487     "060355040b": "OU",
488     "0603550403": "CN",
489     "0603550405": "SN",
490     "0603550408": "ST",
491     "0603550407": "L",
492     "0603550409": "streetAddress",
493     "060355040f": "businessCategory",
494     "0603550411": "postalCode",
495     "060b2b0601040182373c020102": "jurisdictionOfIncorporationSP",
496     "060b2b0601040182373c020103": "jurisdictionOfIncorporationC",
497 };
498 
499 /**
500  * get RSAKey/ECDSA public key object from PEM certificate string
501  * @name getPublicKeyFromCertPEM
502  * @memberOf X509
503  * @function
504  * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
505  * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
506  * @since x509 1.1.1
507  * @description
508  * NOTE: DSA is also supported since x509 1.1.2.
509  */
510 X509.getPublicKeyFromCertPEM = function(sCertPEM) {
511     var info = X509.getPublicKeyInfoPropOfCertPEM(sCertPEM);
512 
513     if (info.algoid == "2a864886f70d010101") { // RSA
514         var aRSA = KEYUTIL.parsePublicRawRSAKeyHex(info.keyhex);
515         var key = new RSAKey();
516         key.setPublic(aRSA.n, aRSA.e);
517         return key;
518     } else if (info.algoid == "2a8648ce3d0201") { // ECC
519         var curveName = KJUR.crypto.OID.oidhex2name[info.algparam];
520         var key = new KJUR.crypto.ECDSA({'curve': curveName, 'info': info.keyhex});
521         key.setPublicKeyHex(info.keyhex);
522         return key;
523     } else if (info.algoid == "2a8648ce380401") { // DSA 1.2.840.10040.4.1
524         var p = ASN1HEX.getVbyList(info.algparam, 0, [0], "02");
525         var q = ASN1HEX.getVbyList(info.algparam, 0, [1], "02");
526         var g = ASN1HEX.getVbyList(info.algparam, 0, [2], "02");
527         var y = ASN1HEX.getHexOfV_AtObj(info.keyhex, 0);
528         y = y.substr(2);
529         var key = new KJUR.crypto.DSA();
530         key.setPublic(new BigInteger(p, 16),
531                       new BigInteger(q, 16),
532                       new BigInteger(g, 16),
533                       new BigInteger(y, 16));
534         return key;
535     } else {
536         throw "unsupported key";
537     }
538 };
539 
540 /**
541  * get public key information from PEM certificate
542  * @name getPublicKeyInfoPropOfCertPEM
543  * @memberOf X509
544  * @function
545  * @param {String} sCertPEM string of PEM formatted certificate
546  * @return {Hash} hash of information for public key
547  * @since x509 1.1.1
548  * @description
549  * Resulted associative array has following properties:<br/>
550  * <ul>
551  * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li>
552  * <li>algparam - hexadecimal string of OID of ECC curve name or null</li>
553  * <li>keyhex - hexadecimal string of key in the certificate</li>
554  * </ul>
555  * NOTE: X509v1 certificate is also supported since x509.js 1.1.9.
556  */
557 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
558     var result = {};
559     result.algparam = null;
560     var hCert = X509.pemToHex(sCertPEM);
561 
562     // 1. Certificate ASN.1
563     var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
564     if (a1.length != 3)
565         throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
566 
567     // 2. tbsCertificate
568     if (hCert.substr(a1[0], 2) != "30")
569         throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
570 
571     var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
572 
573     // 3. subjectPublicKeyInfo
574     var idx_spi = 6; // subjectPublicKeyInfo index in tbsCert for v3 cert
575     if (hCert.substr(a2[0], 2) !== "a0") idx_spi = 5;
576 
577     if (a2.length < idx_spi + 1)
578         throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
579 
580     var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[idx_spi]); 
581 
582     if (a3.length != 2)
583         throw "malformed X.509 certificate PEM (code:004)"; // not AlgId and PubKey
584 
585     // 4. AlgId
586     var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]); 
587 
588     if (a4.length != 2)
589         throw "malformed X.509 certificate PEM (code:005)"; // not 2 item in AlgId
590 
591     result.algoid = ASN1HEX.getHexOfV_AtObj(hCert, a4[0]);
592 
593     if (hCert.substr(a4[1], 2) == "06") { // EC
594         result.algparam = ASN1HEX.getHexOfV_AtObj(hCert, a4[1]);
595     } else if (hCert.substr(a4[1], 2) == "30") { // DSA
596         result.algparam = ASN1HEX.getHexOfTLV_AtObj(hCert, a4[1]);
597     }
598 
599     // 5. Public Key Hex
600     if (hCert.substr(a3[1], 2) != "03")
601         throw "malformed X.509 certificate PEM (code:006)"; // not bitstring
602 
603     var unusedBitAndKeyHex = ASN1HEX.getHexOfV_AtObj(hCert, a3[1]);
604     result.keyhex = unusedBitAndKeyHex.substr(2);
605 
606     return result;
607 };
608 
609 /**
610  * get position of subjectPublicKeyInfo field from HEX certificate
611  * @name getPublicKeyInfoPosOfCertHEX
612  * @memberOf X509
613  * @function
614  * @param {String} hCert hexadecimal string of certificate
615  * @return {Integer} position in hexadecimal string
616  * @since x509 1.1.4
617  * @description
618  * get position for SubjectPublicKeyInfo field in the hexadecimal string of
619  * certificate.
620  */
621 X509.getPublicKeyInfoPosOfCertHEX = function(hCert) {
622     // 1. Certificate ASN.1
623     var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
624     if (a1.length != 3)
625         throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
626 
627     // 2. tbsCertificate
628     if (hCert.substr(a1[0], 2) != "30")
629         throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
630 
631     var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
632 
633     // 3. subjectPublicKeyInfo
634     if (a2.length < 7)
635         throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
636     
637     return a2[6];
638 };
639 
640 /**
641  * get array of X.509 V3 extension value information in hex string of certificate
642  * @name getV3ExtInfoListOfCertHex
643  * @memberOf X509
644  * @function
645  * @param {String} hCert hexadecimal string of X.509 certificate binary
646  * @return {Array} array of result object by {@link X509.getV3ExtInfoListOfCertHex}
647  * @since x509 1.1.5
648  * @description
649  * This method will get all extension information of a X.509 certificate.
650  * Items of resulting array has following properties:
651  * <ul>
652  * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
653  * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
654  * <li>critical - critical flag value for this extension</li>
655  * <li>posV - index of ASN.1 TLV for the extension value.
656  * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
657  * </ul>
658  * @example
659  * hCert = X509.pemToHex(certGithubPEM);
660  * a = X509.getV3ExtInfoListOfCertHex(hCert);
661  * // Then a will be an array of like following:
662  * [{posTLV: 1952, oid: "2.5.29.35", critical: false, posV: 1968},
663  *  {posTLV: 1974, oid: "2.5.29.19", critical: true, posV: 1986}, ...]
664  */
665 X509.getV3ExtInfoListOfCertHex = function(hCert) {
666     // 1. Certificate ASN.1
667     var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
668     if (a1.length != 3)
669         throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
670 
671     // 2. tbsCertificate
672     if (hCert.substr(a1[0], 2) != "30")
673         throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 
674 
675     var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 
676 
677     // 3. v3Extension EXPLICIT Tag [3]
678     // ver, seri, alg, iss, validity, subj, spki, (iui,) (sui,) ext
679     if (a2.length < 8)
680         throw "malformed X.509 certificate PEM (code:003)"; // tbsCert num field too short
681 
682     if (hCert.substr(a2[7], 2) != "a3")
683         throw "malformed X.509 certificate PEM (code:004)"; // not [3] tag
684 
685     var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[7]);
686     if (a3.length != 1)
687         throw "malformed X.509 certificate PEM (code:005)"; // [3]tag numChild!=1
688 
689     // 4. v3Extension SEQUENCE
690     if (hCert.substr(a3[0], 2) != "30")
691         throw "malformed X.509 certificate PEM (code:006)"; // not SEQ
692 
693     var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]);
694 
695     // 5. v3Extension item position
696     var numExt = a4.length;
697     var aInfo = new Array(numExt);
698     for (var i = 0; i < numExt; i++) {
699 	aInfo[i] = X509.getV3ExtItemInfo_AtObj(hCert, a4[i]);
700     }
701     return aInfo;
702 };
703 
704 /**
705  * get X.509 V3 extension value information at the specified position
706  * @name getV3ExtItemInfo_AtObj
707  * @memberOf X509
708  * @function
709  * @param {String} hCert hexadecimal string of X.509 certificate binary
710  * @param {Integer} pos index of hexadecimal string for the extension
711  * @return {Object} properties for the extension
712  * @since x509 1.1.5
713  * @description
714  * This method will get some information of a X.509 V extension 
715  * which is referred by an index of hexadecimal string of X.509 
716  * certificate. 
717  * Resulting object has following properties:
718  * <ul>
719  * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
720  * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
721  * <li>critical - critical flag value for this extension</li>
722  * <li>posV - index of ASN.1 TLV for the extension value.
723  * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
724  * </ul>
725  * This method is used by {@link X509.getV3ExtInfoListOfCertHex} internally.
726  */
727 X509.getV3ExtItemInfo_AtObj = function(hCert, pos) {
728     var info = {};
729 
730     // posTLV - extension TLV
731     info.posTLV = pos;
732 
733     var a  = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos);
734     if (a.length != 2 && a.length != 3)
735         throw "malformed X.509v3 Ext (code:001)"; // oid,(critical,)val
736 
737     // oid - extension OID
738     if (hCert.substr(a[0], 2) != "06")
739         throw "malformed X.509v3 Ext (code:002)"; // not OID "06"
740     var valueHex = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
741     info.oid = ASN1HEX.hextooidstr(valueHex); 
742 
743     // critical - extension critical flag
744     info.critical = false; // critical false by default
745     if (a.length == 3) info.critical = true;
746 
747     // posV - content TLV position of encapsulated
748     //        octet string of V3 extension value.
749     var posExtV = a[a.length - 1];
750     if (hCert.substr(posExtV, 2) != "04")
751         throw "malformed X.509v3 Ext (code:003)"; // not EncapOctet "04"
752     info.posV = ASN1HEX.getStartPosOfV_AtObj(hCert, posExtV);
753     
754     return info;
755 };
756 
757 /**
758  * get X.509 V3 extension value ASN.1 TLV for specified oid or name
759  * @name getHexOfTLV_V3ExtValue
760  * @memberOf X509
761  * @function
762  * @param {String} hCert hexadecimal string of X.509 certificate binary
763  * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
764  * @return {String} hexadecimal string of extension ASN.1 TLV
765  * @since x509 1.1.6
766  * @description
767  * This method will get X.509v3 extension value of ASN.1 TLV
768  * which is specifyed by extension name or oid. 
769  * If there is no such extension in the certificate, it returns null.
770  * @example
771  * hExtValue = X509.getHexOfTLV_V3ExtValue(hCert, "keyUsage");
772  * // hExtValue will be such like '030205a0'.
773  */
774 X509.getHexOfTLV_V3ExtValue = function(hCert, oidOrName) {
775     var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
776     if (pos == -1) return null;
777     return ASN1HEX.getHexOfTLV_AtObj(hCert, pos);
778 };
779 
780 /**
781  * get X.509 V3 extension value ASN.1 V for specified oid or name
782  * @name getHexOfV_V3ExtValue
783  * @memberOf X509
784  * @function
785  * @param {String} hCert hexadecimal string of X.509 certificate binary
786  * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
787  * @return {String} hexadecimal string of extension ASN.1 TLV
788  * @since x509 1.1.6
789  * @description
790  * This method will get X.509v3 extension value of ASN.1 value
791  * which is specifyed by extension name or oid. 
792  * If there is no such extension in the certificate, it returns null.
793  * Available extension names and oids are defined
794  * in the {@link KJUR.asn1.x509.OID} class.
795  * @example
796  * hExtValue = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
797  * // hExtValue will be such like '05a0'.
798  */
799 X509.getHexOfV_V3ExtValue = function(hCert, oidOrName) {
800     var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
801     if (pos == -1) return null;
802     return ASN1HEX.getHexOfV_AtObj(hCert, pos);
803 };
804 
805 /**
806  * get index in the certificate hexa string for specified oid or name specified extension
807  * @name getPosOfTLV_V3ExtValue
808  * @memberOf X509
809  * @function
810  * @param {String} hCert hexadecimal string of X.509 certificate binary
811  * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
812  * @return {Integer} index in the hexadecimal string of certficate for specified extension
813  * @since x509 1.1.6
814  * @description
815  * This method will get X.509v3 extension value of ASN.1 V(value)
816  * which is specifyed by extension name or oid. 
817  * If there is no such extension in the certificate,
818  * it returns -1.
819  * Available extension names and oids are defined
820  * in the {@link KJUR.asn1.x509.OID} class.
821  * @example
822  * idx = X509.getPosOfV_V3ExtValue(hCert, "keyUsage");
823  * // The 'idx' will be index in the string for keyUsage value ASN.1 TLV.
824  */
825 X509.getPosOfTLV_V3ExtValue = function(hCert, oidOrName) {
826     var oid = oidOrName;
827     if (! oidOrName.match(/^[0-9.]+$/)) oid = KJUR.asn1.x509.OID.name2oid(oidOrName);
828     if (oid == '') return -1;
829 
830     var infoList = X509.getV3ExtInfoListOfCertHex(hCert);
831     for (var i = 0; i < infoList.length; i++) {
832 	var info = infoList[i];
833 	if (info.oid == oid) return info.posV;
834     }
835     return -1;
836 };
837 
838 /* ======================================================================
839  *   Specific V3 Extensions
840  * ====================================================================== */
841 
842 /**
843  * get BasicConstraints extension value as object in the certificate
844  * @name getExtBasicConstraints
845  * @memberOf X509
846  * @function
847  * @param {String} hCert hexadecimal string of X.509 certificate binary
848  * @return {Object} associative array which may have "cA" and "pathLen" parameters
849  * @since x509 1.1.7
850  * @description
851  * This method will get basic constraints extension value as object with following paramters.
852  * <ul>
853  * <li>cA - CA flag whether CA or not</li>
854  * <li>pathLen - maximum intermediate certificate length</li>
855  * </ul>
856  * There are use cases for return values:
857  * <ul>
858  * <li>{cA:true, pathLen:3} - cA flag is true and pathLen is 3</li>
859  * <li>{cA:true} - cA flag is true and no pathLen</li>
860  * <li>{} - basic constraints has no value in case of end entity certificate</li>
861  * <li>null - there is no basic constraints extension</li>
862  * </ul>
863  * @example
864  * obj = X509.getExtBasicConstraints(hCert);
865  */
866 X509.getExtBasicConstraints = function(hCert) {
867     var hBC = X509.getHexOfV_V3ExtValue(hCert, "basicConstraints");
868     if (hBC === null) return null;
869     if (hBC === '') return {};
870     if (hBC === '0101ff') return { "cA": true };
871     if (hBC.substr(0, 8) === '0101ff02') {
872 	var pathLexHex = ASN1HEX.getHexOfV_AtObj(hBC, 6);
873 	var pathLen = parseInt(pathLexHex, 16);
874 	return { "cA": true, "pathLen": pathLen };
875     }
876     throw "unknown error";
877 };
878 
879 X509.KEYUSAGE_NAME = [
880     "digitalSignature",
881     "nonRepudiation",
882     "keyEncipherment",
883     "dataEncipherment",
884     "keyAgreement",
885     "keyCertSign",
886     "cRLSign",
887     "encipherOnly",
888     "decipherOnly"
889 ];
890 
891 /**
892  * get KeyUsage extension value as binary string in the certificate
893  * @name getExtKeyUsageBin
894  * @memberOf X509
895  * @function
896  * @param {String} hCert hexadecimal string of X.509 certificate binary
897  * @return {String} binary string of key usage bits (ex. '101')
898  * @since x509 1.1.6
899  * @description
900  * This method will get key usage extension value
901  * as binary string such like '101'.
902  * Key usage bits definition is in the RFC 5280.
903  * If there is no key usage extension in the certificate,
904  * it returns empty string (i.e. '').
905  * @example
906  * bKeyUsage = X509.getExtKeyUsageBin(hCert);
907  * // bKeyUsage will be such like '101'.
908  * // 1 - digitalSignature 
909  * // 0 - nonRepudiation
910  * // 1 - keyEncipherment
911  */
912 X509.getExtKeyUsageBin = function(hCert) {
913     var hKeyUsage = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
914     if (hKeyUsage == '') return '';
915     if (hKeyUsage.length % 2 != 0 || hKeyUsage.length <= 2)
916 	throw "malformed key usage value";
917     var unusedBits = parseInt(hKeyUsage.substr(0, 2));
918     var bKeyUsage = parseInt(hKeyUsage.substr(2), 16).toString(2);
919     return bKeyUsage.substr(0, bKeyUsage.length - unusedBits);
920 };
921 
922 /**
923  * get KeyUsage extension value as names in the certificate
924  * @name getExtKeyUsageString
925  * @memberOf X509
926  * @function
927  * @param {String} hCert hexadecimal string of X.509 certificate binary
928  * @return {String} comma separated string of key usage
929  * @since x509 1.1.6
930  * @description
931  * This method will get key usage extension value
932  * as comma separated string of usage names.
933  * If there is no key usage extension in the certificate,
934  * it returns empty string (i.e. '').
935  * @example
936  * sKeyUsage = X509.getExtKeyUsageString(hCert);
937  * // sKeyUsage will be such like 'digitalSignature,keyEncipherment'.
938  */
939 X509.getExtKeyUsageString = function(hCert) {
940     var bKeyUsage = X509.getExtKeyUsageBin(hCert);
941     var a = new Array();
942     for (var i = 0; i < bKeyUsage.length; i++) {
943 	if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]);
944     }
945     return a.join(",");
946 };
947 
948 /**
949  * get subjectKeyIdentifier value as hexadecimal string in the certificate
950  * @name getExtSubjectKeyIdentifier
951  * @memberOf X509
952  * @function
953  * @param {String} hCert hexadecimal string of X.509 certificate binary
954  * @return {String} hexadecimal string of subject key identifier or null
955  * @since jsrsasign 5.0.10 x509 1.1.8
956  * @description
957  * This method will get subject key identifier extension value
958  * as hexadecimal string.
959  * If there is no its extension in the certificate,
960  * it returns null.
961  * @example
962  * skid = X509.getExtSubjectKeyIdentifier(hCert);
963  */
964 X509.getExtSubjectKeyIdentifier = function(hCert) {
965     var hSKID = X509.getHexOfV_V3ExtValue(hCert, "subjectKeyIdentifier");
966     return hSKID;
967 };
968 
969 /**
970  * get authorityKeyIdentifier value as JSON object in the certificate
971  * @name getExtAuthorityKeyIdentifier
972  * @memberOf X509
973  * @function
974  * @param {String} hCert hexadecimal string of X.509 certificate binary
975  * @return {Object} JSON object of authority key identifier or null
976  * @since jsrsasign 5.0.10 x509 1.1.8
977  * @description
978  * This method will get authority key identifier extension value
979  * as JSON object.
980  * If there is no its extension in the certificate,
981  * it returns null.
982  * <br>
983  * NOTE: Currently this method only supports keyIdentifier so that
984  * authorityCertIssuer and authorityCertSerialNumber will not
985  * be return in the JSON object.
986  * @example
987  * akid = X509.getExtAuthorityKeyIdentifier(hCert);
988  * // returns following JSON object
989  * { kid: "1234abcd..." }
990  */
991 X509.getExtAuthorityKeyIdentifier = function(hCert) {
992     var result = {};
993     var hAKID = X509.getHexOfTLV_V3ExtValue(hCert, "authorityKeyIdentifier");
994     if (hAKID === null) return null;
995 
996     var a = ASN1HEX.getPosArrayOfChildren_AtObj(hAKID, 0); 
997     for (var i = 0; i < a.length; i++) {
998 	if (hAKID.substr(a[i], 2) === "80")
999 	    result.kid = ASN1HEX.getHexOfV_AtObj(hAKID, a[i]);
1000     }
1001     
1002     return result;
1003 };
1004 
1005 /**
1006  * get extKeyUsage value as array of name string in the certificate
1007  * @name getExtExtKeyUsageName
1008  * @memberOf X509
1009  * @function
1010  * @param {String} hCert hexadecimal string of X.509 certificate binary
1011  * @return {Object} array of extended key usage ID name or oid
1012  * @since jsrsasign 5.0.10 x509 1.1.8
1013  * @description
1014  * This method will get extended key usage extension value
1015  * as array of name or OID string.
1016  * If there is no its extension in the certificate,
1017  * it returns null.
1018  * <br>
1019  * NOTE: Supported extended key usage ID names are defined in
1020  * name2oidList parameter in asn1x509.js file.
1021  * @example
1022  * eku = X509.getExtExtKeyUsageName(hCert);
1023  * // returns following array:
1024  * ["serverAuth", "clientAuth", "0.1.2.3.4.5"]
1025  */
1026 X509.getExtExtKeyUsageName = function(hCert) {
1027     var result = new Array();
1028     var h = X509.getHexOfTLV_V3ExtValue(hCert, "extKeyUsage");
1029     if (h === null) return null;
1030 
1031     var a = ASN1HEX.getPosArrayOfChildren_AtObj(h, 0); 
1032     for (var i = 0; i < a.length; i++) {
1033 	var hex = ASN1HEX.getHexOfV_AtObj(h, a[i]);
1034 	var oid = KJUR.asn1.ASN1Util.oidHexToInt(hex);
1035 	var name = KJUR.asn1.x509.OID.oid2name(oid);
1036 	result.push(name);
1037     }
1038     
1039     return result;
1040 };
1041 
1042 /**
1043  * get subjectAltName value as array of string in the certificate
1044  * @name getExtSubjectAltName
1045  * @memberOf X509
1046  * @function
1047  * @param {String} hCert hexadecimal string of X.509 certificate binary
1048  * @return {Object} array of alt names
1049  * @since jsrsasign 5.0.10 x509 1.1.8
1050  * @description
1051  * This method will get subject alt name extension value
1052  * as array of name.
1053  * If there is no its extension in the certificate,
1054  * it returns null.
1055  * <br>
1056  * NOTE: Currently this method supports only dNSName so that
1057  * other name type such like iPAddress or generalName will not be returned.
1058  * @example
1059  * san = X509.getExtSubjectAltName(hCert);
1060  * // returns following array:
1061  * ["example.com", "example.org"]
1062  */
1063 X509.getExtSubjectAltName = function(hCert) {
1064     var result = new Array();
1065     var h = X509.getHexOfTLV_V3ExtValue(hCert, "subjectAltName");
1066     
1067     var a = ASN1HEX.getPosArrayOfChildren_AtObj(h, 0); 
1068     for (var i = 0; i < a.length; i++) {
1069 	if (h.substr(a[i], 2) === "82") {
1070 	    var fqdn = hextoutf8(ASN1HEX.getHexOfV_AtObj(h, a[i]));
1071 	    result.push(fqdn);
1072 	}
1073     }
1074 
1075     return result;
1076 };
1077 
1078 /**
1079  * get array of string for fullName URIs in cRLDistributionPoints(CDP) in the certificate
1080  * @name getExtCRLDistributionPointsURI
1081  * @memberOf X509
1082  * @function
1083  * @param {String} hCert hexadecimal string of X.509 certificate binary
1084  * @return {Object} array of fullName URIs of CDP of the certificate
1085  * @since jsrsasign 5.0.10 x509 1.1.8
1086  * @description
1087  * This method will get all fullName URIs of cRLDistributionPoints extension
1088  * in the certificate as array of URI string.
1089  * If there is no its extension in the certificate,
1090  * it returns null.
1091  * <br>
1092  * NOTE: Currently this method supports only fullName URI so that
1093  * other parameters will not be returned.
1094  * @example
1095  * cdpuri = X509.getExtCRLDistributionPointsURI(hCert);
1096  * // returns following array:
1097  * ["http://example.com/aaa.crl", "http://example.org/aaa.crl"]
1098  */
1099 X509.getExtCRLDistributionPointsURI = function(hCert) {
1100     var result = new Array();
1101     var h = X509.getHexOfTLV_V3ExtValue(hCert, "cRLDistributionPoints");
1102 
1103     var a = ASN1HEX.getPosArrayOfChildren_AtObj(h, 0); 
1104     for (var i = 0; i < a.length; i++) {
1105 	var hDP = ASN1HEX.getHexOfTLV_AtObj(h, a[i]);
1106 
1107 	var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hDP, 0); 
1108 	for (var j = 0; j < a1.length; j++) {
1109 	    if (hDP.substr(a1[j], 2) === "a0") {
1110 		var hDPN = ASN1HEX.getHexOfV_AtObj(hDP, a1[j]);
1111 		if (hDPN.substr(0, 2) === "a0") {
1112 		    var hFullName = ASN1HEX.getHexOfV_AtObj(hDPN, 0);
1113 		    if (hFullName.substr(0, 2) === "86") {
1114 			var hURI = ASN1HEX.getHexOfV_AtObj(hFullName, 0);
1115 			var uri = hextoutf8(hURI);
1116 			result.push(uri);
1117 		    }
1118 		}
1119 	    }
1120 	}
1121     }
1122 
1123     return result;
1124 };
1125 
1126 /**
1127  * get AuthorityInfoAccess extension value in the certificate as associative array
1128  * @name getExtAIAInfo
1129  * @memberOf X509
1130  * @function
1131  * @param {String} hCert hexadecimal string of X.509 certificate binary
1132  * @return {Object} associative array of AIA extension properties
1133  * @since x509 1.1.6
1134  * @description
1135  * This method will get authority info access value
1136  * as associate array which has following properties:
1137  * <ul>
1138  * <li>ocsp - array of string for OCSP responder URL</li>
1139  * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li>
1140  * </ul>
1141  * If there is no key usage extension in the certificate,
1142  * it returns null;
1143  * @example
1144  * oAIA = X509.getExtAIAInfo(hCert);
1145  * // result will be such like:
1146  * // oAIA.ocsp = ["http://ocsp.foo.com"];
1147  * // oAIA.caissuer = ["http://rep.foo.com/aaa.p8m"];
1148  */
1149 X509.getExtAIAInfo = function(hCert) {
1150     var result = {};
1151     result.ocsp = [];
1152     result.caissuer = [];
1153     var pos1 = X509.getPosOfTLV_V3ExtValue(hCert, "authorityInfoAccess");
1154     if (pos1 == -1) return null;
1155     if (hCert.substr(pos1, 2) != "30") // extnValue SEQUENCE
1156 	throw "malformed AIA Extn Value";
1157     
1158     var posAccDescList = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos1);
1159     for (var i = 0; i < posAccDescList.length; i++) {
1160 	var p = posAccDescList[i];
1161 	var posAccDescChild = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
1162 	if (posAccDescChild.length != 2)
1163 	    throw "malformed AccessDescription of AIA Extn";
1164 	var pOID = posAccDescChild[0];
1165 	var pName = posAccDescChild[1];
1166 	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073001") {
1167 	    if (hCert.substr(pName, 2) == "86") {
1168 		result.ocsp.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
1169 	    }
1170 	}
1171 	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073002") {
1172 	    if (hCert.substr(pName, 2) == "86") {
1173 		result.caissuer.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
1174 	    }
1175 	}
1176     }
1177     return result;
1178 };
1179 
1180 /**
1181  * get signature algorithm name from hexadecimal certificate data
1182  * @name getSignatureAlgorithmName
1183  * @memberOf X509
1184  * @function
1185  * @param {String} hCert hexadecimal string of X.509 certificate binary
1186  * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA)
1187  * @since x509 1.1.7
1188  * @description
1189  * This method will get signature algorithm name of certificate:
1190  * @example
1191  * algName = X509.getSignatureAlgorithmName(hCert);
1192  */
1193 X509.getSignatureAlgorithmName = function(hCert) {
1194     var sigAlgOidHex = ASN1HEX.getDecendantHexVByNthList(hCert, 0, [1, 0]);
1195     var sigAlgOidInt = KJUR.asn1.ASN1Util.oidHexToInt(sigAlgOidHex);
1196     var sigAlgName = KJUR.asn1.x509.OID.oid2name(sigAlgOidInt);
1197     return sigAlgName;
1198 };
1199 
1200 /**
1201  * get signature value in hexadecimal string
1202  * @name getSignatureValueHex
1203  * @memberOf X509
1204  * @function
1205  * @param {String} hCert hexadecimal string of X.509 certificate binary
1206  * @return {String} signature value hexadecimal string without BitString unused bits
1207  * @since x509 1.1.7
1208  * @description
1209  * This method will get signature value of certificate:
1210  * @example
1211  * sigHex = X509.getSignatureValueHex(hCert);
1212  */
1213 X509.getSignatureValueHex = function(hCert) {
1214     var h = ASN1HEX.getDecendantHexVByNthList(hCert, 0, [2]);
1215     if (h.substr(0, 2) !== "00")
1216 	throw "can't get signature value";
1217     return h.substr(2);
1218 };
1219 
1220 X509.getSerialNumberHex = function(hCert) {
1221     return ASN1HEX.getDecendantHexVByNthList(hCert, 0, [0, 1]);
1222 };
1223 
1224 /*
1225   X509.prototype.readCertPEM = _x509_readCertPEM;
1226   X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
1227   X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
1228   X509.prototype.getIssuerHex = _x509_getIssuerHex;
1229   X509.prototype.getSubjectHex = _x509_getSubjectHex;
1230   X509.prototype.getIssuerString = _x509_getIssuerString;
1231   X509.prototype.getSubjectString = _x509_getSubjectString;
1232   X509.prototype.getNotBefore = _x509_getNotBefore;
1233   X509.prototype.getNotAfter = _x509_getNotAfter;
1234 */
1235