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