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