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