1 /* x509-1.1.20.js (c) 2012-2018 Kenji Urushima | kjur.github.io/jsrsasign/license 2 */ 3 /* 4 * x509.js - X509 class to read subject public key from certificate. 5 * 6 * Copyright (c) 2010-2018 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * https://kjur.github.io/jsrsasign/license 10 * 11 * The above copyright and license notice shall be 12 * included in all copies or substantial portions of the Software. 13 */ 14 15 /** 16 * @fileOverview 17 * @name x509-1.1.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version jsrsasign 8.0.10 x509 1.1.20 (2018-Apr-09) 20 * @since jsrsasign 1.x.x 21 * @license <a href="https://kjur.github.io/jsrsasign/license/">MIT License</a> 22 */ 23 24 /** 25 * hexadecimal X.509 certificate ASN.1 parser class.<br/> 26 * @class hexadecimal X.509 certificate ASN.1 parser class 27 * @property {String} hex hexacedimal string for X.509 certificate. 28 * @property {Number} version format version (1: X509v1, 3: X509v3, otherwise: unknown) since jsrsasign 7.1.4 29 * @author Kenji Urushima 30 * @version 1.0.1 (08 May 2012) 31 * @see <a href="https://kjur.github.io/jsrsasigns/">'jsrsasign'(RSA Sign JavaScript Library) home page https://kjur.github.io/jsrsasign/</a> 32 * @description 33 * X509 class provides following functionality: 34 * <ul> 35 * <li>parse X.509 certificate ASN.1 structure</li> 36 * <li>get basic fields, extensions, signature algorithms and signature values</li> 37 * <li>read PEM certificate</li> 38 * </ul> 39 * 40 * <ul> 41 * <li><b>TO GET FIELDS</b> 42 * <ul> 43 * <li>serial - {@link X509#getSerialNumberHex}</li> 44 * <li>signature algorithm field - {@link X509#getSignatureAlgorithmField}</li> 45 * <li>issuer - {@link X509#getIssuerHex}</li> 46 * <li>issuer - {@link X509#getIssuerString}</li> 47 * <li>notBefore - {@link X509#getNotBefore}</li> 48 * <li>notAfter - {@link X509#getNotAfter}</li> 49 * <li>subject - {@link X509#getSubjectHex}</li> 50 * <li>subject - {@link X509#getSubjectString}</li> 51 * <li>subjectPublicKeyInfo - {@link X509#getPublicKey}</li> 52 * <li>subjectPublicKeyInfo - {@link X509#getPublicKeyHex}</li> 53 * <li>subjectPublicKeyInfo - {@link X509#getPublicKeyIdx}</li> 54 * <li>subjectPublicKeyInfo - {@link X509.getPublicKeyFromCertPEM}</li> 55 * <li>subjectPublicKeyInfo - {@link X509.getPublicKeyFromCertHex}</li> 56 * <li>subjectPublicKeyInfo - {@link X509#getPublicKeyContentIdx}</li> 57 * <li>signature algorithm - {@link X509#getSignatureAlgorithmName}</li> 58 * <li>signature value - {@link X509#getSignatureValueHex}</li> 59 * </ul> 60 * </li> 61 * <li><b>X509 METHODS TO GET EXTENSIONS</b> 62 * <ul> 63 * <li>basicConstraints - {@link X509#getExtBasicConstraints}</li> 64 * <li>keyUsage - {@link X509#getExtKeyUsageBin}</li> 65 * <li>keyUsage - {@link X509#getExtKeyUsageString}</li> 66 * <li>subjectKeyIdentifier - {@link X509#getExtSubjectKeyIdentifier}</li> 67 * <li>authorityKeyIdentifier - {@link X509#getExtAuthorityKeyIdentifier}</li> 68 * <li>extKeyUsage - {@link X509#getExtExtKeyUsageName}</li> 69 * <li>subjectAltName(DEPRECATED) - {@link X509#getExtSubjectAltName}</li> 70 * <li>subjectAltName2 - {@link X509#getExtSubjectAltName2}</li> 71 * <li>cRLDistributionPoints - {@link X509#getExtCRLDistributionPointsURI}</li> 72 * <li>authorityInfoAccess - {@link X509#getExtAIAInfo}</li> 73 * <li>certificatePolicies - {@link X509#getExtCertificatePolicies}</li> 74 * </ul> 75 * </li> 76 * <li><b>UTILITIES</b> 77 * <ul> 78 * <li>reading PEM X.509 certificate - {@link X509#readCertPEM}</li> 79 * <li>reading hexadecimal string of X.509 certificate - {@link X509#readCertHex}</li> 80 * <li>get all certificate information - {@link X509#getInfo}</li> 81 * <li>get specified extension information - {@link X509#getExtInfo}</li> 82 * <li>verify signature value - {@link X509#verifySignature}</li> 83 * </ul> 84 * </li> 85 * </ul> 86 */ 87 function X509() { 88 var _ASN1HEX = ASN1HEX, 89 _getChildIdx = _ASN1HEX.getChildIdx, 90 _getV = _ASN1HEX.getV, 91 _getTLV = _ASN1HEX.getTLV, 92 _getVbyList = _ASN1HEX.getVbyList, 93 _getTLVbyList = _ASN1HEX.getTLVbyList, 94 _getIdxbyList = _ASN1HEX.getIdxbyList, 95 _getVidx = _ASN1HEX.getVidx, 96 _oidname = _ASN1HEX.oidname, 97 _X509 = X509, 98 _pemtohex = pemtohex; 99 100 this.hex = null; 101 this.version = 0; // version (1: X509v1, 3: X509v3, others: unspecified) 102 this.foffset = 0; // field index offset (-1: for X509v1, 0: for X509v3) 103 this.aExtInfo = null; 104 105 // ===== get basic fields from hex ===================================== 106 107 /** 108 * get format version (X.509v1 or v3 certificate)<br/> 109 * @name getVersion 110 * @memberOf X509# 111 * @function 112 * @return {Number} 1 for X509v1, 3 for X509v3, otherwise 0 113 * @since jsrsasign 7.1.14 x509 1.1.13 114 * @description 115 * This method returns a format version of X.509 certificate. 116 * It returns 1 for X.509v1 certificate and 3 for v3 certificate. 117 * Otherwise returns 0. 118 * This method will be automatically called in 119 * {@link X509#readCertPEM}. After then, you can use 120 * {@link X509.version} parameter. 121 * @example 122 * var x = new X509(); 123 * x.readCertPEM(sCertPEM); 124 * version = x.getVersion(); // 1 or 3 125 * sn = x.getSerialNumberHex(); // return string like "01ad..." 126 */ 127 this.getVersion = function() { 128 if (this.hex === null || this.version !== 0) return this.version; 129 130 // check if the first item of tbsCertificate "[0] { INTEGER 2 }" 131 if (_getTLVbyList(this.hex, 0, [0, 0]) !== 132 "a003020102") { 133 this.version = 1; 134 this.foffset = -1; 135 return 1; 136 } 137 138 this.version = 3; 139 return 3; 140 }; 141 142 /** 143 * get hexadecimal string of serialNumber field of certificate.<br/> 144 * @name getSerialNumberHex 145 * @memberOf X509# 146 * @function 147 * @return {String} hexadecimal string of certificate serial number 148 * @example 149 * var x = new X509(); 150 * x.readCertPEM(sCertPEM); 151 * var sn = x.getSerialNumberHex(); // return string like "01ad..." 152 */ 153 this.getSerialNumberHex = function() { 154 return _getVbyList(this.hex, 0, [0, 1 + this.foffset], "02"); 155 }; 156 157 /** 158 * get signature algorithm name in basic field 159 * @name getSignatureAlgorithmField 160 * @memberOf X509# 161 * @function 162 * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA) 163 * @since x509 1.1.8 164 * @description 165 * This method will get a name of signature algorithm field of certificate: 166 * @example 167 * var x = new X509(); 168 * x.readCertPEM(sCertPEM); 169 * algName = x.getSignatureAlgorithmField(); 170 */ 171 this.getSignatureAlgorithmField = function() { 172 return _oidname(_getVbyList(this.hex, 0, [0, 2 + this.foffset, 0], "06")); 173 }; 174 175 /** 176 * get hexadecimal string of issuer field TLV of certificate.<br/> 177 * @name getIssuerHex 178 * @memberOf X509# 179 * @function 180 * @return {String} hexadecial string of issuer DN ASN.1 181 * @example 182 * var x = new X509(); 183 * x.readCertPEM(sCertPEM); 184 * var issuer = x.getIssuerHex(); // return string like "3013..." 185 */ 186 this.getIssuerHex = function() { 187 return _getTLVbyList(this.hex, 0, [0, 3 + this.foffset], "30"); 188 }; 189 190 /** 191 * get string of issuer field of certificate.<br/> 192 * @name getIssuerString 193 * @memberOf X509# 194 * @function 195 * @return {String} issuer DN string 196 * @example 197 * var x = new X509(); 198 * x.readCertPEM(sCertPEM); 199 * var issuer = x.getIssuerString(); // return string like "/C=US/O=TEST" 200 */ 201 this.getIssuerString = function() { 202 return _X509.hex2dn(this.getIssuerHex()); 203 }; 204 205 /** 206 * get hexadecimal string of subject field of certificate.<br/> 207 * @name getSubjectHex 208 * @memberOf X509# 209 * @function 210 * @return {String} hexadecial string of subject DN ASN.1 211 * @example 212 * var x = new X509(); 213 * x.readCertPEM(sCertPEM); 214 * var subject = x.getSubjectHex(); // return string like "3013..." 215 */ 216 this.getSubjectHex = function() { 217 return _getTLVbyList(this.hex, 0, [0, 5 + this.foffset], "30"); 218 }; 219 220 /** 221 * get string of subject field of certificate.<br/> 222 * @name getSubjectString 223 * @memberOf X509# 224 * @function 225 * @return {String} subject DN string 226 * @example 227 * var x = new X509(); 228 * x.readCertPEM(sCertPEM); 229 * var subject = x.getSubjectString(); // return string like "/C=US/O=TEST" 230 */ 231 this.getSubjectString = function() { 232 return _X509.hex2dn(this.getSubjectHex()); 233 }; 234 235 /** 236 * get notBefore field string of certificate.<br/> 237 * @name getNotBefore 238 * @memberOf X509# 239 * @function 240 * @return {String} not before time value (ex. "151231235959Z") 241 * @example 242 * var x = new X509(); 243 * x.readCertPEM(sCertPEM); 244 * var notBefore = x.getNotBefore(); // return string like "151231235959Z" 245 */ 246 this.getNotBefore = function() { 247 var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 0]); 248 s = s.replace(/(..)/g, "%$1"); 249 s = decodeURIComponent(s); 250 return s; 251 }; 252 253 /** 254 * get notAfter field string of certificate.<br/> 255 * @name getNotAfter 256 * @memberOf X509# 257 * @function 258 * @return {String} not after time value (ex. "151231235959Z") 259 * @example 260 * var x = new X509(); 261 * x.readCertPEM(sCertPEM); 262 * var notAfter = x.getNotAfter(); // return string like "151231235959Z" 263 */ 264 this.getNotAfter = function() { 265 var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 1]); 266 s = s.replace(/(..)/g, "%$1"); 267 s = decodeURIComponent(s); 268 return s; 269 }; 270 271 /** 272 * get a hexadecimal string of subjectPublicKeyInfo field.<br/> 273 * @name getPublicKeyHex 274 * @memberOf X509# 275 * @function 276 * @return {String} ASN.1 SEQUENCE hexadecimal string of subjectPublicKeyInfo field 277 * @since jsrsasign 7.1.4 x509 1.1.13 278 * @example 279 * x = new X509(); 280 * x.readCertPEM(sCertPEM); 281 * hSPKI = x.getPublicKeyHex(); // return string like "30820122..." 282 */ 283 this.getPublicKeyHex = function() { 284 return _ASN1HEX.getTLVbyList(this.hex, 0, [0, 6 + this.foffset], "30"); 285 }; 286 287 /** 288 * get a string index of subjectPublicKeyInfo field for hexadecimal string certificate.<br/> 289 * @name getPublicKeyIdx 290 * @memberOf X509# 291 * @function 292 * @return {Number} string index of subjectPublicKeyInfo field for hexadecimal string certificate. 293 * @since jsrsasign 7.1.4 x509 1.1.13 294 * @example 295 * x = new X509(); 296 * x.readCertPEM(sCertPEM); 297 * idx = x.getPublicKeyIdx(); // return string index in x.hex parameter 298 */ 299 this.getPublicKeyIdx = function() { 300 return _getIdxbyList(this.hex, 0, [0, 6 + this.foffset], "30"); 301 }; 302 303 /** 304 * get a string index of contents of subjectPublicKeyInfo BITSTRING value from hexadecimal certificate<br/> 305 * @name getPublicKeyContentIdx 306 * @memberOf X509# 307 * @function 308 * @return {Integer} string index of key contents 309 * @since jsrsasign 8.0.0 x509 1.2.0 310 * @example 311 * x = new X509(); 312 * x.readCertPEM(sCertPEM); 313 * idx = x.getPublicKeyContentIdx(); // return string index in x.hex parameter 314 */ 315 // NOTE: Without BITSTRING encapsulation. 316 this.getPublicKeyContentIdx = function() { 317 var idx = this.getPublicKeyIdx(); 318 return _getIdxbyList(this.hex, idx, [1, 0], "30"); 319 }; 320 321 /** 322 * get a RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field.<br/> 323 * @name getPublicKey 324 * @memberOf X509# 325 * @function 326 * @return {Object} RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field 327 * @since jsrsasign 7.1.4 x509 1.1.13 328 * @example 329 * x = new X509(); 330 * x.readCertPEM(sCertPEM); 331 * pubkey= x.getPublicKey(); 332 */ 333 this.getPublicKey = function() { 334 return KEYUTIL.getKey(this.getPublicKeyHex(), null, "pkcs8pub"); 335 }; 336 337 /** 338 * get signature algorithm name from hexadecimal certificate data 339 * @name getSignatureAlgorithmName 340 * @memberOf X509# 341 * @function 342 * @param {String} hCert hexadecimal string of X.509 certificate binary 343 * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA) 344 * @since jsrsasign 7.2.0 x509 1.1.14 345 * @description 346 * This method will get signature algorithm name of certificate: 347 * @example 348 * var x = new X509(); 349 * x.readCertPEM(sCertPEM); 350 * x.getSignatureAlgorithmName() → "SHA256withRSA" 351 */ 352 this.getSignatureAlgorithmName = function() { 353 return _oidname(_getVbyList(this.hex, 0, [1, 0], "06")); 354 }; 355 356 /** 357 * get signature value in hexadecimal string<br/> 358 * @name getSignatureValueHex 359 * @memberOf X509# 360 * @function 361 * @return {String} signature value hexadecimal string without BitString unused bits 362 * @since jsrsasign 7.2.0 x509 1.1.14 363 * @description 364 * This method will get signature value of certificate: 365 * @example 366 * var x = new X509(); 367 * x.readCertPEM(sCertPEM); 368 * x.getSignatureValueHex() &rarr "8a4c47913..." 369 */ 370 this.getSignatureValueHex = function() { 371 return _getVbyList(this.hex, 0, [2], "03", true); 372 }; 373 374 /** 375 * verifies signature value by public key<br/> 376 * @name verifySignature 377 * @memberOf X509# 378 * @function 379 * @param {Object} pubKey public key object 380 * @return {Boolean} true if signature value is valid otherwise false 381 * @since jsrsasign 7.2.0 x509 1.1.14 382 * @description 383 * This method verifies signature value of hexadecimal string of 384 * X.509 certificate by specified public key object. 385 * @example 386 * pubKey = KEYUTIL.getKey(pemPublicKey); // or certificate 387 * x = new X509(); 388 * x.readCertPEM(pemCert); 389 * x.verifySignature(pubKey) → true, false or raising exception 390 */ 391 this.verifySignature = function(pubKey) { 392 var algName = this.getSignatureAlgorithmName(); 393 var hSigVal = this.getSignatureValueHex(); 394 var hTbsCert = _getTLVbyList(this.hex, 0, [0], "30"); 395 396 var sig = new KJUR.crypto.Signature({alg: algName}); 397 sig.init(pubKey); 398 sig.updateHex(hTbsCert); 399 return sig.verify(hSigVal); 400 }; 401 402 // ===== parse extension ====================================== 403 /** 404 * set array of X.509v3 extesion information such as extension OID, criticality and value index.<br/> 405 * @name parseExt 406 * @memberOf X509# 407 * @function 408 * @since jsrsasign 7.2.0 x509 1.1.14 409 * @description 410 * This method will set an array of X.509v3 extension information having 411 * following parameters: 412 * <ul> 413 * <li>oid - extension OID (ex. 2.5.29.19)</li> 414 * <li>critical - true or false</li> 415 * <li>vidx - string index for extension value</li> 416 * @example 417 * x = new X509(); 418 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 419 * 420 * x.aExtInfo → 421 * [ { oid: "2.5.29,19", critical: true, vidx: 2504 }, ... ] 422 */ 423 this.parseExt = function() { 424 if (this.version !== 3) return -1; 425 var iExtSeq = _getIdxbyList(this.hex, 0, [0, 7, 0], "30"); 426 var aExtIdx = _getChildIdx(this.hex, iExtSeq); 427 428 this.aExtInfo = new Array(); 429 for (var i = 0; i < aExtIdx.length; i++) { 430 var item = {}; 431 item.critical = false; 432 var a = _getChildIdx(this.hex, aExtIdx[i]); 433 var offset = 0; 434 435 if (a.length === 3) { 436 item.critical = true; 437 offset = 1; 438 } 439 440 item.oid = _ASN1HEX.hextooidstr(_getVbyList(this.hex, aExtIdx[i], [0], "06")); 441 var octidx = _getIdxbyList(this.hex, aExtIdx[i], [1 + offset]); 442 item.vidx = _getVidx(this.hex, octidx); 443 this.aExtInfo.push(item); 444 } 445 }; 446 447 /** 448 * get a X.509v3 extesion information such as extension OID, criticality and value index for specified oid or name.<br/> 449 * @name getExtInfo 450 * @memberOf X509# 451 * @function 452 * @param {String} oidOrName X.509 extension oid or name (ex. keyUsage or 2.5.29.19) 453 * @return X.509 extension information such as extension OID or value indx (see {@link X509#parseExt}) 454 * @since jsrsasign 7.2.0 x509 1.1.14 455 * @description 456 * This method will get an X.509v3 extension information JSON object 457 * having extension OID, criticality and value idx for specified 458 * extension OID or name. 459 * If there is no such extension, this returns undefined. 460 * @example 461 * x = new X509(); 462 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 463 * 464 * x.getExtInfo("keyUsage") → { oid: "2.5.29.15", critical: true, vidx: 1714 } 465 * x.getExtInfo("unknownExt") → undefined 466 */ 467 this.getExtInfo = function(oidOrName) { 468 var a = this.aExtInfo; 469 var oid = oidOrName; 470 if (! oidOrName.match(/^[0-9.]+$/)) { 471 oid = KJUR.asn1.x509.OID.name2oid(oidOrName); 472 } 473 if (oid === '') return undefined; 474 475 for (var i = 0; i < a.length; i++) { 476 if (a[i].oid === oid) return a[i]; 477 } 478 return undefined; 479 }; 480 481 /** 482 * get BasicConstraints extension value as object in the certificate 483 * @name getExtBasicConstraints 484 * @memberOf X509# 485 * @function 486 * @return {Object} associative array which may have "cA" and "pathLen" parameters 487 * @since jsrsasign 7.2.0 x509 1.1.14 488 * @description 489 * This method will get basic constraints extension value as object with following paramters. 490 * <ul> 491 * <li>cA - CA flag whether CA or not</li> 492 * <li>pathLen - maximum intermediate certificate length</li> 493 * </ul> 494 * There are use cases for return values: 495 * <ul> 496 * <li>{cA:true, pathLen:3} - cA flag is true and pathLen is 3</li> 497 * <li>{cA:true} - cA flag is true and no pathLen</li> 498 * <li>{} - basic constraints has no value in case of end entity certificate</li> 499 * <li>undefined - there is no basic constraints extension</li> 500 * </ul> 501 * @example 502 * x = new X509(); 503 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 504 * x.getExtBasicConstraints() → { cA: true, pathLen: 3 }; 505 */ 506 this.getExtBasicConstraints = function() { 507 var info = this.getExtInfo("basicConstraints"); 508 if (info === undefined) return info; 509 510 var hBC = _getV(this.hex, info.vidx); 511 if (hBC === '') return {}; 512 if (hBC === '0101ff') return { cA: true }; 513 if (hBC.substr(0, 8) === '0101ff02') { 514 var pathLexHex = _getV(hBC, 6); 515 var pathLen = parseInt(pathLexHex, 16); 516 return { cA: true, pathLen: pathLen }; 517 } 518 throw "basicConstraints parse error"; 519 }; 520 521 522 /** 523 * get KeyUsage extension value as binary string in the certificate<br/> 524 * @name getExtKeyUsageBin 525 * @memberOf X509# 526 * @function 527 * @return {String} binary string of key usage bits (ex. '101') 528 * @since jsrsasign 7.2.0 x509 1.1.14 529 * @description 530 * This method will get key usage extension value 531 * as binary string such like '101'. 532 * Key usage bits definition is in the RFC 5280. 533 * If there is no key usage extension in the certificate, 534 * it returns empty string (i.e. ''). 535 * @example 536 * x = new X509(); 537 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 538 * x.getExtKeyUsageBin() → '101' 539 * // 1 - digitalSignature 540 * // 0 - nonRepudiation 541 * // 1 - keyEncipherment 542 */ 543 this.getExtKeyUsageBin = function() { 544 var info = this.getExtInfo("keyUsage"); 545 if (info === undefined) return ''; 546 547 var hKeyUsage = _getV(this.hex, info.vidx); 548 if (hKeyUsage.length % 2 != 0 || hKeyUsage.length <= 2) 549 throw "malformed key usage value"; 550 var unusedBits = parseInt(hKeyUsage.substr(0, 2)); 551 var bKeyUsage = parseInt(hKeyUsage.substr(2), 16).toString(2); 552 return bKeyUsage.substr(0, bKeyUsage.length - unusedBits); 553 }; 554 555 /** 556 * get KeyUsage extension value as names in the certificate<br/> 557 * @name getExtKeyUsageString 558 * @memberOf X509# 559 * @function 560 * @return {String} comma separated string of key usage 561 * @since jsrsasign 7.2.0 x509 1.1.14 562 * @description 563 * This method will get key usage extension value 564 * as comma separated string of usage names. 565 * If there is no key usage extension in the certificate, 566 * it returns empty string (i.e. ''). 567 * @example 568 * x = new X509(); 569 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 570 * x.getExtKeyUsageString() → "digitalSignature,keyEncipherment" 571 */ 572 this.getExtKeyUsageString = function() { 573 var bKeyUsage = this.getExtKeyUsageBin(); 574 var a = new Array(); 575 for (var i = 0; i < bKeyUsage.length; i++) { 576 if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]); 577 } 578 return a.join(","); 579 }; 580 581 /** 582 * get subjectKeyIdentifier value as hexadecimal string in the certificate<br/> 583 * @name getExtSubjectKeyIdentifier 584 * @memberOf X509# 585 * @function 586 * @return {String} hexadecimal string of subject key identifier or null 587 * @since jsrsasign 7.2.0 x509 1.1.14 588 * @description 589 * This method will get subject key identifier extension value 590 * as hexadecimal string. 591 * If there is this in the certificate, it returns undefined; 592 * @example 593 * x = new X509(); 594 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 595 * x.getExtSubjectKeyIdentifier() → "1b3347ab..."; 596 */ 597 this.getExtSubjectKeyIdentifier = function() { 598 var info = this.getExtInfo("subjectKeyIdentifier"); 599 if (info === undefined) return info; 600 601 return _getV(this.hex, info.vidx); 602 }; 603 604 /** 605 * get authorityKeyIdentifier value as JSON object in the certificate<br/> 606 * @name getExtAuthorityKeyIdentifier 607 * @memberOf X509# 608 * @function 609 * @return {Object} JSON object of authority key identifier or null 610 * @since jsrsasign 7.2.0 x509 1.1.14 611 * @description 612 * This method will get authority key identifier extension value 613 * as JSON object. 614 * If there is this in the certificate, it returns undefined; 615 * <br> 616 * NOTE: Currently this method only supports keyIdentifier so that 617 * authorityCertIssuer and authorityCertSerialNumber will not 618 * be return in the JSON object. 619 * @example 620 * x = new X509(); 621 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 622 * x.getExtAuthorityKeyIdentifier() → { kid: "1234abcd..." } 623 */ 624 this.getExtAuthorityKeyIdentifier = function() { 625 var info = this.getExtInfo("authorityKeyIdentifier"); 626 if (info === undefined) return info; 627 628 var result = {}; 629 var hAKID = _getTLV(this.hex, info.vidx); 630 var a = _getChildIdx(hAKID, 0); 631 for (var i = 0; i < a.length; i++) { 632 if (hAKID.substr(a[i], 2) === "80") 633 result.kid = _getV(hAKID, a[i]); 634 } 635 return result; 636 }; 637 638 /** 639 * get extKeyUsage value as array of name string in the certificate<br/> 640 * @name getExtExtKeyUsageName 641 * @memberOf X509# 642 * @function 643 * @return {Object} array of extended key usage ID name or oid 644 * @since jsrsasign 7.2.0 x509 1.1.14 645 * @description 646 * This method will get extended key usage extension value 647 * as array of name or OID string. 648 * If there is this in the certificate, it returns undefined; 649 * <br> 650 * NOTE: Supported extended key usage ID names are defined in 651 * name2oidList parameter in asn1x509.js file. 652 * @example 653 * x = new X509(); 654 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 655 * x.getExtExtKeyUsageName() → ["serverAuth", "clientAuth", "0.1.2.3.4.5"] 656 */ 657 this.getExtExtKeyUsageName = function() { 658 var info = this.getExtInfo("extKeyUsage"); 659 if (info === undefined) return info; 660 661 var result = new Array(); 662 663 var h = _getTLV(this.hex, info.vidx); 664 if (h === '') return result; 665 666 var a = _getChildIdx(h, 0); 667 for (var i = 0; i < a.length; i++) { 668 result.push(_oidname(_getV(h, a[i]))); 669 } 670 671 return result; 672 }; 673 674 /** 675 * (DEPRECATED) get subjectAltName value as array of string in the certificate 676 * @name getExtSubjectAltName 677 * @memberOf X509# 678 * @function 679 * @return {Object} array of alt names 680 * @since jsrsasign 7.2.0 x509 1.1.14 681 * @deprecated since jsrsasign 8.0.1 x509 1.1.17. Please move to {@link X509#getExtSubjectAltName2} 682 * @description 683 * This method will get subject alt name extension value 684 * as array of name. 685 * If there is this in the certificate, it returns undefined; 686 * <br> 687 * NOTE: Currently this method supports only dNSName so that 688 * other name type such like iPAddress or generalName will not be returned. 689 * @example 690 * x = new X509(); 691 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 692 * x.getExtSubjectAltName() → ["example.com", "example.org"] 693 */ 694 this.getExtSubjectAltName = function() { 695 var a = this.getExtSubjectAltName2(); 696 var result = new Array(); 697 698 for (var i = 0; i < a.length; i++) { 699 if (a[i][0] === "DNS") result.push(a[i][1]); 700 } 701 return result; 702 }; 703 704 /** 705 * get subjectAltName value as array of string in the certificate 706 * @name getExtSubjectAltName2 707 * @memberOf X509# 708 * @function 709 * @return {Object} array of alt name array 710 * @since jsrsasign 8.0.1 x509 1.1.17 711 * @description 712 * This method will get subject alt name extension value 713 * as array of type and name. 714 * If there is this in the certificate, it returns undefined; 715 * Type of GeneralName will be shown as following: 716 * <ul> 717 * <li>"MAIL" - [1]rfc822Name</li> 718 * <li>"DNS" - [2]dNSName</li> 719 * <li>"DN" - [4]directoryName</li> 720 * <li>"URI" - [6]uniformResourceIdentifier</li> 721 * <li>"IP" - [7]iPAddress</li> 722 * </ul> 723 * @example 724 * x = new X509(); 725 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 726 * x.getExtSubjectAltName2() → 727 * [["DNS", "example.com"], 728 * ["DNS", "example.org"], 729 * ["MAIL", "foo@example.com"], 730 * ["IP", "192.168.1.1"], 731 * ["IP", "2001:db8::2:1"], 732 * ["DN", "/C=US/O=TEST1"]] 733 */ 734 this.getExtSubjectAltName2 = function() { 735 var gnValueHex, gnValueStr, gnTag; 736 var info = this.getExtInfo("subjectAltName"); 737 if (info === undefined) return info; 738 739 var result = new Array(); 740 var h = _getTLV(this.hex, info.vidx); 741 742 var a = _getChildIdx(h, 0); 743 for (var i = 0; i < a.length; i++) { 744 gnTag = h.substr(a[i], 2); 745 gnValueHex = _getV(h, a[i]); 746 747 if (gnTag === "81") { // rfc822Name [1] 748 gnValueStr = hextoutf8(gnValueHex); 749 result.push(["MAIL", gnValueStr]); 750 } 751 if (gnTag === "82") { // dNSName [2] 752 gnValueStr = hextoutf8(gnValueHex); 753 result.push(["DNS", gnValueStr]); 754 } 755 if (gnTag === "84") { // directoryName [4] 756 gnValueStr = X509.hex2dn(gnValueHex, 0); 757 result.push(["DN", gnValueStr]); 758 } 759 if (gnTag === "86") { // uniformResourceIdentifier [6] 760 gnValueStr = hextoutf8(gnValueHex); 761 result.push(["URI", gnValueStr]); 762 } 763 if (gnTag === "87") { // iPAddress [7] 764 gnValueStr = hextoip(gnValueHex); 765 result.push(["IP", gnValueStr]); 766 } 767 } 768 return result; 769 }; 770 771 /** 772 * get array of string for fullName URIs in cRLDistributionPoints(CDP) in the certificate 773 * @name getExtCRLDistributionPointsURI 774 * @memberOf X509# 775 * @function 776 * @return {Object} array of fullName URIs of CDP of the certificate 777 * @since jsrsasign 7.2.0 x509 1.1.14 778 * @description 779 * This method will get all fullName URIs of cRLDistributionPoints extension 780 * in the certificate as array of URI string. 781 * If there is this in the certificate, it returns undefined; 782 * <br> 783 * NOTE: Currently this method supports only fullName URI so that 784 * other parameters will not be returned. 785 * @example 786 * x = new X509(); 787 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 788 * x.getExtCRLDistributionPointsURI() → 789 * ["http://example.com/aaa.crl", "http://example.org/aaa.crl"] 790 */ 791 this.getExtCRLDistributionPointsURI = function() { 792 var info = this.getExtInfo("cRLDistributionPoints"); 793 if (info === undefined) return info; 794 795 var result = new Array(); 796 var a = _getChildIdx(this.hex, info.vidx); 797 for (var i = 0; i < a.length; i++) { 798 try { 799 var hURI = _getVbyList(this.hex, a[i], [0, 0, 0], "86"); 800 var uri = hextoutf8(hURI); 801 result.push(uri); 802 } catch(ex) {}; 803 } 804 805 return result; 806 }; 807 808 /** 809 * get AuthorityInfoAccess extension value in the certificate as associative array 810 * @name getExtAIAInfo 811 * @memberOf X509# 812 * @function 813 * @return {Object} associative array of AIA extension properties 814 * @since jsrsasign 7.2.0 x509 1.1.14 815 * @description 816 * This method will get authority info access value 817 * as associate array which has following properties: 818 * <ul> 819 * <li>ocsp - array of string for OCSP responder URL</li> 820 * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li> 821 * </ul> 822 * If there is this in the certificate, it returns undefined; 823 * @example 824 * x = new X509(); 825 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 826 * x.getExtAIAInfo(hCert) → 827 * { ocsp: ["http://ocsp.foo.com"], 828 * caissuer: ["http://rep.foo.com/aaa.p8m"] } 829 */ 830 this.getExtAIAInfo = function() { 831 var info = this.getExtInfo("authorityInfoAccess"); 832 if (info === undefined) return info; 833 834 var result = { ocsp: [], caissuer: [] }; 835 var a = _getChildIdx(this.hex, info.vidx); 836 for (var i = 0; i < a.length; i++) { 837 var hOID = _getVbyList(this.hex, a[i], [0], "06"); 838 var hName = _getVbyList(this.hex, a[i], [1], "86"); 839 if (hOID === "2b06010505073001") { 840 result.ocsp.push(hextoutf8(hName)); 841 } 842 if (hOID === "2b06010505073002") { 843 result.caissuer.push(hextoutf8(hName)); 844 } 845 } 846 847 return result; 848 }; 849 850 /** 851 * get CertificatePolicies extension value in the certificate as array 852 * @name getExtCertificatePolicies 853 * @memberOf X509# 854 * @function 855 * @return {Object} array of PolicyInformation JSON object 856 * @since jsrsasign 7.2.0 x509 1.1.14 857 * @description 858 * This method will get certificate policies value 859 * as an array of JSON object which has following properties: 860 * <ul> 861 * <li>id - </li> 862 * <li>cps - URI of certification practice statement</li> 863 * <li>unotice - string of UserNotice explicitText</li> 864 * </ul> 865 * If there is this extension in the certificate, 866 * it returns undefined; 867 * @example 868 * x = new X509(); 869 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 870 * x.getExtCertificatePolicies → 871 * [{ id: 1.2.3.4, 872 * cps: "http://example.com/cps", 873 * unotice: "explicit text" }] 874 */ 875 this.getExtCertificatePolicies = function() { 876 var info = this.getExtInfo("certificatePolicies"); 877 if (info === undefined) return info; 878 879 var hExt = _getTLV(this.hex, info.vidx); 880 var result = []; 881 882 var a = _getChildIdx(hExt, 0); 883 for (var i = 0; i < a.length; i++) { 884 var policyInfo = {}; 885 var a1 = _getChildIdx(hExt, a[i]); 886 887 policyInfo.id = _oidname(_getV(hExt, a1[0])); 888 889 if (a1.length === 2) { 890 var a2 = _getChildIdx(hExt, a1[1]); 891 892 for (var j = 0; j < a2.length; j++) { 893 var hQualifierId = _getVbyList(hExt, a2[j], [0], "06"); 894 895 if (hQualifierId === "2b06010505070201") { // cps 896 policyInfo.cps = hextoutf8(_getVbyList(hExt, a2[j], [1])); 897 } else if (hQualifierId === "2b06010505070202") { // unotice 898 policyInfo.unotice = 899 hextoutf8(_getVbyList(hExt, a2[j], [1, 0])); 900 } 901 } 902 } 903 904 result.push(policyInfo); 905 } 906 907 return result; 908 } 909 910 // ===== read certificate ===================================== 911 /** 912 * read PEM formatted X.509 certificate from string.<br/> 913 * @name readCertPEM 914 * @memberOf X509# 915 * @function 916 * @param {String} sCertPEM string for PEM formatted X.509 certificate 917 * @example 918 * x = new X509(); 919 * x.readCertPEM(sCertPEM); // read certificate 920 */ 921 this.readCertPEM = function(sCertPEM) { 922 this.readCertHex(_pemtohex(sCertPEM)); 923 }; 924 925 /** 926 * read a hexadecimal string of X.509 certificate<br/> 927 * @name readCertHex 928 * @memberOf X509# 929 * @function 930 * @param {String} sCertHex hexadecimal string of X.509 certificate 931 * @since jsrsasign 7.1.4 x509 1.1.13 932 * @description 933 * NOTE: {@link X509#parseExt} will called internally since jsrsasign 7.2.0. 934 * @example 935 * x = new X509(); 936 * x.readCertHex("3082..."); // read certificate 937 */ 938 this.readCertHex = function(sCertHex) { 939 this.hex = sCertHex; 940 this.getVersion(); // set version parameter 941 942 try { 943 _getIdxbyList(this.hex, 0, [0, 7], "a3"); // has [3] v3ext 944 this.parseExt(); 945 } catch(ex) {}; 946 }; 947 948 /** 949 * get certificate information as string.<br/> 950 * @name getInfo 951 * @memberOf X509# 952 * @function 953 * @return {String} certificate information string 954 * @since jsrsasign 5.0.10 x509 1.1.8 955 * @example 956 * x = new X509(); 957 * x.readCertPEM(certPEM); 958 * console.log(x.getInfo()); 959 * // this shows as following 960 * Basic Fields 961 * serial number: 02ac5c266a0b409b8f0b79f2ae462577 962 * signature algorithm: SHA1withRSA 963 * issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA 964 * notBefore: 061110000000Z 965 * notAfter: 311110000000Z 966 * subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA 967 * subject public key info: 968 * key algorithm: RSA 969 * n=c6cce573e6fbd4bb... 970 * e=10001 971 * X509v3 Extensions: 972 * keyUsage CRITICAL: 973 * digitalSignature,keyCertSign,cRLSign 974 * basicConstraints CRITICAL: 975 * cA=true 976 * subjectKeyIdentifier : 977 * b13ec36903f8bf4701d498261a0802ef63642bc3 978 * authorityKeyIdentifier : 979 * kid=b13ec36903f8bf4701d498261a0802ef63642bc3 980 * signature algorithm: SHA1withRSA 981 * signature: 1c1a0697dcd79c9f... 982 */ 983 this.getInfo = function() { 984 var _X509 = X509; 985 var s, pubkey, aExt; 986 s = "Basic Fields\n"; 987 s += " serial number: " + this.getSerialNumberHex() + "\n"; 988 s += " signature algorithm: " + this.getSignatureAlgorithmField() + "\n"; 989 s += " issuer: " + this.getIssuerString() + "\n"; 990 s += " notBefore: " + this.getNotBefore() + "\n"; 991 s += " notAfter: " + this.getNotAfter() + "\n"; 992 s += " subject: " + this.getSubjectString() + "\n"; 993 s += " subject public key info: " + "\n"; 994 995 // subject public key info 996 pubkey = this.getPublicKey(); 997 s += " key algorithm: " + pubkey.type + "\n"; 998 999 if (pubkey.type === "RSA") { 1000 s += " n=" + hextoposhex(pubkey.n.toString(16)).substr(0, 16) + "...\n"; 1001 s += " e=" + hextoposhex(pubkey.e.toString(16)) + "\n"; 1002 } 1003 1004 // X.509v3 Extensions 1005 aExt = this.aExtInfo; 1006 1007 if (aExt !== undefined && aExt !== null) { 1008 s += "X509v3 Extensions:\n"; 1009 1010 for (var i = 0; i < aExt.length; i++) { 1011 var info = aExt[i]; 1012 1013 // show extension name and critical flag 1014 var extName = KJUR.asn1.x509.OID.oid2name(info["oid"]); 1015 if (extName === '') extName = info["oid"]; 1016 1017 var critical = ''; 1018 if (info["critical"] === true) critical = "CRITICAL"; 1019 1020 s += " " + extName + " " + critical + ":\n"; 1021 1022 // show extension value if supported 1023 if (extName === "basicConstraints") { 1024 var bc = this.getExtBasicConstraints(); 1025 if (bc.cA === undefined) { 1026 s += " {}\n"; 1027 } else { 1028 s += " cA=true"; 1029 if (bc.pathLen !== undefined) 1030 s += ", pathLen=" + bc.pathLen; 1031 s += "\n"; 1032 } 1033 } else if (extName === "keyUsage") { 1034 s += " " + this.getExtKeyUsageString() + "\n"; 1035 } else if (extName === "subjectKeyIdentifier") { 1036 s += " " + this.getExtSubjectKeyIdentifier() + "\n"; 1037 } else if (extName === "authorityKeyIdentifier") { 1038 var akid = this.getExtAuthorityKeyIdentifier(); 1039 if (akid.kid !== undefined) 1040 s += " kid=" + akid.kid + "\n"; 1041 } else if (extName === "extKeyUsage") { 1042 var eku = this.getExtExtKeyUsageName(); 1043 s += " " + eku.join(", ") + "\n"; 1044 } else if (extName === "subjectAltName") { 1045 var san = this.getExtSubjectAltName2(); 1046 s += " " + san + "\n"; 1047 } else if (extName === "cRLDistributionPoints") { 1048 var cdp = this.getExtCRLDistributionPointsURI(); 1049 s += " " + cdp + "\n"; 1050 } else if (extName === "authorityInfoAccess") { 1051 var aia = this.getExtAIAInfo(); 1052 if (aia.ocsp !== undefined) 1053 s += " ocsp: " + aia.ocsp.join(",") + "\n"; 1054 if (aia.caissuer !== undefined) 1055 s += " caissuer: " + aia.caissuer.join(",") + "\n"; 1056 } else if (extName === "certificatePolicies") { 1057 var aCP = this.getExtCertificatePolicies(); 1058 for (var j = 0; j < aCP.length; j++) { 1059 if (aCP[j].id !== undefined) 1060 s += " policy oid: " + aCP[j].id + "\n"; 1061 if (aCP[j].cps !== undefined) 1062 s += " cps: " + aCP[j].cps + "\n"; 1063 } 1064 } 1065 } 1066 } 1067 1068 s += "signature algorithm: " + this.getSignatureAlgorithmName() + "\n"; 1069 s += "signature: " + this.getSignatureValueHex().substr(0, 16) + "...\n"; 1070 return s; 1071 }; 1072 }; 1073 1074 /** 1075 * get distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER X.500 name<br/> 1076 * @name hex2dn 1077 * @memberOf X509 1078 * @function 1079 * @param {String} hex hexadecimal string of ASN.1 DER distinguished name 1080 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 1081 * @return {String} OpenSSL online format distinguished name 1082 * @description 1083 * This static method converts from a hexadecimal string of 1084 * distinguished name (DN) 1085 * specified by 'hex' and 'idx' to OpenSSL oneline string representation (ex. /C=US/O=a). 1086 * @example 1087 * X509.hex2dn("3031310b3...") → /C=US/O=a/CN=b2+OU=b1 1088 */ 1089 X509.hex2dn = function(hex, idx) { 1090 if (idx === undefined) idx = 0; 1091 if (hex.substr(idx, 2) !== "30") throw "malformed DN"; 1092 1093 var a = new Array(); 1094 1095 var aIdx = ASN1HEX.getChildIdx(hex, idx); 1096 for (var i = 0; i < aIdx.length; i++) { 1097 a.push(X509.hex2rdn(hex, aIdx[i])); 1098 } 1099 1100 a = a.map(function(s) { return s.replace("/", "\\/"); }); 1101 return "/" + a.join("/"); 1102 }; 1103 1104 /** 1105 * get relative distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER RDN<br/> 1106 * @name hex2rdn 1107 * @memberOf X509 1108 * @function 1109 * @param {String} hex hexadecimal string of ASN.1 DER concludes relative distinguished name 1110 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 1111 * @return {String} OpenSSL online format relative distinguished name 1112 * @description 1113 * This static method converts from a hexadecimal string of 1114 * relative distinguished name (RDN) 1115 * specified by 'hex' and 'idx' to LDAP string representation (ex. O=test+CN=test).<br/> 1116 * NOTE: Multi-valued RDN is supported since jsnrsasign 6.2.2 x509 1.1.10. 1117 * @example 1118 * X509.hex2rdn("310a3008060355040a0c0161") → O=a 1119 * X509.hex2rdn("31143008060355040a0c01613008060355040a0c0162") → O=a+O=b 1120 */ 1121 X509.hex2rdn = function(hex, idx) { 1122 if (idx === undefined) idx = 0; 1123 if (hex.substr(idx, 2) !== "31") throw "malformed RDN"; 1124 1125 var a = new Array(); 1126 1127 var aIdx = ASN1HEX.getChildIdx(hex, idx); 1128 for (var i = 0; i < aIdx.length; i++) { 1129 a.push(X509.hex2attrTypeValue(hex, aIdx[i])); 1130 } 1131 1132 a = a.map(function(s) { return s.replace("+", "\\+"); }); 1133 return a.join("+"); 1134 }; 1135 1136 /** 1137 * get string from hexadecimal string of ASN.1 DER AttributeTypeAndValue<br/> 1138 * @name hex2attrTypeValue 1139 * @memberOf X509 1140 * @function 1141 * @param {String} hex hexadecimal string of ASN.1 DER concludes AttributeTypeAndValue 1142 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 1143 * @return {String} string representation of AttributeTypeAndValue (ex. C=US) 1144 * @description 1145 * This static method converts from a hexadecimal string of AttributeTypeAndValue 1146 * specified by 'hex' and 'idx' to LDAP string representation (ex. C=US). 1147 * @example 1148 * X509.hex2attrTypeValue("3008060355040a0c0161") → O=a 1149 * X509.hex2attrTypeValue("300806035504060c0161") → C=a 1150 * X509.hex2attrTypeValue("...3008060355040a0c0161...", 128) → O=a 1151 */ 1152 X509.hex2attrTypeValue = function(hex, idx) { 1153 var _ASN1HEX = ASN1HEX; 1154 var _getV = _ASN1HEX.getV; 1155 1156 if (idx === undefined) idx = 0; 1157 if (hex.substr(idx, 2) !== "30") throw "malformed attribute type and value"; 1158 1159 var aIdx = _ASN1HEX.getChildIdx(hex, idx); 1160 if (aIdx.length !== 2 || hex.substr(aIdx[0], 2) !== "06") 1161 "malformed attribute type and value"; 1162 1163 var oidHex = _getV(hex, aIdx[0]); 1164 var oidInt = KJUR.asn1.ASN1Util.oidHexToInt(oidHex); 1165 var atype = KJUR.asn1.x509.OID.oid2atype(oidInt); 1166 1167 var hV = _getV(hex, aIdx[1]); 1168 var rawV = hextorstr(hV); 1169 1170 return atype + "=" + rawV; 1171 }; 1172 1173 /** 1174 * get RSA/DSA/ECDSA public key object from X.509 certificate hexadecimal string<br/> 1175 * @name getPublicKeyFromCertHex 1176 * @memberOf X509 1177 * @function 1178 * @param {String} h hexadecimal string of X.509 certificate for RSA/ECDSA/DSA public key 1179 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key 1180 * @since jsrasign 7.1.0 x509 1.1.11 1181 */ 1182 X509.getPublicKeyFromCertHex = function(h) { 1183 var x = new X509(); 1184 x.readCertHex(h); 1185 return x.getPublicKey(); 1186 }; 1187 1188 /** 1189 * get RSA/DSA/ECDSA public key object from PEM certificate string 1190 * @name getPublicKeyFromCertPEM 1191 * @memberOf X509 1192 * @function 1193 * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate 1194 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key 1195 * @since x509 1.1.1 1196 * @description 1197 * NOTE: DSA is also supported since x509 1.1.2. 1198 */ 1199 X509.getPublicKeyFromCertPEM = function(sCertPEM) { 1200 var x = new X509(); 1201 x.readCertPEM(sCertPEM); 1202 return x.getPublicKey(); 1203 }; 1204 1205 /** 1206 * get public key information from PEM certificate 1207 * @name getPublicKeyInfoPropOfCertPEM 1208 * @memberOf X509 1209 * @function 1210 * @param {String} sCertPEM string of PEM formatted certificate 1211 * @return {Hash} hash of information for public key 1212 * @since x509 1.1.1 1213 * @description 1214 * Resulted associative array has following properties:<br/> 1215 * <ul> 1216 * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li> 1217 * <li>algparam - hexadecimal string of OID of ECC curve name or null</li> 1218 * <li>keyhex - hexadecimal string of key in the certificate</li> 1219 * </ul> 1220 * NOTE: X509v1 certificate is also supported since x509.js 1.1.9. 1221 */ 1222 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) { 1223 var _ASN1HEX = ASN1HEX; 1224 var _getVbyList = _ASN1HEX.getVbyList; 1225 1226 var result = {}; 1227 var x, hSPKI, pubkey; 1228 result.algparam = null; 1229 1230 x = new X509(); 1231 x.readCertPEM(sCertPEM); 1232 1233 hSPKI = x.getPublicKeyHex(); 1234 result.keyhex = _getVbyList(hSPKI, 0, [1], "03").substr(2); 1235 result.algoid = _getVbyList(hSPKI, 0, [0, 0], "06"); 1236 1237 if (result.algoid === "2a8648ce3d0201") { // ecPublicKey 1238 result.algparam = _getVbyList(hSPKI, 0, [0, 1], "06"); 1239 }; 1240 1241 return result; 1242 }; 1243 1244 /* ====================================================================== 1245 * Specific V3 Extensions 1246 * ====================================================================== */ 1247 1248 X509.KEYUSAGE_NAME = [ 1249 "digitalSignature", 1250 "nonRepudiation", 1251 "keyEncipherment", 1252 "dataEncipherment", 1253 "keyAgreement", 1254 "keyCertSign", 1255 "cRLSign", 1256 "encipherOnly", 1257 "decipherOnly" 1258 ]; 1259