1 /* x509-2.1.1.js (c) 2012-2022 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-2022 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 10.6.1 x509 2.1.1 (2022-Nov-20) 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>policyMappings - {@link X509#getExtPolicyMappings}</li> 71 * <li>policyConstraints - {@link X509#getExtPolicyConstraints}</li> 72 * <li>inhibitAnyPolicy - {@link X509#getExtInhibitAnyPolicy}</li> 73 * <li>subjectAltName - {@link X509#getExtSubjectAltName}</li> 74 * <li>subjectAltName2 - {@link X509#getExtSubjectAltName2} (DEPRECATED)</li> 75 * <li>issuerAltName - {@link X509#getExtIssuerAltName}</li> 76 * <li>basicConstraints - {@link X509#getExtBasicConstraints}</li> 77 * <li>nameConstraints - {@link X509#getExtNameConstraints}</li> 78 * <li>extKeyUsage - {@link X509#getExtExtKeyUsage}</li> 79 * <li>extKeyUsage - {@link X509#getExtExtKeyUsageName} (DEPRECATED)</li> 80 * <li>cRLDistributionPoints - {@link X509#getExtCRLDistributionPoints}</li> 81 * <li>cRLDistributionPoints - {@link X509#getExtCRLDistributionPointsURI} (DEPRECATED)</li> 82 * <li>authorityInfoAccess - {@link X509#getExtAuthorityInfoAccess}</li> 83 * <li>authorityInfoAccess - {@link X509#getExtAIAInfo} (DEPRECATED)</li> 84 * <li>cRLNumber - {@link X509#getExtCRLNumber}</li> 85 * <li>cRLReason - {@link X509#getExtCRLReason}</li> 86 * <li>ocspNonce - {@link X509#getExtOcspNonce}</li> 87 * <li>ocspNoCheck - {@link X509#getExtOcspNoCheck}</li> 88 * <li>adobeTimeStamp - {@link X509#getExtAdobeTimeStamp}</li> 89 * </ul> 90 * </li> 91 * <li><b>UTILITIES</b> 92 * <ul> 93 * <li>reading PEM X.509 certificate - {@link X509#readCertPEM}</li> 94 * <li>reading hexadecimal string of X.509 certificate - {@link X509#readCertHex}</li> 95 * <li>get all certificate information - {@link X509#getInfo}</li> 96 * <li>get specified extension information - {@link X509#getExtInfo}</li> 97 * <li>verify signature value - {@link X509#verifySignature}</li> 98 * <li>utility for extensions - {@link X509#getCriticalExtV}</li> 99 * </ul> 100 * </li> 101 * </ul> 102 */ 103 function X509(params) { 104 var _ASN1HEX = ASN1HEX, 105 _getChildIdx = _ASN1HEX.getChildIdx, 106 _getV = _ASN1HEX.getV, 107 _dump = _ASN1HEX.dump, 108 _ASN1HEX_parse = _ASN1HEX.parse, 109 _getTLV = _ASN1HEX.getTLV, 110 _getVbyList = _ASN1HEX.getVbyList, 111 _getVbyListEx = _ASN1HEX.getVbyListEx, 112 _getTLVbyList = _ASN1HEX.getTLVbyList, 113 _getTLVbyListEx = _ASN1HEX.getTLVbyListEx, 114 _getIdxbyList = _ASN1HEX.getIdxbyList, 115 _getIdxbyListEx = _ASN1HEX.getIdxbyListEx, 116 _getVidx = _ASN1HEX.getVidx, 117 _getInt = _ASN1HEX.getInt, 118 _oidname = _ASN1HEX.oidname, 119 _hextooidstr = _ASN1HEX.hextooidstr, 120 _X509 = X509, 121 _pemtohex = pemtohex, 122 _PSSNAME2ASN1TLV, 123 _Error = Error; 124 125 try { 126 _PSSNAME2ASN1TLV = KJUR.asn1.x509.AlgorithmIdentifier.PSSNAME2ASN1TLV; 127 } catch (ex) {}; 128 this.HEX2STAG = {"0c": "utf8", "13": "prn", "16": "ia5", 129 "1a": "vis" , "1e": "bmp"}; 130 131 this.hex = null; 132 this.version = 0; // version (1: X509v1, 3: X509v3, others: unspecified) 133 this.foffset = 0; // field index offset (-1: for X509v1, 0: for X509v3) 134 this.aExtInfo = null; 135 136 // ===== get basic fields from hex ===================================== 137 138 /** 139 * get format version (X.509v1 or v3 certificate)<br/> 140 * @name getVersion 141 * @memberOf X509# 142 * @function 143 * @return {Number} 1 for X509v1, 3 for X509v3, otherwise 0 144 * @since jsrsasign 7.1.14 x509 1.1.13 145 * @description 146 * This method returns a format version of X.509 certificate. 147 * It returns 1 for X.509v1 certificate and 3 for v3 certificate. 148 * Otherwise returns 0. 149 * This method will be automatically called in 150 * {@link X509#readCertPEM}. After then, you can use 151 * {@link X509.version} parameter. 152 * @example 153 * var x = new X509(); 154 * x.readCertPEM(sCertPEM); 155 * version = x.getVersion(); // 1 or 3 156 * sn = x.getSerialNumberHex(); // return string like "01ad..." 157 */ 158 this.getVersion = function() { 159 if (this.hex === null || this.version !== 0) return this.version; 160 161 // check if the first item of tbsCertificate "[0] { INTEGER 2 }" 162 var hFirstObj = _getTLVbyList(this.hex, 0, [0, 0]); 163 if (hFirstObj.substr(0, 2) == "a0") { 164 var hVersionTLV = _getTLVbyList(hFirstObj, 0, [0]); 165 var iVersion = _getInt(hVersionTLV, 0); 166 if (iVersion < 0 || 2 < iVersion) { 167 throw new Error("malformed version field"); 168 } 169 this.version = iVersion + 1; 170 return this.version; 171 } else { 172 this.version = 1; 173 this.foffset = -1; 174 return 1; 175 } 176 }; 177 178 /** 179 * get hexadecimal string of serialNumber field of certificate.<br/> 180 * @name getSerialNumberHex 181 * @memberOf X509# 182 * @function 183 * @return {String} hexadecimal string of certificate serial number 184 * @example 185 * var x = new X509(); 186 * x.readCertPEM(sCertPEM); 187 * var sn = x.getSerialNumberHex(); // return string like "01ad..." 188 */ 189 this.getSerialNumberHex = function() { 190 return _getVbyListEx(this.hex, 0, [0, 0], "02"); 191 }; 192 193 /** 194 * get signature algorithm name in basic field 195 * @name getSignatureAlgorithmField 196 * @memberOf X509# 197 * @function 198 * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA, SHA512withRSAandMGF1) 199 * @since x509 1.1.8 200 * @see X509#getAlgorithmIdentifierName 201 * @description 202 * This method will get a name of signature algorithm in 203 * basic field of certificate. 204 * <br/> 205 * NOTE: From jsrsasign 8.0.21, RSA-PSS certificate is also supported. 206 * For supported RSA-PSS algorithm name and PSS parameters, 207 * see {@link X509#getSignatureAlgorithmField}. 208 * @example 209 * var x = new X509(); 210 * x.readCertPEM(sCertPEM); 211 * algName = x.getSignatureAlgorithmField(); 212 */ 213 this.getSignatureAlgorithmField = function() { 214 var hTLV = _getTLVbyListEx(this.hex, 0, [0, 1]); 215 return this.getAlgorithmIdentifierName(hTLV); 216 }; 217 218 /** 219 * get algorithm name name of AlgorithmIdentifier ASN.1 structure 220 * @name getAlgorithmIdentifierName 221 * @memberOf X509# 222 * @function 223 * @param {String} hTLV hexadecimal string of AlgorithmIdentifier 224 * @return {String} algorithm name (ex. SHA1withRSA, SHA256withECDSA, SHA512withRSAandMGF1, SHA1) 225 * @since jsrsasign 9.0.0 x509 2.0.0 226 * @description 227 * This method will get a name of AlgorithmIdentifier. 228 * <br/> 229 * @example 230 * var x = new X509(); 231 * algName = x.getAlgorithmIdentifierName("30..."); 232 */ 233 this.getAlgorithmIdentifierName = function(hTLV) { 234 for (var key in _PSSNAME2ASN1TLV) { 235 if (hTLV === _PSSNAME2ASN1TLV[key]) { 236 return key; 237 } 238 } 239 return _oidname(_getVbyListEx(hTLV, 0, [0], "06")); 240 }; 241 242 /** 243 * get JSON object of issuer field<br/> 244 * @name getIssuer 245 * @memberOf X509# 246 * @function 247 * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false) 248 * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false) 249 * @return {Array} JSON object of issuer field 250 * @since jsrsasign 9.0.0 x509 2.0.0 251 * @see X509#getX500Name 252 * 253 * @description 254 * Get a JSON object of an issuer field. 255 * <br> 256 * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 257 * supported to conclude a canonicalized name for caseIgnoreMatch 258 * desribed in <a href="https://tools.ietf.org/html/rfc4518"> 259 * RFC 4518</a>. 260 * 261 * @example 262 * var x = new X509(sCertPEM); 263 * x.getIssuer() → 264 * { array: [[{type:'C',value:'JP',ds:'prn'}],...], 265 * str: "/C=JP/..." } 266 * 267 * // with flags 268 * x.getIssuer(true, true) → 269 * { array: ..., 270 * str: "/C=JP/O= Test 123 ", 271 * canon: "/c=jp/o=test 123", 272 * hex: "30..." } 273 */ 274 this.getIssuer = function(flagCanon, flagHex) { 275 return this.getX500Name(this.getIssuerHex(), flagCanon, flagHex); 276 }; 277 278 /** 279 * get hexadecimal string of issuer field TLV of certificate.<br/> 280 * @name getIssuerHex 281 * @memberOf X509# 282 * @function 283 * @return {String} hexadecial string of issuer DN ASN.1 284 * @example 285 * var x = new X509(); 286 * x.readCertPEM(sCertPEM); 287 * var issuer = x.getIssuerHex(); // return string like "3013..." 288 */ 289 this.getIssuerHex = function() { 290 return _getTLVbyList(this.hex, 0, [0, 3 + this.foffset], "30"); 291 }; 292 293 /** 294 * get string of issuer field of certificate.<br/> 295 * @name getIssuerString 296 * @memberOf X509# 297 * @function 298 * @return {String} issuer DN string 299 * @see X509#getIssuer 300 * @example 301 * var x = new X509(); 302 * x.readCertPEM(sCertPEM); 303 * var dn1 = x.getIssuerString(); // return string like "/C=US/O=TEST" 304 * var dn2 = KJUR.asn1.x509.X500Name.compatToLDAP(dn1); // returns "O=TEST, C=US" 305 */ 306 this.getIssuerString = function() { 307 var pIssuer = this.getIssuer(); 308 return pIssuer.str; 309 }; 310 311 /** 312 * get JSON object of subject field<br/> 313 * @name getSubject 314 * @memberOf X509# 315 * @function 316 * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false) 317 * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false) 318 * @return {object} JSON object of subject field 319 * @since jsrsasign 9.0.0 x509 2.0.0 320 * @see X509#getX500Name 321 * 322 * @description 323 * Get a JSON object of a subject field. 324 * <br> 325 * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 326 * supported to conclude a canonicalized name for caseIgnoreMatch 327 * desribed in <a href="https://tools.ietf.org/html/rfc4518"> 328 * RFC 4518</a>. 329 * 330 * @example 331 * var x = new X509(sCertPEM); 332 * x.getSubject() → 333 * { array: [[{type:'C',value:'JP',ds:'prn'}],...], 334 * str: "/C=JP/..." } 335 * 336 * // with flags 337 * x.getSubject(true, true) → 338 * { array: ..., 339 * str: "/C=JP/O= Test 123 ", 340 * canon: "/c=jp/o=test 123", 341 * hex: "30..." } 342 */ 343 this.getSubject = function(flagCanon, flagHex) { 344 return this.getX500Name(this.getSubjectHex(), flagCanon, flagHex); 345 }; 346 347 /** 348 * get hexadecimal string of subject field of certificate.<br/> 349 * @name getSubjectHex 350 * @memberOf X509# 351 * @function 352 * @return {String} hexadecial string of subject DN ASN.1 353 * @example 354 * var x = new X509(); 355 * x.readCertPEM(sCertPEM); 356 * var subject = x.getSubjectHex(); // return string like "3013..." 357 */ 358 this.getSubjectHex = function() { 359 return _getTLVbyList(this.hex, 0, [0, 5 + this.foffset], "30"); 360 }; 361 362 /** 363 * get string of subject field of certificate.<br/> 364 * @name getSubjectString 365 * @memberOf X509# 366 * @function 367 * @return {String} subject DN string 368 * @see X509#getSubject 369 * @example 370 * var x = new X509(); 371 * x.readCertPEM(sCertPEM); 372 * var dn1 = x.getSubjectString(); // return string like "/C=US/O=TEST" 373 * var dn2 = KJUR.asn1.x509.X500Name.compatToLDAP(dn1); // returns "O=TEST, C=US" 374 */ 375 this.getSubjectString = function() { 376 var pSubject = this.getSubject(); 377 return pSubject.str; 378 }; 379 380 /** 381 * get notBefore field string of certificate.<br/> 382 * @name getNotBefore 383 * @memberOf X509# 384 * @function 385 * @return {String} not before time value (ex. "151231235959Z") 386 * @example 387 * var x = new X509(); 388 * x.readCertPEM(sCertPEM); 389 * var notBefore = x.getNotBefore(); // return string like "151231235959Z" 390 */ 391 this.getNotBefore = function() { 392 var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 0]); 393 s = s.replace(/(..)/g, "%$1"); 394 s = decodeURIComponent(s); 395 return s; 396 }; 397 398 /** 399 * get notAfter field string of certificate.<br/> 400 * @name getNotAfter 401 * @memberOf X509# 402 * @function 403 * @return {String} not after time value (ex. "151231235959Z") 404 * @example 405 * var x = new X509(); 406 * x.readCertPEM(sCertPEM); 407 * var notAfter = x.getNotAfter(); // return string like "151231235959Z" 408 */ 409 this.getNotAfter = function() { 410 var s = _getVbyList(this.hex, 0, [0, 4 + this.foffset, 1]); 411 s = s.replace(/(..)/g, "%$1"); 412 s = decodeURIComponent(s); 413 return s; 414 }; 415 416 /** 417 * get a hexadecimal string of subjectPublicKeyInfo field.<br/> 418 * @name getPublicKeyHex 419 * @memberOf X509# 420 * @function 421 * @return {String} ASN.1 SEQUENCE hexadecimal string of subjectPublicKeyInfo field 422 * @since jsrsasign 7.1.4 x509 1.1.13 423 * @deprecated since jsrsasign 10.5.7 x509 2.0.13. Please use {@link X509#getSPKI} instead. 424 * 425 * @example 426 * x = new X509(sCertPEM); 427 * hSPKI = x.getPublicKeyHex(); // return string like "30820122..." 428 */ 429 this.getPublicKeyHex = function() { 430 return this.getSPKI(); 431 }; 432 433 /** 434 * get ASN.1 TLV hexadecimal string of subjectPublicKeyInfo field.<br/> 435 * @name getSPKI 436 * @memberOf X509# 437 * @function 438 * @return {string} ASN.1 SEQUENCE hexadecimal string of subjectPublicKeyInfo field 439 * @since jsrsasign 10.5.8 x509 2.0.13 440 * @see X509#getPublicKeyHex 441 * @see X509#getSPKIValue 442 * 443 * @description 444 * Get a hexadecimal string of SubjectPublicKeyInfo ASN.1 TLV of the certificate.<br/> 445 * <pre> 446 * SubjectPublicKeyInfo ::= SEQUENCE { 447 * algorithm AlgorithmIdentifier, 448 * subjectPublicKey BIT STRING } 449 * </pre> 450 * 451 * @example 452 * x = new X509(sCertPEM); 453 * hSPKI = x.getSPKI(); // return string like "30820122..." 454 */ 455 this.getSPKI = function() { 456 return _getTLVbyList(this.hex, 0, [0, 6 + this.foffset], "30"); 457 }; 458 459 /** 460 * get hexadecimal string of subjectPublicKey of subjectPublicKeyInfo field.<br/> 461 * @name getSPKIValue 462 * @memberOf X509# 463 * @function 464 * @return {string} ASN.1 hexadecimal string of subjectPublicKey 465 * @since jsrsasign 10.5.8 x509 2.0.13 466 * @see X509#getSPKI 467 * 468 * @description 469 * Get a hexadecimal string of subjectPublicKey ASN.1 value of SubjectPublicKeyInfo 470 * of the certificate without unusedbit "00". 471 * The "subjectPublicKey" is encapsulated by BIT STRING. 472 * This method returns BIT STRING value without unusedbits. 473 * <br/> 474 * <pre> 475 * SubjectPublicKeyInfo ::= SEQUENCE { 476 * algorithm AlgorithmIdentifier, 477 * subjectPublicKey BIT STRING } 478 * </pre> 479 * 480 * @example 481 * x = new X509(sCertPEM); 482 * hSPKIValue = x.getSPKIValue(); // without BIT STRING Encapusulation. 483 */ 484 this.getSPKIValue = function() { 485 var hSPKI = this.getSPKI(); 486 if (hSPKI == null) return null; 487 return _getVbyList(hSPKI, 0, [1], "03", true); // true: remove unused bit 488 }; 489 490 /** 491 * get a string index of subjectPublicKeyInfo field for hexadecimal string certificate.<br/> 492 * @name getPublicKeyIdx 493 * @memberOf X509# 494 * @function 495 * @return {Number} string index of subjectPublicKeyInfo field for hexadecimal string certificate. 496 * @since jsrsasign 7.1.4 x509 1.1.13 497 * @example 498 * x = new X509(); 499 * x.readCertPEM(sCertPEM); 500 * idx = x.getPublicKeyIdx(); // return string index in x.hex parameter 501 */ 502 this.getPublicKeyIdx = function() { 503 return _getIdxbyList(this.hex, 0, [0, 6 + this.foffset], "30"); 504 }; 505 506 /** 507 * get a string index of contents of subjectPublicKeyInfo BITSTRING value from hexadecimal certificate<br/> 508 * @name getPublicKeyContentIdx 509 * @memberOf X509# 510 * @function 511 * @return {Integer} string index of key contents 512 * @since jsrsasign 8.0.0 x509 1.2.0 513 * @example 514 * x = new X509(); 515 * x.readCertPEM(sCertPEM); 516 * idx = x.getPublicKeyContentIdx(); // return string index in x.hex parameter 517 */ 518 // NOTE: Without BITSTRING encapsulation. 519 this.getPublicKeyContentIdx = function() { 520 var idx = this.getPublicKeyIdx(); 521 return _getIdxbyList(this.hex, idx, [1, 0], "30"); 522 }; 523 524 /** 525 * get a RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field.<br/> 526 * @name getPublicKey 527 * @memberOf X509# 528 * @function 529 * @return {Object} RSAKey/ECDSA/DSA public key object of subjectPublicKeyInfo field 530 * @since jsrsasign 7.1.4 x509 1.1.13 531 * @example 532 * x = new X509(); 533 * x.readCertPEM(sCertPEM); 534 * pubkey= x.getPublicKey(); 535 */ 536 this.getPublicKey = function() { 537 return KEYUTIL.getKey(this.getPublicKeyHex(), null, "pkcs8pub"); 538 }; 539 540 /** 541 * get signature algorithm name from hexadecimal certificate data 542 * @name getSignatureAlgorithmName 543 * @memberOf X509# 544 * @function 545 * @return {String} signature algorithm name (ex. SHA1withRSA, SHA256withECDSA) 546 * @since jsrsasign 7.2.0 x509 1.1.14 547 * @see X509#getAlgorithmIdentifierName 548 * @description 549 * This method will get signature algorithm name of certificate: 550 * @example 551 * var x = new X509(); 552 * x.readCertPEM(sCertPEM); 553 * x.getSignatureAlgorithmName() → "SHA256withRSA" 554 */ 555 this.getSignatureAlgorithmName = function() { 556 var hTLV = _getTLVbyList(this.hex, 0, [1], "30"); 557 return this.getAlgorithmIdentifierName(hTLV); 558 }; 559 560 /** 561 * get signature value as hexadecimal string<br/> 562 * @name getSignatureValueHex 563 * @memberOf X509# 564 * @function 565 * @return {String} signature value hexadecimal string without BitString unused bits 566 * @since jsrsasign 7.2.0 x509 1.1.14 567 * 568 * @description 569 * This method will get signature value of certificate: 570 * 571 * @example 572 * var x = new X509(); 573 * x.readCertPEM(sCertPEM); 574 * x.getSignatureValueHex() &rarr "8a4c47913..." 575 */ 576 this.getSignatureValueHex = function() { 577 return _getVbyList(this.hex, 0, [2], "03", true); 578 }; 579 580 /** 581 * verifies signature value by public key<br/> 582 * @name verifySignature 583 * @memberOf X509# 584 * @function 585 * @param {Object} pubKey public key object 586 * @return {Boolean} true if signature value is valid otherwise false 587 * @since jsrsasign 7.2.0 x509 1.1.14 588 * 589 * @description 590 * This method verifies signature value of hexadecimal string of 591 * X.509 certificate by specified public key object. 592 * The signature algorithm used to verify will refer 593 * signatureAlgorithm field. (See {@link X509#getSignatureAlgorithmField}) 594 * RSA-PSS signature algorithms (SHA{,256,384,512}withRSAandMGF1) 595 * are available. 596 * 597 * @example 598 * pubKey = KEYUTIL.getKey(pemPublicKey); // or certificate 599 * x = new X509(); 600 * x.readCertPEM(pemCert); 601 * x.verifySignature(pubKey) → true, false or raising exception 602 */ 603 this.verifySignature = function(pubKey) { 604 var algName = this.getSignatureAlgorithmField(); 605 var hSigVal = this.getSignatureValueHex(); 606 var hTbsCert = _getTLVbyList(this.hex, 0, [0], "30"); 607 608 var sig = new KJUR.crypto.Signature({alg: algName}); 609 sig.init(pubKey); 610 sig.updateHex(hTbsCert); 611 return sig.verify(hSigVal); 612 }; 613 614 // ===== parse extension ====================================== 615 /** 616 * set array of X.509v3 and CSR extesion information such as extension OID, criticality and value index. (DEPRECATED)<br/> 617 * @name parseExt 618 * @memberOf X509# 619 * @function 620 * @param {String} hCSR - PEM string of certificate signing requrest(CSR) (OPTION) 621 * @since jsrsasign 7.2.0 x509 1.1.14 622 * @deprecated jsrsasign 9.1.1 x509 2.0.1 623 * 624 * @description 625 * This method will set an array of X.509v3 extension information having 626 * following parameters: 627 * <ul> 628 * <li>oid - extension OID (ex. 2.5.29.19)</li> 629 * <li>critical - true or false</li> 630 * <li>vidx - string index for extension value</li> 631 * <br/> 632 * When you want to parse extensionRequest of CSR, 633 * argument 'hCSR' shall be specified. 634 * <br/> 635 * NOTE: CSR is supported from jsrsasign 8.0.20 x509 1.1.22. 636 * <br/> 637 * This method and X509.aExtInfo property 638 * have been *deprecated* since jsrsasign 9.1.1. 639 * All extension parser method such as X509.getExt* shall be 640 * call with argument "hExtV" and "critical" explicitly. 641 * 642 * @example 643 * x = new X509(); 644 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 645 * 646 * x.aExtInfo → 647 * [ { oid: "2.5.29,19", critical: true, vidx: 2504 }, ... ] 648 * 649 * // to parse CSR 650 * X = new X509() 651 * x.parseExt("-----BEGIN CERTIFICATE REQUEST-----..."); 652 * x.aExtInfo → 653 * [ { oid: "2.5.29,19", critical: true, vidx: 2504 }, ... ] 654 */ 655 this.parseExt = function(hCSR) { 656 var iExtSeq, aExtIdx, h; 657 658 if (hCSR === undefined) { 659 h = this.hex; 660 if (this.version !== 3) return -1; 661 iExtSeq = _getIdxbyList(h, 0, [0, 7, 0], "30"); 662 aExtIdx = _getChildIdx(h, iExtSeq); 663 } else { 664 h = pemtohex(hCSR); 665 var idx1 = _getIdxbyList(h, 0, [0, 3, 0, 0], "06"); 666 667 if (_getV(h, idx1) != "2a864886f70d01090e") { 668 this.aExtInfo = new Array(); 669 return; 670 } 671 672 iExtSeq = _getIdxbyList(h, 0, [0, 3, 0, 1, 0], "30"); 673 aExtIdx = _getChildIdx(h, iExtSeq); 674 675 this.hex = h; 676 } 677 678 this.aExtInfo = new Array(); 679 for (var i = 0; i < aExtIdx.length; i++) { 680 var item = {}; 681 item.critical = false; 682 var a = _getChildIdx(h, aExtIdx[i]); 683 var offset = 0; 684 685 if (a.length === 3) { 686 item.critical = true; 687 offset = 1; 688 } 689 690 item.oid = _ASN1HEX.hextooidstr(_getVbyList(h, aExtIdx[i], [0], "06")); 691 var octidx = _getIdxbyList(h, aExtIdx[i], [1 + offset]); 692 item.vidx = _getVidx(h, octidx); 693 this.aExtInfo.push(item); 694 } 695 }; 696 697 /** 698 * get a X.509v3 extesion information such as extension OID, criticality and value index for specified oid or name.<br/> 699 * @name getExtInfo 700 * @memberOf X509# 701 * @function 702 * @param {String} oidOrName X.509 extension oid or name (ex. keyUsage or 2.5.29.19) 703 * @return X.509 extension information such as extension OID or value indx (see {@link X509#parseExt}) 704 * @since jsrsasign 7.2.0 x509 1.1.14 705 * @description 706 * This method will get an X.509v3 extension information JSON object 707 * having extension OID, criticality and value idx for specified 708 * extension OID or name. 709 * If there is no such extension, this returns undefined. 710 * @example 711 * x = new X509(); 712 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 713 * 714 * x.getExtInfo("keyUsage") → { oid: "2.5.29.15", critical: true, vidx: 1714 } 715 * x.getExtInfo("unknownExt") → undefined 716 */ 717 this.getExtInfo = function(oidOrName) { 718 var a = this.aExtInfo; 719 var oid = oidOrName; 720 if (! oidOrName.match(/^[0-9.]+$/)) { 721 oid = KJUR.asn1.x509.OID.name2oid(oidOrName); 722 } 723 if (oid === '') return undefined; 724 725 for (var i = 0; i < a.length; i++) { 726 if (a[i].oid === oid) return a[i]; 727 } 728 return undefined; 729 }; 730 731 /** 732 * get extension value and critical flag value<br/> 733 * @name getCriticalExtV 734 * @memberOf X509# 735 * @function 736 * @param {string} extname name string of the extension 737 * @param {string} hExtV hexadecimal string of extension 738 * @param {boolean} critical flag 739 * @return {Array} extension value hex and critical flag 740 * @since jsrsasign 10.6.1 x509 2.1.1 741 * 742 * @description 743 * This method is an utility method for all getExt* of extensions. 744 * 745 * @example 746 * x = new X509(sCertPEM); 747 * x.getCriticalExtV("inhibitAnyPolicy") &rarr ["020103", true] // get from X509 object 748 * x.getCriticalExtV("inhibitAnyPolicy", 749 * "020104", 750 * true) &rarr ["020104", true] // by argument of method. 751 */ 752 this.getCriticalExtV = function(extname, hExtV, critical) { 753 if (hExtV != undefined) return [hExtV, critical]; 754 var info = this.getExtInfo(extname); 755 if (info == undefined) return [null, null]; 756 return [_getTLV(this.hex, info.vidx), info.critical]; 757 }; 758 759 /** 760 * get BasicConstraints extension value as object in the certificate 761 * @name getExtBasicConstraints 762 * @memberOf X509# 763 * @function 764 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 765 * @param {Boolean} critical flag (OPTIONAL) 766 * @return {Array} JSON object of BasicConstraints parameter or undefined 767 * @since jsrsasign 7.2.0 x509 1.1.14 768 * @see KJUR.asn1.x509.BasicConstraints 769 * @description 770 * This method will get basic constraints extension value as object with following paramters. 771 * <ul> 772 * <li>{Boolean}cA - CA flag whether CA or not</li> 773 * <li>{Integer}pathLen - maximum intermediate certificate length</li> 774 * <li>{Boolean}critical - critical flag</li> 775 * </ul> 776 * There are use cases for return values: 777 * <ul> 778 * <li>{cA:true,pathLen:3,critical:true} - cA flag is true and pathLen is 3</li> 779 * <li>{cA:true,critical:true} - cA flag is true and no pathLen</li> 780 * <li>{} - basic constraints has no value in case of end entity certificate</li> 781 * <li>undefined - there is no basic constraints extension</li> 782 * </ul> 783 * @example 784 * x = new X509(); 785 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 786 * x.getExtBasicConstraints() → {cA:true,pathLen:3,critical:true} 787 */ 788 this.getExtBasicConstraints = function(hExtV, critical) { 789 if (hExtV === undefined && critical === undefined) { 790 var info = this.getExtInfo("basicConstraints"); 791 if (info === undefined) return undefined; 792 hExtV = _getTLV(this.hex, info.vidx); 793 critical = info.critical; 794 } 795 796 var result = {extname:"basicConstraints"}; 797 if (critical) result.critical = true; 798 799 if (hExtV === '3000') return result; 800 if (hExtV === '30030101ff') { 801 result.cA = true; 802 return result; 803 } 804 if (hExtV.substr(0, 12) === '30060101ff02') { 805 var pathLexHex = _getV(hExtV, 10); 806 var pathLen = parseInt(pathLexHex, 16); 807 result.cA = true; 808 result.pathLen = pathLen; 809 return result; 810 } 811 throw new Error("hExtV parse error: " + hExtV); 812 }; 813 814 /** 815 * get NameConstraints extension value as object in the certificate<br/> 816 * @name getExtNameConstraints 817 * @memberOf X509# 818 * @function 819 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 820 * @param {Boolean} critical flag (OPTIONAL) 821 * @return {Object} JSON object of NamConstraints parameter or undefined 822 * @since jsrsasign 10.5.16 x509 2.0.16 823 * @see KJUR.asn1.x509.NameConstraints 824 * @see KJUR.asn1.x509.GeneralSubtree 825 * @see KJUR.asn1.x509.GeneralName 826 * @see X509#getGeneralSubtree 827 * @see X509#getGeneralName 828 * 829 * @description 830 * This method will get name constraints extension value as object with following paramters. 831 * <ul> 832 * <li>{Array}permit - array of {@link KJUR.asn1.x509.GeneralSubtree} parameter</li> 833 * <li>{Array}exclude - array of {@link KJUR.asn1.x509.GeneralSubtree} parameter</li> 834 * <li>{Boolean}critical - critical flag</li> 835 * </ul> 836 * 837 * @example 838 * x = new X509(sCertPEM); 839 * x.getExtNameConstraints() → { 840 * critical: true, 841 * permit: [{dns: 'example.com'},{rfc822: 'john@example.com'}], 842 * exclude: [{dn: {...X500Name parameter...}}] 843 * } 844 */ 845 this.getExtNameConstraints = function(hExtV, critical) { 846 var aExtVCritical = this.getCriticalExtV("nameConstraints", hExtV, critical); 847 hExtV = aExtVCritical[0]; 848 critical = aExtVCritical[1]; 849 if (hExtV == null) return undefined; 850 var result = {extname:"nameConstraints"}; 851 if (critical) result.critical = true; 852 853 var aIdx = _getChildIdx(hExtV, 0); 854 for (var i = 0; i < aIdx.length; i++) { 855 var aList = []; 856 var aIdx2 = _getChildIdx(hExtV, aIdx[i]); 857 for (var j = 0; j < aIdx2.length; j++) { 858 var hSub = _getTLV(hExtV, aIdx2[j]); 859 var p = this.getGeneralSubtree(hSub); 860 aList.push(p); 861 } 862 863 var tag = hExtV.substr(aIdx[i], 2); 864 if (tag == "a0") { 865 result.permit = aList; 866 } else if (tag == "a1") { 867 result.exclude = aList; 868 } 869 } 870 return result; 871 }; 872 873 /** 874 * get GeneralSubtree ASN.1 structure parameter as JSON object<br/> 875 * @name getGeneralSubtree 876 * @memberOf X509# 877 * @function 878 * @param {String} h hexadecimal string of GeneralSubtree 879 * @return {Object} JSON object of GeneralSubtree parameters or undefined 880 * @since jsrsasign 10.5.16 x509 2.0.16 881 * @see KJUR.asn1.x509.GeneralSubtree 882 * @see KJUR.asn1.x509.GeneralName 883 * @see X509#getExtNameConstraints 884 * @see X509#getGeneralName 885 * 886 * @description 887 * This method will get GeneralSubtree parameters defined in 888 * <a href="https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10"> 889 * RFC 5280 4.2.1.10</a>. 890 * <pre> 891 * GeneralSubtree ::= SEQUENCE { 892 * base GeneralName, 893 * minimum [0] BaseDistance DEFAULT 0, 894 * maximum [1] BaseDistance OPTIONAL } 895 * BaseDistance ::= INTEGER (0..MAX) 896 * </pre> 897 * Result of this method can be passed to 898 * {@link KJUR.asn1.x509.GeneralSubtree} constructor. 899 * 900 * @example 901 * x = new X509(sPEM); 902 * x.getGeneralSubtree("30...") → { dn: ...X500NameObject..., min: 1, max: 3 } 903 * x.getGeneralSubtree("30...") → { dns: ".example.com" } 904 */ 905 this.getGeneralSubtree = function(h) { 906 var aIdx = _getChildIdx(h, 0); 907 var len = aIdx.length; 908 if (len < 1 || 2 < len) throw new Error("wrong num elements"); 909 var result = this.getGeneralName(_getTLV(h, aIdx[0])); 910 911 for (var i = 1; i < len; i++) { 912 var tag = h.substr(aIdx[i], 2); 913 var hV = _getV(h, aIdx[i]); 914 var minmaxValue = parseInt(hV, 16); 915 if (tag == "80") result.min = minmaxValue; 916 if (tag == "81") result.max = minmaxValue; 917 } 918 return result; 919 }; 920 921 /** 922 * get KeyUsage extension value as JSON object 923 * @memberOf X509# 924 * @function 925 * @name getExtKeyUsage 926 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 927 * @param {Boolean} critical flag (OPTIONAL) 928 * @return {Array} JSON object of KeyUsage parameter or undefined 929 * @since jsrsasign 9.0.0 x509 2.0.0 930 * @see KJUR.asn1.x509.KeyUsage 931 * @see X509#getExtKeyUsageString 932 * @description 933 * This method parse keyUsage extension. When arguments are 934 * not specified, its extension in X509 object will be parsed. 935 * Result of this method can be passed to 936 * {@link KJUR.asn1.x509.KeyUsage} constructor. 937 * <br> 938 * When hExtV and critical specified as arguments, return value 939 * will be generated from them. 940 * <pre> 941 * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } 942 * KeyUsage ::= BIT STRING { 943 * digitalSignature (0), 944 * nonRepudiation (1), 945 * keyEncipherment (2), 946 * dataEncipherment (3), 947 * keyAgreement (4), 948 * keyCertSign (5), 949 * cRLSign (6), 950 * encipherOnly (7), 951 * decipherOnly (8) } 952 * </pre> 953 * @example 954 * x = new X509(); 955 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 956 * x.getExtKeyUsage() → 957 * { 958 * critial: true, 959 * names: ["digitalSignature", "decipherOnly"] 960 * } 961 * 962 * x = new X509(); 963 * x.getExtKeyUsage("306230...") 964 * x.getExtKeyUsage("306230...", true) 965 */ 966 this.getExtKeyUsage = function(hExtV, critical) { 967 var aExtVCritical = this.getCriticalExtV("keyUsage", hExtV, critical); 968 hExtV = aExtVCritical[0]; 969 critical = aExtVCritical[1]; 970 if (hExtV == null) return undefined; 971 var result = {extname:"keyUsage"}; 972 if (critical) result.critical = true; 973 974 result.names = this.getExtKeyUsageString(hExtV).split(","); 975 976 return result; 977 }; 978 979 /** 980 * get KeyUsage extension value as binary string in the certificate<br/> 981 * @name getExtKeyUsageBin 982 * @memberOf X509# 983 * @function 984 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 985 * @return {String} binary string of key usage bits (ex. '101') 986 * @since jsrsasign 7.2.0 x509 1.1.14 987 * @see X509#getExtKeyUsage 988 * @description 989 * This method will get key usage extension value 990 * as binary string such like '101'. 991 * Key usage bits definition is in the RFC 5280. 992 * If there is no key usage extension in the certificate, 993 * it returns empty string (i.e. ''). 994 * <br/> 995 * NOTE: argument 'hExtV' supported since jsrsasign 9.0.0 x509 2.0.0. 996 * @example 997 * x = new X509(); 998 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 999 * x.getExtKeyUsageBin() → '101' 1000 * // 1 - digitalSignature 1001 * // 0 - nonRepudiation 1002 * // 1 - keyEncipherment 1003 */ 1004 this.getExtKeyUsageBin = function(hExtV) { 1005 if (hExtV === undefined) { 1006 var info = this.getExtInfo("keyUsage"); 1007 if (info === undefined) return ''; 1008 hExtV = _getTLV(this.hex, info.vidx); 1009 } 1010 1011 if (hExtV.length != 8 && hExtV.length != 10) 1012 throw new Error("malformed key usage value: " + hExtV); 1013 1014 var s = "000000000000000" + parseInt(hExtV.substr(6), 16).toString(2); 1015 if (hExtV.length == 8) s = s.slice(-8); 1016 if (hExtV.length == 10) s = s.slice(-16); 1017 s = s.replace(/0+$/, ''); 1018 if (s == '') s = '0'; 1019 return s; 1020 }; 1021 1022 /** 1023 * get KeyUsage extension value as names in the certificate<br/> 1024 * @name getExtKeyUsageString 1025 * @memberOf X509# 1026 * @function 1027 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1028 * @return {String} comma separated string of key usage 1029 * @since jsrsasign 7.2.0 x509 1.1.14 1030 * @see X509#getExtKeyUsage 1031 * @description 1032 * This method will get key usage extension value 1033 * as comma separated string of usage names. 1034 * If there is no key usage extension in the certificate, 1035 * it returns empty string (i.e. ''). 1036 * <br/> 1037 * NOTE: argument 'hExtV' supported since jsrsasign 9.0.0 x509 2.0.0. 1038 * @example 1039 * x = new X509(); 1040 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1041 * x.getExtKeyUsageString() → "digitalSignature,keyEncipherment" 1042 */ 1043 this.getExtKeyUsageString = function(hExtV) { 1044 var bKeyUsage = this.getExtKeyUsageBin(hExtV); 1045 var a = new Array(); 1046 for (var i = 0; i < bKeyUsage.length; i++) { 1047 if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]); 1048 } 1049 return a.join(","); 1050 }; 1051 1052 /** 1053 * get subjectKeyIdentifier value as hexadecimal string in the certificate<br/> 1054 * @name getExtSubjectKeyIdentifier 1055 * @memberOf X509# 1056 * @function 1057 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1058 * @param {Boolean} critical flag (OPTIONAL) 1059 * @return {Array} JSON object of SubjectKeyIdentifier parameter or undefined 1060 * @since jsrsasign 7.2.0 x509 1.1.14 1061 * @description 1062 * This method will get 1063 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.2"> 1064 * SubjectKeyIdentifier extension</a> value as JSON object. 1065 * <br> 1066 * When hExtV and critical specified as arguments, return value 1067 * will be generated from them. 1068 * If there is no such extension in the certificate, it returns undefined. 1069 * <br> 1070 * Result of this method can be passed to 1071 * {@link KJUR.asn1.x509.SubjectKeyIdentifier} constructor. 1072 * <pre> 1073 * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } 1074 * SubjectKeyIdentifier ::= KeyIdentifier 1075 * </pre> 1076 * <br> 1077 * CAUTION: 1078 * Returned JSON value format have been changed without 1079 * backward compatibility since jsrsasign 9.0.0 x509 2.0.0. 1080 * 1081 * @example 1082 * x = new X509(); 1083 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1084 * x.getExtSubjectKeyIdentifier() → 1085 * { kid: {hex: "1b3347ab..."}, critical: true }; 1086 */ 1087 this.getExtSubjectKeyIdentifier = function(hExtV, critical) { 1088 if (hExtV === undefined && critical === undefined) { 1089 var info = this.getExtInfo("subjectKeyIdentifier"); 1090 if (info === undefined) return undefined; 1091 hExtV = _getTLV(this.hex, info.vidx); 1092 critical = info.critical; 1093 } 1094 1095 var result = {extname:"subjectKeyIdentifier"}; 1096 if (critical) result.critical = true; 1097 1098 var hKID = _getV(hExtV, 0); 1099 result.kid = {hex: hKID}; 1100 1101 return result; 1102 }; 1103 1104 /** 1105 * get authorityKeyIdentifier value as JSON object in the certificate<br/> 1106 * @name getExtAuthorityKeyIdentifier 1107 * @memberOf X509# 1108 * @function 1109 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1110 * @param {Boolean} critical flag (OPTIONAL) 1111 * @return {Array} JSON object of AuthorityKeyIdentifier parameter or undefined 1112 * @since jsrsasign 7.2.0 x509 1.1.14 1113 * @see KJUR.asn1.x509.AuthorityKeyIdentifier 1114 * @description 1115 * This method will get 1116 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.1"> 1117 * AuthorityKeyIdentifier extension</a> value as JSON object. 1118 * <br> 1119 * When hExtV and critical specified as arguments, return value 1120 * will be generated from them. 1121 * If there is no such extension in the certificate, it returns undefined. 1122 * <br/> 1123 * Result of this method can be passed to 1124 * {@link KJUR.asn1.x509.AuthorityKeyIdentifier} constructor. 1125 * <pre> 1126 * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } 1127 * AuthorityKeyIdentifier ::= SEQUENCE { 1128 * keyIdentifier [0] KeyIdentifier OPTIONAL, 1129 * authorityCertIssuer [1] GeneralNames OPTIONAL, 1130 * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } 1131 * KeyIdentifier ::= OCTET STRING 1132 * </pre> 1133 * Constructor may have following parameters: 1134 * <ul> 1135 * <li>{Array}kid - JSON object of {@link KJUR.asn1.DEROctetString} parameters</li> 1136 * <li>{Array}issuer - JSON object of {@link KJUR.asn1.x509.X500Name} parameters</li> 1137 * <li>{Array}sn - JSON object of {@link KJUR.asn1.DERInteger} parameters</li> 1138 * <li>{Boolean}critical - critical flag</li> 1139 * </ul> 1140 * <br> 1141 * NOTE: The 'authorityCertIssuer' and 'authorityCertSerialNumber' 1142 * supported since jsrsasign 9.0.0 x509 2.0.0. 1143 * @example 1144 * x = new X509(); 1145 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1146 * x.getExtAuthorityKeyIdentifier() → 1147 * { kid: {hex: "1234abcd..."}, 1148 * issuer: {hex: "30..."}, 1149 * sn: {hex: "1234..."}, 1150 * critical: true} 1151 */ 1152 this.getExtAuthorityKeyIdentifier = function(hExtV, critical) { 1153 if (hExtV === undefined && critical === undefined) { 1154 var info = this.getExtInfo("authorityKeyIdentifier"); 1155 if (info === undefined) return undefined; 1156 hExtV = _getTLV(this.hex, info.vidx); 1157 critical = info.critical; 1158 } 1159 1160 var result = {extname:"authorityKeyIdentifier"}; 1161 if (critical) result.critical = true; 1162 1163 var a = _getChildIdx(hExtV, 0); 1164 for (var i = 0; i < a.length; i++) { 1165 var tag = hExtV.substr(a[i], 2); 1166 if (tag === "80") { 1167 result.kid = {hex: _getV(hExtV, a[i])}; 1168 } 1169 if (tag === "a1") { 1170 var hGNS = _getTLV(hExtV, a[i]); 1171 var gnsParam = this.getGeneralNames(hGNS); 1172 result.issuer = gnsParam[0]["dn"]; 1173 } 1174 if (tag === "82") { 1175 result.sn = {hex: _getV(hExtV, a[i])}; 1176 } 1177 } 1178 return result; 1179 }; 1180 1181 /** 1182 * get extKeyUsage value as JSON object 1183 * @name getExtExtKeyUsage 1184 * @memberOf X509# 1185 * @function 1186 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1187 * @param {Boolean} critical flag (OPTIONAL) 1188 * @return {Array} JSON object of ExtKeyUsage parameter or undefined 1189 * @return {Object} JSONarray of extended key usage ID name or oid 1190 * @since jsrsasign 9.0.0 x509 2.0.0 1191 * @see KJUR.asn1.x509.ExtKeyUsage 1192 * @description 1193 * This method parse extKeyUsage extension. When arguments are 1194 * not specified, its extension in X509 object will be parsed. 1195 * Result of this method can be passed to 1196 * {@link KJUR.asn1.x509.ExtKeyUsage} constructor. 1197 * <br> 1198 * When hExtV and critical specified as arguments, return value 1199 * will be generated from them. 1200 * @example 1201 * x = new X509(); 1202 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1203 * x.getExtExtKeyUsage() → 1204 * { array: ["clientAuth", "emailProtection", "1.3.6.1.4.1.311.10.3.4"], 1205 * critical: true}, 1206 */ 1207 this.getExtExtKeyUsage = function(hExtV, critical) { 1208 if (hExtV === undefined && critical === undefined) { 1209 var info = this.getExtInfo("extKeyUsage"); 1210 if (info === undefined) return undefined; 1211 hExtV = _getTLV(this.hex, info.vidx); 1212 critical = info.critical; 1213 } 1214 1215 var result = {extname:"extKeyUsage",array:[]}; 1216 if (critical) result.critical = true; 1217 1218 var a = _getChildIdx(hExtV, 0); 1219 1220 for (var i = 0; i < a.length; i++) { 1221 result.array.push(_oidname(_getV(hExtV, a[i]))); 1222 } 1223 1224 return result; 1225 }; 1226 1227 /** 1228 * get extKeyUsage value as array of name string in the certificate(DEPRECATED)<br/> 1229 * @name getExtExtKeyUsageName 1230 * @memberOf X509# 1231 * @function 1232 * @return {Object} array of extended key usage ID name or oid 1233 * @since jsrsasign 7.2.0 x509 1.1.14 1234 * @deprecated since jsrsasign 9.0.0 x509 2.0.0 1235 * @description 1236 * This method will get extended key usage extension value 1237 * as array of name or OID string. 1238 * If there is this in the certificate, it returns undefined; 1239 * <br> 1240 * NOTE: Supported extended key usage ID names are defined in 1241 * name2oidList parameter in asn1x509.js file. 1242 * @example 1243 * x = new X509(); 1244 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1245 * x.getExtExtKeyUsageName() → ["serverAuth", "clientAuth", "0.1.2.3.4.5"] 1246 */ 1247 this.getExtExtKeyUsageName = function() { 1248 var info = this.getExtInfo("extKeyUsage"); 1249 if (info === undefined) return info; 1250 1251 var result = new Array(); 1252 1253 var h = _getTLV(this.hex, info.vidx); 1254 if (h === '') return result; 1255 1256 var a = _getChildIdx(h, 0); 1257 for (var i = 0; i < a.length; i++) { 1258 result.push(_oidname(_getV(h, a[i]))); 1259 } 1260 1261 return result; 1262 }; 1263 1264 /** 1265 * get subjectAltName value as array of string in the certificate 1266 * @name getExtSubjectAltName 1267 * @memberOf X509# 1268 * @function 1269 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1270 * @param {Boolean} critical flag (OPTIONAL) 1271 * @return {Array} JSON object of SubjectAltName parameters or undefined 1272 * @since jsrsasign 7.2.0 x509 1.1.14 1273 * @see KJUR.asn1.x509.SubjectAltName 1274 * @see X509#getExtIssuerAltName 1275 * @description 1276 * This method will get subjectAltName value 1277 * as an array of JSON object which has properties defined 1278 * in {@link KJUR.asn1.x509.SubjectAltName}. 1279 * Result of this method can be passed to 1280 * {@link KJUR.asn1.x509.SubjectAltName} constructor. 1281 * If there is no this extension in the certificate, 1282 * it returns undefined. 1283 * <br> 1284 * When hExtV and critical specified as arguments, return value 1285 * will be generated from them. 1286 * <br> 1287 * CAUTION: return value of JSON object format have been changed 1288 * from jsrsasign 9.0.0 x509 2.0.0 without backword compatibility. 1289 * @example 1290 * x = new X509(); 1291 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1292 * x.getExtSubjectAltName() → 1293 * { array: [ 1294 * {uri: "http://example.com/"}, 1295 * {rfc822: "user1@example.com"}, 1296 * {dns: "example.com"} 1297 * ], 1298 * critical: true 1299 * } 1300 * 1301 * x.getExtSubjectAltName("3026...") → 1302 * { array: [{ip: "192.168.1.1"}] } 1303 */ 1304 this.getExtSubjectAltName = function(hExtV, critical) { 1305 if (hExtV === undefined && critical === undefined) { 1306 var info = this.getExtInfo("subjectAltName"); 1307 if (info === undefined) return undefined; 1308 hExtV = _getTLV(this.hex, info.vidx); 1309 critical = info.critical; 1310 } 1311 1312 var result = {extname:"subjectAltName",array:[]}; 1313 if (critical) result.critical = true; 1314 1315 result.array = this.getGeneralNames(hExtV); 1316 1317 return result; 1318 }; 1319 1320 /** 1321 * get issuerAltName value as array of string in the certificate 1322 * @name getExtIssuerAltName 1323 * @memberOf X509# 1324 * @function 1325 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1326 * @param {Boolean} critical flag (OPTIONAL) 1327 * @return {Array} JSON object of IssuerAltName parameters 1328 * @since jsrsasign 9.0.0 x509 2.0.0 1329 * @see KJUR.asn1.x509.IssuerAltName 1330 * @see X509#getExtSubjectAltName 1331 * @description 1332 * This method will get issuerAltName value 1333 * as an array of JSON object which has properties defined 1334 * in {@link KJUR.asn1.x509.IssuerAltName}. 1335 * Result of this method can be passed to 1336 * {@link KJUR.asn1.x509.IssuerAltName} constructor. 1337 * If there is no this extension in the certificate, 1338 * it returns undefined. 1339 * <br> 1340 * When hExtV and critical specified as arguments, return value 1341 * will be generated from them. 1342 * @example 1343 * x = new X509(); 1344 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1345 * x.getExtIssuerAltName() → 1346 * { array: [ 1347 * {uri: "http://example.com/"}, 1348 * {rfc822: "user1@example.com"}, 1349 * {dns: "example.com"} 1350 * ], 1351 * critical: true 1352 * } 1353 * 1354 * x.getExtIssuerAltName("3026...") → 1355 * { array: [{ip: "192.168.1.1"}] } 1356 */ 1357 this.getExtIssuerAltName = function(hExtV, critical) { 1358 if (hExtV === undefined && critical === undefined) { 1359 var info = this.getExtInfo("issuerAltName"); 1360 if (info === undefined) return undefined; 1361 hExtV = _getTLV(this.hex, info.vidx); 1362 critical = info.critical; 1363 } 1364 1365 var result = {extname:"issuerAltName",array:[]}; 1366 if (critical) result.critical = true; 1367 1368 result.array = this.getGeneralNames(hExtV); 1369 1370 return result; 1371 }; 1372 1373 /** 1374 * get GeneralNames ASN.1 structure parameter as JSON object 1375 * @name getGeneralNames 1376 * @memberOf X509# 1377 * @function 1378 * @param {String} h hexadecimal string of GeneralNames 1379 * @return {Array} array of GeneralNames parameters 1380 * @see KJUR.asn1.x509.GeneralNames 1381 * @see KJUR.asn1.x509.GeneralName 1382 * @see X509#getGeneralNames 1383 * @since jsrsasign 9.0.0 x509 2.0.0 1384 * @description 1385 * This method will get GeneralNames parameters defined in 1386 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6"> 1387 * RFC 5280 4.2.1.6</a>. 1388 * <pre> 1389 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 1390 * </pre> 1391 * Result of this method can be passed to 1392 * {@link KJUR.asn1.x509.GeneralNames} constructor. 1393 * @example 1394 * x = new X509(); 1395 * x.getGeneralNames("3011860f687474703a2f2f6161612e636f6d2f") 1396 * → [{uri: "http://aaa.com/"}] 1397 * 1398 * x.getGeneralNames("301ea41c30...") → 1399 * [{ dn: { 1400 * array: [ 1401 * [{type:"C", value:"JP", ds:"prn"}], 1402 * [{type:"O", value:"T1", ds:"utf8"}] 1403 * ], 1404 * str: "/C=JP/O=T1" } }] 1405 */ 1406 this.getGeneralNames = function(h) { 1407 var aIdx = _getChildIdx(h, 0); 1408 var result = []; 1409 for (var i = 0; i < aIdx.length; i++) { 1410 var gnParam = this.getGeneralName(_getTLV(h, aIdx[i])); 1411 if (gnParam !== undefined) result.push(gnParam); 1412 } 1413 return result; 1414 }; 1415 1416 /** 1417 * get GeneralName ASN.1 structure parameter as JSON object<br/> 1418 * @name getGeneralName 1419 * @memberOf X509# 1420 * @function 1421 * @param {String} h hexadecimal string of GeneralName 1422 * @return {Array} JSON object of GeneralName parameters or undefined 1423 * @since jsrsasign 9.0.0 x509 2.0.0 1424 * @see KJUR.asn1.x509.GeneralNames 1425 * @see KJUR.asn1.x509.GeneralName 1426 * @see KJUR.asn1.x509.OtherName 1427 * @see X509#getGeneralName 1428 * @see X509#getOtherName 1429 * 1430 * @description 1431 * This method will get GeneralName parameters defined in 1432 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6"> 1433 * RFC 5280 4.2.1.6</a>. 1434 * <pre> 1435 * GeneralName ::= CHOICE { 1436 * otherName [0] OtherName, 1437 * rfc822Name [1] IA5String, 1438 * dNSName [2] IA5String, 1439 * x400Address [3] ORAddress, 1440 * directoryName [4] Name, 1441 * ediPartyName [5] EDIPartyName, 1442 * uniformResourceIdentifier [6] IA5String, 1443 * iPAddress [7] OCTET STRING, 1444 * registeredID [8] OBJECT IDENTIFIER } 1445 * </pre> 1446 * Result of this method can be passed to 1447 * {@link KJUR.asn1.x509.GeneralName} constructor. 1448 * @example 1449 * x = new X509(); 1450 * x.getGeneralName("860f687474703a2f2f6161612e636f6d2f") 1451 * → {uri: "http://aaa.com/"} 1452 * x.getGeneralName("a41c30...") → 1453 * { dn: { 1454 * array: [ 1455 * [{type:"C", value:"JP", ds:"prn"}], 1456 * [{type:"O", value:"T1", ds:"utf8"}] 1457 * ], 1458 * str: "/C=JP/O=T1" } } 1459 */ 1460 this.getGeneralName = function(h) { 1461 var tag = h.substr(0, 2); 1462 var hValue = _getV(h, 0); 1463 var sValue = hextorstr(hValue); 1464 if (tag == "81") return {rfc822: sValue}; 1465 if (tag == "82") return {dns: sValue}; 1466 if (tag == "86") return {uri: sValue}; 1467 if (tag == "87") return {ip: hextoip(hValue)}; 1468 if (tag == "a4") return {dn: this.getX500Name(hValue)}; 1469 if (tag == "a0") return {other: this.getOtherName(h)}; 1470 return undefined; 1471 }; 1472 1473 /** 1474 * get subjectAltName value as array of string in the certificate (DEPRECATED) 1475 * @name getExtSubjectAltName2 1476 * @memberOf X509# 1477 * @function 1478 * @return {Object} array of alt name array 1479 * @since jsrsasign 8.0.1 x509 1.1.17 1480 * @deprecated jsrsasign 9.0.0 x509 2.0.0 1481 * @description 1482 * This method will get subject alt name extension value 1483 * as array of type and name. 1484 * If there is this in the certificate, it returns undefined; 1485 * Type of GeneralName will be shown as following: 1486 * <ul> 1487 * <li>"MAIL" - [1]rfc822Name</li> 1488 * <li>"DNS" - [2]dNSName</li> 1489 * <li>"DN" - [4]directoryName</li> 1490 * <li>"URI" - [6]uniformResourceIdentifier</li> 1491 * <li>"IP" - [7]iPAddress</li> 1492 * </ul> 1493 * @example 1494 * x = new X509(); 1495 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1496 * x.getExtSubjectAltName2() → 1497 * [["DNS", "example.com"], 1498 * ["DNS", "example.org"], 1499 * ["MAIL", "foo@example.com"], 1500 * ["IP", "192.168.1.1"], 1501 * ["IP", "2001:db8::2:1"], 1502 * ["DN", "/C=US/O=TEST1"]] 1503 */ 1504 this.getExtSubjectAltName2 = function() { 1505 var gnValueHex, gnValueStr, gnTag; 1506 var info = this.getExtInfo("subjectAltName"); 1507 if (info === undefined) return info; 1508 1509 var result = new Array(); 1510 var h = _getTLV(this.hex, info.vidx); 1511 1512 var a = _getChildIdx(h, 0); 1513 for (var i = 0; i < a.length; i++) { 1514 gnTag = h.substr(a[i], 2); 1515 gnValueHex = _getV(h, a[i]); 1516 1517 if (gnTag === "81") { // rfc822Name [1] 1518 gnValueStr = hextoutf8(gnValueHex); 1519 result.push(["MAIL", gnValueStr]); 1520 } 1521 if (gnTag === "82") { // dNSName [2] 1522 gnValueStr = hextoutf8(gnValueHex); 1523 result.push(["DNS", gnValueStr]); 1524 } 1525 if (gnTag === "84") { // directoryName [4] 1526 gnValueStr = X509.hex2dn(gnValueHex, 0); 1527 result.push(["DN", gnValueStr]); 1528 } 1529 if (gnTag === "86") { // uniformResourceIdentifier [6] 1530 gnValueStr = hextoutf8(gnValueHex); 1531 result.push(["URI", gnValueStr]); 1532 } 1533 if (gnTag === "87") { // iPAddress [7] 1534 gnValueStr = hextoip(gnValueHex); 1535 result.push(["IP", gnValueStr]); 1536 } 1537 } 1538 return result; 1539 }; 1540 1541 /** 1542 * get CRLDistributionPoints extension value as JSON object 1543 * @name getExtCRLDistributionPoints 1544 * @memberOf X509# 1545 * @function 1546 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1547 * @param {Boolean} critical flag (OPTIONAL) 1548 * @return {Object} JSON object of CRLDistributionPoints parameters or undefined 1549 * @since jsrsasign 9.0.0 x509 2.0.0 1550 * @see KJUR.asn1.x509.CRLDistributionPoints 1551 * @see X509#getDistributionPoint 1552 * @see X509#getDistributionPointName 1553 * @see X509#getGeneralNames 1554 * @see X509#getGeneralName 1555 * @description 1556 * This method will get certificate policies value 1557 * as an array of JSON object which has properties defined 1558 * in {@link KJUR.asn1.x509.CRLDistributionPoints}. 1559 * Result of this method can be passed to 1560 * {@link KJUR.asn1.x509.CRLDistributionPoints} constructor. 1561 * If there is no this extension in the certificate, 1562 * it returns undefined. 1563 * @example 1564 * x = new X509(); 1565 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1566 * x.getExtCRLDistributionPoints() → 1567 * {array: [ 1568 * {dpname: {full: [{uri: "http://example.com/"}]}}, 1569 * {dpname: {full: [{uri: "ldap://example.com/"}]}} 1570 * ], 1571 * critical: true} 1572 */ 1573 this.getExtCRLDistributionPoints = function(hExtV, critical) { 1574 if (hExtV === undefined && critical === undefined) { 1575 var info = this.getExtInfo("cRLDistributionPoints"); 1576 if (info === undefined) return undefined; 1577 hExtV = _getTLV(this.hex, info.vidx); 1578 critical = info.critical; 1579 } 1580 1581 var result = {extname:"cRLDistributionPoints",array:[]}; 1582 if (critical) result.critical = true; 1583 1584 var a = _getChildIdx(hExtV, 0); 1585 for (var i = 0; i < a.length; i++) { 1586 var hTLV = _getTLV(hExtV, a[i]); 1587 result.array.push(this.getDistributionPoint(hTLV)); 1588 } 1589 1590 return result; 1591 }; 1592 1593 /** 1594 * get DistributionPoint ASN.1 structure parameter as JSON object 1595 * @name getDistributionPoint 1596 * @memberOf X509# 1597 * @function 1598 * @param {String} h hexadecimal string of DistributionPoint 1599 * @return {Object} JSON object of DistributionPoint parameters 1600 * @since jsrsasign 9.0.0 x509 2.0.0 1601 * @see X509#getExtCRLDistributionPoints 1602 * @see X509#getDistributionPointName 1603 * @see X509#getGeneralNames 1604 * @see X509#getGeneralName 1605 * @description 1606 * This method will get DistributionPoint parameters. 1607 * Result of this method can be passed to 1608 * {@link KJUR.asn1.x509.DistributionPoint} constructor. 1609 * <br/> 1610 * NOTE: reasons[1] and CRLIssuer[2] field not supported 1611 * @example 1612 * x = new X509(); 1613 * x.getDistributionPoint("30...") → 1614 * {dpname: {full: [{uri: "http://aaa.com/"}]}} 1615 */ 1616 this.getDistributionPoint = function(h) { 1617 var result = {}; 1618 var a = _getChildIdx(h, 0); 1619 for (var i = 0; i < a.length; i++) { 1620 var tag = h.substr(a[i], 2); 1621 var hTLV = _getTLV(h, a[i]); 1622 if (tag == "a0") { 1623 result.dpname = this.getDistributionPointName(hTLV); 1624 } 1625 } 1626 return result; 1627 }; 1628 1629 /** 1630 * get DistributionPointName ASN.1 structure parameter as JSON object 1631 * @name getDistributionPointName 1632 * @memberOf X509# 1633 * @function 1634 * @param {String} h hexadecimal string of DistributionPointName 1635 * @return {Object} JSON object of DistributionPointName parameters 1636 * @since jsrsasign 9.0.0 x509 2.0.0 1637 * @see X509#getExtCRLDistributionPoints 1638 * @see X509#getDistributionPoint 1639 * @see X509#getGeneralNames 1640 * @see X509#getGeneralName 1641 * @description 1642 * This method will get DistributionPointName parameters. 1643 * Result of this method can be passed to 1644 * {@link KJUR.asn1.x509.DistributionPointName} constructor. 1645 * <br/> 1646 * NOTE: nameRelativeToCRLIssuer[1] not supported 1647 * @example 1648 * x = new X509(); 1649 * x.getDistributionPointName("a0...") → 1650 * {full: [{uri: "http://aaa.com/"}]} 1651 */ 1652 this.getDistributionPointName = function(h) { 1653 var result = {}; 1654 var a = _getChildIdx(h, 0); 1655 for (var i = 0; i < a.length; i++) { 1656 var tag = h.substr(a[i], 2); 1657 var hTLV = _getTLV(h, a[i]); 1658 if (tag == "a0") { 1659 result.full = this.getGeneralNames(hTLV); 1660 } 1661 } 1662 return result; 1663 }; 1664 1665 /** 1666 * get array of string for fullName URIs in cRLDistributionPoints(CDP) in the certificate (DEPRECATED) 1667 * @name getExtCRLDistributionPointsURI 1668 * @memberOf X509# 1669 * @function 1670 * @return {Object} array of fullName URIs of CDP of the certificate 1671 * @since jsrsasign 7.2.0 x509 1.1.14 1672 * @description 1673 * This method will get all fullName URIs of cRLDistributionPoints extension 1674 * in the certificate as array of URI string. 1675 * If there is this in the certificate, it returns undefined; 1676 * <br> 1677 * NOTE: Currently this method supports only fullName URI so that 1678 * other parameters will not be returned. 1679 * @example 1680 * x = new X509(); 1681 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1682 * x.getExtCRLDistributionPointsURI() → 1683 * ["http://example.com/aaa.crl", "http://example.org/aaa.crl"] 1684 */ 1685 this.getExtCRLDistributionPointsURI = function() { 1686 var p = this.getExtCRLDistributionPoints(); 1687 if (p == undefined) return p; 1688 var a = p.array; 1689 var result = []; 1690 for (var i = 0; i < a.length; i++) { 1691 try { 1692 if (a[i].dpname.full[0].uri != undefined) { 1693 result.push(a[i].dpname.full[0].uri); 1694 } 1695 } catch(ex) {} 1696 } 1697 return result; 1698 }; 1699 1700 /** 1701 * get AuthorityInfoAccess extension value in the certificate as associative array 1702 * @name getExtAIAInfo 1703 * @memberOf X509# 1704 * @function 1705 * @return {Object} associative array of AIA extension properties 1706 * @since jsrsasign 7.2.0 x509 1.1.14 1707 * @description 1708 * This method will get authority info access value 1709 * as associate array which has following properties: 1710 * <ul> 1711 * <li>ocsp - array of string for OCSP responder URL</li> 1712 * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li> 1713 * </ul> 1714 * If there is this in the certificate, it returns undefined; 1715 * @example 1716 * x = new X509(); 1717 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1718 * x.getExtAIAInfo(hCert) → 1719 * { ocsp: ["http://ocsp.foo.com"], 1720 * caissuer: ["http://rep.foo.com/aaa.p8m"] } 1721 */ 1722 this.getExtAIAInfo = function() { 1723 var info = this.getExtInfo("authorityInfoAccess"); 1724 if (info === undefined) return info; 1725 1726 var result = { ocsp: [], caissuer: [] }; 1727 var a = _getChildIdx(this.hex, info.vidx); 1728 for (var i = 0; i < a.length; i++) { 1729 var hOID = _getVbyList(this.hex, a[i], [0], "06"); 1730 var hName = _getVbyList(this.hex, a[i], [1], "86"); 1731 if (hOID === "2b06010505073001") { 1732 result.ocsp.push(hextoutf8(hName)); 1733 } 1734 if (hOID === "2b06010505073002") { 1735 result.caissuer.push(hextoutf8(hName)); 1736 } 1737 } 1738 1739 return result; 1740 }; 1741 1742 /** 1743 * get AuthorityInfoAccess extension value as JSON object 1744 * @name getExtAuthorityInfoAccess 1745 * @memberOf X509# 1746 * @function 1747 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1748 * @param {Boolean} critical flag (OPTIONAL) 1749 * @return {Array} JSON object of AuthorityInfoAccess parameters or undefined 1750 * @since jsrsasign 9.0.0 x509 2.0.0 1751 * @see KJUR.asn1.x509.AuthorityInfoAccess 1752 * @description 1753 * This method parse authorityInfoAccess extension. When arguments are 1754 * not specified, its extension in X509 object will be parsed. 1755 * Result of this method can be passed to 1756 * {@link KJUR.asn1.x509.AuthorityInfoAccess} constructor. 1757 * <br> 1758 * When hExtV and critical specified as arguments, return value 1759 * will be generated from them. 1760 * @example 1761 * x = new X509(); 1762 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1763 * x.getExtAuthorityInfoAccess() → 1764 * { 1765 * critial: true, // 1766 * array: [{ocsp: http://ocsp.example.com/}, 1767 * {caissuer: https://repository.example.com/}] 1768 * } 1769 * 1770 * x = new X509(); 1771 * x.getExtAuthorityInfoAccesss("306230...") 1772 * x.getExtAuthorityInfoAccesss("306230...", true) 1773 */ 1774 this.getExtAuthorityInfoAccess = function(hExtV, critical) { 1775 if (hExtV === undefined && critical === undefined) { 1776 var info = this.getExtInfo("authorityInfoAccess"); 1777 if (info === undefined) return undefined; 1778 hExtV = _getTLV(this.hex, info.vidx); 1779 critical = info.critical; 1780 } 1781 1782 var result = {extname:"authorityInfoAccess",array:[]}; 1783 if (critical) result.critical = true; 1784 1785 var a = _getChildIdx(hExtV, 0); 1786 for (var i = 0; i < a.length; i++) { 1787 var hMethod = _getVbyListEx(hExtV, a[i], [0], "06"); 1788 var hLoc = _getVbyList(hExtV, a[i], [1], "86"); 1789 var sLoc = hextoutf8(hLoc); 1790 if (hMethod == "2b06010505073001") { 1791 result.array.push({ocsp: sLoc}); 1792 } else if (hMethod == "2b06010505073002") { 1793 result.array.push({caissuer: sLoc}); 1794 } else { 1795 throw new Error("unknown method: " + hMethod); 1796 } 1797 } 1798 1799 return result; 1800 } 1801 1802 /** 1803 * get CertificatePolicies extension value as JSON object 1804 * @name getExtCertificatePolicies 1805 * @memberOf X509# 1806 * @function 1807 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 1808 * @param {Boolean} critical flag (OPTIONAL) 1809 * @return {Object} JSON object of CertificatePolicies parameters or undefined 1810 * @since jsrsasign 7.2.0 x509 1.1.14 1811 * @description 1812 * This method will get certificate policies value 1813 * as an array of JSON object which has properties defined 1814 * in {@link KJUR.asn1.x509.CertificatePolicies}. 1815 * Result of this method can be passed to 1816 * {@link KJUR.asn1.x509.CertificatePolicies} constructor. 1817 * If there is no this extension in the certificate, 1818 * it returns undefined. 1819 * <br> 1820 * CAUTION: return value of JSON object format have been changed 1821 * from jsrsasign 9.0.0 without backword compatibility. 1822 * <br> 1823 * When hExtV and critical specified as arguments, return value 1824 * will be generated from them. 1825 * @example 1826 * x = new X509(); 1827 * x.readCertPEM(sCertPEM); // parseExt() will also be called internally. 1828 * x.getExtCertificatePolicies() → 1829 * { array: [ 1830 * { policyoid: "1.2.3.4" } 1831 * { policyoid: "1.2.3.5", 1832 * array: [ 1833 * { cps: "https://example.com/" }, 1834 * { unotice: { exptext: { type: "bmp", str: "sample text" } } } 1835 * ] 1836 * } 1837 * ]} 1838 */ 1839 this.getExtCertificatePolicies = function(hExtV, critical) { 1840 if (hExtV === undefined && critical === undefined) { 1841 var info = this.getExtInfo("certificatePolicies"); 1842 if (info === undefined) return undefined; 1843 hExtV = _getTLV(this.hex, info.vidx); 1844 critical = info.critical; 1845 } 1846 var result = {extname:"certificatePolicies",array:[]}; 1847 if (critical) result.critical = true; 1848 1849 var aIdxPI = _getChildIdx(hExtV, 0); // PolicyInformation list index 1850 for (var i = 0; i < aIdxPI.length; i++) { 1851 var hPolicyInformation = _getTLV(hExtV, aIdxPI[i]); 1852 var polinfo = this.getPolicyInformation(hPolicyInformation); 1853 result.array.push(polinfo); 1854 } 1855 return result; 1856 } 1857 1858 /** 1859 * get PolicyInformation ASN.1 structure parameter as JSON object 1860 * @name getPolicyInformation 1861 * @memberOf X509# 1862 * @function 1863 * @param {String} h hexadecimal string of PolicyInformation 1864 * @return {Object} JSON object of PolicyInformation parameters 1865 * @since jsrsasign 9.0.0 x509 2.0.0 1866 * @description 1867 * This method will get PolicyInformation parameters defined in 1868 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4"> 1869 * RFC 5280 4.2.1.4</a>. 1870 * <pre> 1871 * PolicyInformation ::= SEQUENCE { 1872 * policyIdentifier CertPolicyId, 1873 * policyQualifiers SEQUENCE SIZE (1..MAX) OF 1874 * PolicyQualifierInfo OPTIONAL } 1875 * </pre> 1876 * Result of this method can be passed to 1877 * {@link KJUR.asn1.x509.PolicyInformation} constructor. 1878 * @example 1879 * x = new X509(); 1880 * x.getPolicyInformation("30...") → 1881 * { 1882 * policyoid: "2.16.840.1.114412.2.1", 1883 * array: [{cps: "https://www.digicert.com/CPS"}] 1884 * } 1885 */ 1886 this.getPolicyInformation = function(h) { 1887 var result = {}; 1888 1889 var hPOLICYOID = _getVbyList(h, 0, [0], "06"); 1890 result.policyoid = _oidname(hPOLICYOID); 1891 1892 var idxPQSEQ = _getIdxbyListEx(h, 0, [1], "30"); 1893 if (idxPQSEQ != -1) { 1894 result.array = []; 1895 var aIdx = _getChildIdx(h, idxPQSEQ); 1896 for (var j = 0; j < aIdx.length; j++) { 1897 var hPQI = _getTLV(h, aIdx[j]); 1898 var pqinfo = this.getPolicyQualifierInfo(hPQI); 1899 result.array.push(pqinfo); 1900 } 1901 } 1902 1903 return result; 1904 }; 1905 1906 /** 1907 * getOtherName ASN.1 structure parameter as JSON object<br/> 1908 * @name getOtherName 1909 * @memberOf X509# 1910 * @param {String} h hexadecimal string of GeneralName 1911 * @return {Array} associative array of OtherName 1912 * @since jsrsasign 10.5.3 x509 2.0.12 1913 * @see KJUR.asn1.x509.GeneralNames 1914 * @see KJUR.asn1.x509.GeneralName 1915 * @see KJUR.asn1.x509.OtherName 1916 * @see X509#getGeneralName 1917 * @see ASN1HEX#parse 1918 * 1919 * @description 1920 * This method will get OtherName parameters defined in 1921 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6"> 1922 * RFC 5280 4.2.1.6</a>. 1923 * <pre> 1924 * OtherName ::= SEQUENCE { 1925 * type-id OBJECT IDENTIFIER, 1926 * value [0] EXPLICIT ANY DEFINED BY type-id } 1927 * </pre> 1928 * The value of member "other" is converted by 1929 * {@link ASN1HEX#parse}. 1930 * 1931 * @example 1932 * x = new X509(); 1933 * x.getOtherName("30...") → 1934 * { oid: "1.2.3.4", 1935 * value: {utf8str: {str: "aaa"}} } 1936 */ 1937 this.getOtherName = function(h) { 1938 var result = {}; 1939 var a = _getChildIdx(h, 0); 1940 var hOID = _getVbyList(h, a[0], [], "06"); 1941 var hValue = _getVbyList(h, a[1], []); 1942 result.oid = _oidname(hOID); 1943 result.value = _ASN1HEX_parse(hValue); 1944 return result; 1945 }; 1946 1947 /** 1948 * get PolicyQualifierInfo ASN.1 structure parameter as JSON object 1949 * @name getPolicyQualifierInfo 1950 * @memberOf X509# 1951 * @function 1952 * @param {String} h hexadecimal string of PolicyQualifierInfo 1953 * @return {Object} JSON object of PolicyQualifierInfo parameters 1954 * @since jsrsasign 9.0.0 x509 2.0.0 1955 * @see X509#getExtCertificatePolicies 1956 * @see X509#getPolicyInformation 1957 * @description 1958 * This method will get 1959 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4"> 1960 * PolicyQualifierInfo</a> parameters. 1961 * <pre> 1962 * PolicyQualifierInfo ::= SEQUENCE { 1963 * policyQualifierId PolicyQualifierId, 1964 * qualifier ANY DEFINED BY policyQualifierId } 1965 * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } 1966 * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } 1967 * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } 1968 * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) 1969 * Qualifier ::= CHOICE { 1970 * cPSuri CPSuri, 1971 * userNotice UserNotice } 1972 * CPSuri ::= IA5String 1973 * </pre> 1974 * Result of this method can be passed to 1975 * {@link KJUR.asn1.x509.PolicyQualifierInfo} constructor. 1976 * @example 1977 * x = new X509(); 1978 * x.getPolicyQualifierInfo("30...") 1979 * → {unotice: {exptext: {type: 'utf8', str: 'aaa'}}} 1980 * x.getPolicyQualifierInfo("30...") 1981 * → {cps: "https://repository.example.com/"} 1982 */ 1983 this.getPolicyQualifierInfo = function(h) { 1984 var result = {}; 1985 var hPQOID = _getVbyList(h, 0, [0], "06"); 1986 if (hPQOID === "2b06010505070201") { // cps 1987 var hCPSURI = _getVbyListEx(h, 0, [1], "16"); 1988 result.cps = hextorstr(hCPSURI); 1989 } else if (hPQOID === "2b06010505070202") { // unotice 1990 var hUserNotice = _getTLVbyList(h, 0, [1], "30"); 1991 result.unotice = this.getUserNotice(hUserNotice); 1992 } 1993 return result; 1994 }; 1995 1996 /** 1997 * get UserNotice ASN.1 structure parameter as JSON object 1998 * @name getUserNotice 1999 * @memberOf X509# 2000 * @function 2001 * @param {String} h hexadecimal string of UserNotice 2002 * @return {Object} JSON object of UserNotice parameters 2003 * @since jsrsasign 9.0.0 x509 2.0.0 2004 * @see X509#getExtCertificatePolicies 2005 * @see X509#getPolicyInformation 2006 * @see X509#getPolicyQualifierInfo 2007 * @description 2008 * This method will get 2009 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4"> 2010 * UserNotice</a> parameters. 2011 * <pre> 2012 * UserNotice ::= SEQUENCE { 2013 * noticeRef NoticeReference OPTIONAL, 2014 * explicitText DisplayText OPTIONAL } 2015 * </pre> 2016 * Result of this method can be passed to 2017 * {@link KJUR.asn1.x509.NoticeReference} constructor. 2018 * <br/> 2019 * NOTE: NoticeReference parsing is currently not supported and 2020 * it will be ignored. 2021 * @example 2022 * x = new X509(); 2023 * x.getUserNotice("30...") → {exptext: {type: 'utf8', str: 'aaa'}} 2024 */ 2025 this.getUserNotice = function(h) { 2026 var result = {}; 2027 var a = _getChildIdx(h, 0); 2028 for (var i = 0; i < a.length; i++) { 2029 var hItem = _getTLV(h, a[i]); 2030 if (hItem.substr(0, 2) != "30") { 2031 result.exptext = this.getDisplayText(hItem); 2032 } 2033 } 2034 return result; 2035 }; 2036 2037 /** 2038 * get DisplayText ASN.1 structure parameter as JSON object 2039 * @name getDisplayText 2040 * @memberOf X509# 2041 * @function 2042 * @param {String} h hexadecimal string of DisplayText 2043 * @return {Object} JSON object of DisplayText parameters 2044 * @since jsrsasign 9.0.0 x509 2.0.0 2045 * @see X509#getExtCertificatePolicies 2046 * @see X509#getPolicyInformation 2047 * @description 2048 * This method will get 2049 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4"> 2050 * DisplayText</a> parameters. 2051 * <pre> 2052 * DisplayText ::= CHOICE { 2053 * ia5String IA5String (SIZE (1..200)), 2054 * visibleString VisibleString (SIZE (1..200)), 2055 * bmpString BMPString (SIZE (1..200)), 2056 * utf8String UTF8String (SIZE (1..200)) } 2057 * </pre> 2058 * Result of this method can be passed to 2059 * {@link KJUR.asn1.x509.DisplayText} constructor. 2060 * @example 2061 * x = new X509(); 2062 * x.getDisplayText("0c03616161") &rarr {type: 'utf8', str: 'aaa'} 2063 * x.getDisplayText("1e03616161") &rarr {type: 'bmp', str: 'aaa'} 2064 */ 2065 this.getDisplayText = function(h) { 2066 var _DISPLAYTEXTTAG = {"0c": "utf8", "16": "ia5", "1a": "vis" , "1e": "bmp"}; 2067 var result = {}; 2068 result.type = _DISPLAYTEXTTAG[h.substr(0, 2)]; 2069 result.str = hextorstr(_getV(h, 0)); 2070 return result; 2071 }; 2072 2073 /** 2074 * get PolicyMappings extension value as JSON object<br/> 2075 * @name getExtPolicyMappings 2076 * @memberOf X509# 2077 * @function 2078 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 2079 * @param {Boolean} critical flag (OPTIONAL) 2080 * @return {Object} JSON object of PolicyMappings parameters or undefined 2081 * @since jsrsasign 10.6.1 x509 2.1.1 2082 * @see KJUR.asn1.x509.PolicyMappings 2083 * 2084 * @description 2085 * This method will get certificate policies value 2086 * as an array of JSON object which has properties defined 2087 * in {@link KJUR.asn1.x509.PolicyMappings}. 2088 * Result of this method can be passed to 2089 * {@link KJUR.asn1.x509.PolicyMappings} constructor. 2090 * If there is no this extension in the certificate, 2091 * it returns undefined. 2092 * <br> 2093 * When hExtV and critical specified as arguments, return value 2094 * will be generated from them. 2095 * @example 2096 * x = new X509(sCertPEM); 2097 * x.getExtPolicyMappings() → 2098 * { extname: "policyMappings", 2099 * critical: true, 2100 * array: [["1.2.3", "1.4.5"],["0.1.2", "anyPolicy"]]} 2101 */ 2102 this.getExtPolicyMappings = function(hExtV, critical) { 2103 var aExtVCritical = this.getCriticalExtV("policyMappings", hExtV, critical); 2104 hExtV = aExtVCritical[0]; 2105 critical = aExtVCritical[1]; 2106 if (hExtV == null) return undefined; 2107 var result = {extname: "policyMappings"}; 2108 if (critical) result.critical = true; 2109 2110 try { 2111 var p = _ASN1HEX_parse(hExtV); 2112 //result._asn1 = p; 2113 var aPair = p.seq; 2114 var a = []; 2115 for (var i = 0; i < aPair.length; i++) { 2116 var aOid = aPair[i].seq; 2117 a.push([aOid[0].oid, aOid[1].oid]); 2118 } 2119 result.array = a; 2120 } catch(ex) { 2121 throw new _Error("malformed policyMappings"); 2122 } 2123 2124 return result; 2125 }; 2126 2127 /** 2128 * get PolicyConstraints extension value as JSON object<br/> 2129 * @name getExtPolicyConstraints 2130 * @memberOf X509# 2131 * @function 2132 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 2133 * @param {Boolean} critical flag (OPTIONAL) 2134 * @return {Object} JSON object of PolicyConstraints parameters or undefined 2135 * @since jsrsasign 10.6.1 x509 2.1.1 2136 * @see KJUR.asn1.x509.PolicyConstraints 2137 * 2138 * @description 2139 * This method will get certificate policies value 2140 * as an array of JSON object which has properties defined 2141 * in {@link KJUR.asn1.x509.PolicyConstraints}. 2142 * Result of this method can be passed to 2143 * {@link KJUR.asn1.x509.PolicyConstraints} constructor. 2144 * If there is no this extension in the certificate, 2145 * it returns undefined. 2146 * <br> 2147 * When hExtV and critical specified as arguments, return value 2148 * will be generated from them. 2149 * @example 2150 * x = new X509(sCertPEM); 2151 * x.getExtPolicyConstraints() → 2152 * { extname: "policyConstraints", 2153 * critical: true, 2154 * reqexp: 3, 2155 * inhibit: 3 } 2156 */ 2157 this.getExtPolicyConstraints = function(hExtV, critical) { 2158 var aExtVCritical = this.getCriticalExtV("policyConstraints", hExtV, critical); 2159 hExtV = aExtVCritical[0]; 2160 critical = aExtVCritical[1]; 2161 if (hExtV == null) return undefined; 2162 var result = {extname: "policyConstraints"}; 2163 if (critical) result.critical = true; 2164 2165 var p = _ASN1HEX_parse(hExtV); 2166 try { 2167 var aItem = p.seq; 2168 for (var i = 0; i < aItem.length; i++) { 2169 var pTag = aItem[i].tag; 2170 if (pTag.explicit != false) continue; 2171 if (pTag.tag == "80") result.reqexp = parseInt(pTag.hex, 16); 2172 if (pTag.tag == "81") result.inhibit = parseInt(pTag.hex, 16); 2173 } 2174 } catch(ex) { 2175 return new _Error("malformed policyConstraints value"); 2176 } 2177 return result; 2178 }; 2179 2180 /** 2181 * get InhibitAnyPolicy extension value as JSON object<br/> 2182 * @name getExtInhibitAnyPolicy 2183 * @memberOf X509# 2184 * @function 2185 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 2186 * @param {Boolean} critical flag (OPTIONAL) 2187 * @return {Object} JSON object of InhibitAnyPolicy parameters or undefined 2188 * @since jsrsasign 10.6.1 x509 2.1.1 2189 * @see KJUR.asn1.x509.InhibitAnyPolicy 2190 * 2191 * @description 2192 * This method will get certificate policies value 2193 * as an array of JSON object which has properties defined 2194 * in {@link KJUR.asn1.x509.InhibitAnyPolicy}. 2195 * Result of this method can be passed to 2196 * {@link KJUR.asn1.x509.InhibitAnyPolicy} constructor. 2197 * If there is no this extension in the certificate, 2198 * it returns undefined. 2199 * <br> 2200 * When hExtV and critical specified as arguments, return value 2201 * will be generated from them. 2202 * @example 2203 * x = new X509(sCertPEM); 2204 * x.getExtInhibitAnyPolicy() → 2205 * { extname: "policyConstraints", 2206 * critical: true, 2207 * skip: 3 } 2208 * 2209 * x.getExtInhibitAnyPolicy("020103", true) → same as above 2210 */ 2211 this.getExtInhibitAnyPolicy = function(hExtV, critical) { 2212 var aExtVCritical = this.getCriticalExtV("inhibitAnyPolicy", hExtV, critical); 2213 hExtV = aExtVCritical[0]; 2214 critical = aExtVCritical[1]; 2215 if (hExtV == null) return undefined; 2216 var result = {extname: "inhibitAnyPolicy"}; 2217 if (critical) result.critical = true; 2218 2219 var skip = _getInt(hExtV, 0); 2220 if (skip == -1) return new _Error("wrong value"); 2221 result.skip = skip; 2222 return result; 2223 }; 2224 2225 /** 2226 * parse cRLNumber CRL extension as JSON object<br/> 2227 * @name getExtCRLNumber 2228 * @memberOf X509# 2229 * @function 2230 * @param {String} hExtV hexadecimal string of extension value 2231 * @param {Boolean} critical flag 2232 * @since jsrsasign 9.1.1 x509 2.0.1 2233 * @see KJUR.asn1.x509.CRLNumber 2234 * @see X509#getExtParamArray 2235 * @description 2236 * This method parses 2237 * CRLNumber CRL extension value defined in 2238 * <a href="https://tools.ietf.org/html/rfc5280#section-5.2.3"> 2239 * RFC 5280 5.2.3</a> as JSON object. 2240 * <pre> 2241 * id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } 2242 * CRLNumber ::= INTEGER (0..MAX) 2243 * </pre> 2244 * <br/> 2245 * Result of this method can be passed to 2246 * {@link KJUR.asn1.x509.CRLNumber} constructor. 2247 * @example 2248 * crl = X509CRL("-----BEGIN X509 CRL..."); 2249 * ... get hExtV and critical flag ... 2250 * crl.getExtCRLNumber("02...", false) → 2251 * {extname: "cRLNumber", num: {hex: "12af"}} 2252 */ 2253 this.getExtCRLNumber = function(hExtV, critical) { 2254 var result = {extname:"cRLNumber"}; 2255 if (critical) result.critical = true; 2256 2257 if (hExtV.substr(0, 2) == "02") { 2258 result.num = {hex: _getV(hExtV, 0)}; 2259 return result; 2260 } 2261 throw new _Error("hExtV parse error: " + hExtV); 2262 }; 2263 2264 /** 2265 * parse cRLReason CRL entry extension as JSON object<br/> 2266 * @name getExtCRLReason 2267 * @memberOf X509# 2268 * @function 2269 * @param {String} hExtV hexadecimal string of extension value 2270 * @param {Boolean} critical flag 2271 * @since jsrsasign 9.1.1 x509 2.0.1 2272 * @see KJUR.asn1.x509.CRLReason 2273 * @see X509#getExtParamArray 2274 * @description 2275 * This method parses 2276 * CRLReason CRL entry extension value defined in 2277 * <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1"> 2278 * RFC 5280 5.3.1</a> as JSON object. 2279 * <pre> 2280 * id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 } 2281 * -- reasonCode ::= { CRLReason } 2282 * CRLReason ::= ENUMERATED { 2283 * unspecified (0), 2284 * keyCompromise (1), 2285 * cACompromise (2), 2286 * affiliationChanged (3), 2287 * superseded (4), 2288 * cessationOfOperation (5), 2289 * certificateHold (6), 2290 * removeFromCRL (8), 2291 * privilegeWithdrawn (9), 2292 * aACompromise (10) } 2293 * </pre> 2294 * <br/> 2295 * Result of this method can be passed to 2296 * {@link KJUR.asn1.x509.CRLReason} constructor. 2297 * @example 2298 * crl = X509CRL("-----BEGIN X509 CRL..."); 2299 * ... get hExtV and critical flag ... 2300 * crl.getExtCRLReason("02...", false) → 2301 * {extname: "cRLReason", code: 3} 2302 */ 2303 this.getExtCRLReason = function(hExtV, critical) { 2304 var result = {extname:"cRLReason"}; 2305 if (critical) result.critical = true; 2306 2307 if (hExtV.substr(0, 2) == "0a") { 2308 result.code = parseInt(_getV(hExtV, 0), 16); 2309 return result; 2310 } 2311 throw new Error("hExtV parse error: " + hExtV); 2312 }; 2313 2314 /** 2315 * parse OCSPNonce OCSP extension as JSON object<br/> 2316 * @name getExtOcspNonce 2317 * @memberOf X509# 2318 * @function 2319 * @param {String} hExtV hexadecimal string of extension value 2320 * @param {Boolean} critical flag 2321 * @return {Array} JSON object of parsed OCSPNonce extension 2322 * @since jsrsasign 9.1.6 x509 2.0.3 2323 * @see KJUR.asn1.x509.OCSPNonce 2324 * @see X509#getExtParamArray 2325 * @see X509#getExtParam 2326 * @description 2327 * This method parses 2328 * Nonce OCSP extension value defined in 2329 * <a href="https://tools.ietf.org/html/rfc6960#section-4.4.1"> 2330 * RFC 6960 4.4.1</a> as JSON object. 2331 * <pre> 2332 * id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp } 2333 * id-pkix-ocsp-nonce OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 } 2334 * Nonce ::= OCTET STRING 2335 * </pre> 2336 * <br/> 2337 * Result of this method can be passed to 2338 * {@link KJUR.asn1.x509.OCSPNonce} constructor. 2339 * @example 2340 * x = new X509(); 2341 * x.getExtOcspNonce(<<extn hex value >>) → 2342 * { extname: "ocspNonce", hex: "1a2b..." } 2343 */ 2344 this.getExtOcspNonce = function(hExtV, critical) { 2345 var result = {extname:"ocspNonce"}; 2346 if (critical) result.critical = true; 2347 2348 var hNonce = _getV(hExtV, 0); 2349 result.hex = hNonce; 2350 2351 return result; 2352 }; 2353 2354 /** 2355 * parse OCSPNoCheck OCSP extension as JSON object<br/> 2356 * @name getExtOcspNoCheck 2357 * @memberOf X509# 2358 * @function 2359 * @param {String} hExtV hexadecimal string of extension value 2360 * @param {Boolean} critical flag 2361 * @return {Array} JSON object of parsed OCSPNoCheck extension 2362 * @since jsrsasign 9.1.6 x509 2.0.3 2363 * @see KJUR.asn1.x509.OCSPNoCheck 2364 * @see X509#getExtParamArray 2365 * @see X509#getExtParam 2366 * @description 2367 * This method parses 2368 * OCSPNoCheck extension value defined in 2369 * <a href="https://tools.ietf.org/html/rfc6960#section-4.2.2.2.1"> 2370 * RFC 6960 4.2.2.2.1</a> as JSON object. 2371 * <pre> 2372 * id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 } 2373 * </pre> 2374 * <br/> 2375 * Result of this method can be passed to 2376 * {@link KJUR.asn1.x509.OCSPNoCheck} constructor. 2377 * @example 2378 * x = new X509(); 2379 * x.getExtOcspNoCheck(<<extn hex value >>) → 2380 * { extname: "ocspNoCheck" } 2381 */ 2382 this.getExtOcspNoCheck = function(hExtV, critical) { 2383 var result = {extname:"ocspNoCheck"}; 2384 if (critical) result.critical = true; 2385 2386 return result; 2387 }; 2388 2389 /** 2390 * parse AdobeTimeStamp extension as JSON object<br/> 2391 * @name getExtAdobeTimeStamp 2392 * @memberOf X509# 2393 * @function 2394 * @param {String} hExtV hexadecimal string of extension value 2395 * @param {Boolean} critical flag 2396 * @return {Array} JSON object of parsed AdobeTimeStamp extension 2397 * @since jsrsasign 10.0.1 x509 2.0.5 2398 * @see KJUR.asn1.x509.AdobeTimeStamp 2399 * @see X509#getExtParamArray 2400 * @see X509#getExtParam 2401 * @description 2402 * This method parses 2403 * X.509v3 AdobeTimeStamp private extension value defined in the 2404 * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSigDC/oids.html"> 2405 * Adobe site</a> as JSON object. 2406 * This extension provides the URL location for time stamp service. 2407 * <pre> 2408 * adbe- OBJECT IDENTIFIER ::= { adbe(1.2.840.113583) acrobat(1) security(1) x509Ext(9) 1 } 2409 * ::= SEQUENCE { 2410 * version INTEGER { v1(1) }, -- extension version 2411 * location GeneralName (In v1 GeneralName can be only uniformResourceIdentifier) 2412 * requiresAuth boolean (default false), OPTIONAL } 2413 * </pre> 2414 * <br/> 2415 * Result of this method can be passed to 2416 * {@link KJUR.asn1.x509.AdobeTimeStamp} constructor. 2417 * <br/> 2418 * NOTE: This extesion doesn't seem to have official name. This may be called as "pdfTimeStamp". 2419 * @example 2420 * x.getExtAdobeTimeStamp(<<extn hex value >>) → 2421 * { extname: "adobeTimeStamp", uri: "http://tsa.example.com/" reqauth: true } 2422 */ 2423 this.getExtAdobeTimeStamp = function(hExtV, critical) { 2424 if (hExtV === undefined && critical === undefined) { 2425 var info = this.getExtInfo("adobeTimeStamp"); 2426 if (info === undefined) return undefined; 2427 hExtV = _getTLV(this.hex, info.vidx); 2428 critical = info.critical; 2429 } 2430 2431 var result = {extname:"adobeTimeStamp"}; 2432 if (critical) result.critical = true; 2433 2434 var a = _getChildIdx(hExtV, 0); 2435 if (a.length > 1) { 2436 var hGN = _getTLV(hExtV, a[1]) 2437 var gnParam = this.getGeneralName(hGN); 2438 if (gnParam.uri != undefined) { 2439 result.uri = gnParam.uri; 2440 } 2441 } 2442 if (a.length > 2) { 2443 var hBool = _getTLV(hExtV, a[2]); 2444 if (hBool == "0101ff") result.reqauth = true; 2445 if (hBool == "010100") result.reqauth = false; 2446 } 2447 2448 return result; 2449 }; 2450 2451 // ===== BEGIN X500Name related ===================================== 2452 /* 2453 * convert ASN.1 parsed object to attrTypeAndValue assoc array<br/> 2454 * @name _convATV 2455 * @param p associative array of parsed attrTypeAndValue object 2456 * @return attrTypeAndValue associative array 2457 * @since jsrsasign 10.5.12 x509 2.0.14 2458 * @example 2459 * _convATV({seq: [...]} &rarr: {type:"C",value:"JP",ds:"prn"} 2460 */ 2461 var _convATV = function(p) { 2462 var result = {}; 2463 try { 2464 var name = p.seq[0].oid; 2465 var oid = KJUR.asn1.x509.OID.name2oid(name); 2466 result.type = KJUR.asn1.x509.OID.oid2atype(oid); 2467 var item1 = p.seq[1]; 2468 if (item1.utf8str != undefined) { 2469 result.ds = "utf8"; 2470 result.value = item1.utf8str.str; 2471 } else if (item1.numstr != undefined) { 2472 result.ds = "num"; 2473 result.value = item1.numstr.str; 2474 } else if (item1.telstr != undefined) { 2475 result.ds = "tel"; 2476 result.value = item1.telstr.str; 2477 } else if (item1.prnstr != undefined) { 2478 result.ds = "prn"; 2479 result.value = item1.prnstr.str; 2480 } else if (item1.ia5str != undefined) { 2481 result.ds = "ia5"; 2482 result.value = item1.ia5str.str; 2483 } else if (item1.visstr != undefined) { 2484 result.ds = "vis"; 2485 result.value = item1.visstr.str; 2486 } else if (item1.bmpstr != undefined) { 2487 result.ds = "bmp"; 2488 result.value = item1.bmpstr.str; 2489 } else { 2490 throw "error"; 2491 } 2492 return result; 2493 } catch(ex) { 2494 throw new Erorr("improper ASN.1 parsed AttrTypeAndValue"); 2495 } 2496 }; 2497 2498 /* 2499 * convert ASN.1 parsed object to RDN array<br/> 2500 * @name _convRDN 2501 * @param p associative array of parsed RDN object 2502 * @return RDN array 2503 * @since jsrsasign 10.5.12 x509 2.0.14 2504 * @example 2505 * _convRDN({set: [...]} &rarr: [{type:"C",value:"JP",ds:"prn"}] 2506 */ 2507 var _convRDN = function(p) { 2508 try { 2509 return p.set.map(function(pATV){return _convATV(pATV)}); 2510 } catch(ex) { 2511 throw new Error("improper ASN.1 parsed RDN: " + ex); 2512 } 2513 }; 2514 2515 /* 2516 * convert ASN.1 parsed object to X500Name array<br/> 2517 * @name _convX500Name 2518 * @param p associative array of parsed X500Name array object 2519 * @return RDN array 2520 * @since jsrsasign 10.5.12 x509 2.0.14 2521 * @example 2522 * _convX500Name({seq: [...]} &rarr: [[{type:"C",value:"JP",ds:"prn"}]] 2523 */ 2524 var _convX500Name = function(p) { 2525 try { 2526 return p.seq.map(function(pRDN){return _convRDN(pRDN)}); 2527 } catch(ex) { 2528 throw new Error("improper ASN.1 parsed X500Name: " + ex); 2529 } 2530 }; 2531 2532 this.getX500NameRule = function(aDN) { 2533 var isPRNRule = true; 2534 var isUTF8Rule = true; 2535 var isMixedRule = false; 2536 var logfull = ""; 2537 var logcheck = ""; 2538 var lasttag = null; 2539 2540 var a = []; 2541 for (var i = 0; i < aDN.length; i++) { 2542 var aRDN = aDN[i]; 2543 for (var j = 0; j < aRDN.length; j++) { 2544 a.push(aRDN[j]); 2545 } 2546 } 2547 2548 for (var i = 0; i < a.length; i++) { 2549 var item = a[i]; 2550 var tag = item.ds; 2551 var value = item.value; 2552 var type = item.type; 2553 logfull += ":" + tag; 2554 2555 if (tag != "prn" && tag != "utf8" && tag != "ia5") { 2556 return "mixed"; 2557 } 2558 if (tag == "ia5") { 2559 if (type != "CN") { 2560 return "mixed"; 2561 } else { 2562 if (! KJUR.lang.String.isMail(value)) { 2563 return "mixed"; 2564 } else { 2565 continue; 2566 } 2567 } 2568 } 2569 if (type == "C") { 2570 if (tag == "prn") { 2571 continue; 2572 } else { 2573 return "mixed"; 2574 } 2575 } 2576 logcheck += ":" + tag; 2577 if (lasttag == null) { 2578 lasttag = tag; 2579 } else { 2580 if (lasttag !== tag) return "mixed"; 2581 } 2582 } 2583 if (lasttag == null) { 2584 return "prn"; 2585 } else { 2586 return lasttag; 2587 } 2588 }; 2589 2590 /** 2591 * get AttributeTypeAndValue ASN.1 structure parameter as JSON object<br/> 2592 * @name getAttrTypeAndValue 2593 * @memberOf X509# 2594 * @function 2595 * @param {String} h hexadecimal string of AttributeTypeAndValue 2596 * @return {Object} JSON object of AttributeTypeAndValue parameters 2597 * @since jsrsasign 9.0.0 x509 2.0.0 2598 * @see X509#getX500Name 2599 * @see X509#getRDN 2600 * @description 2601 * This method will get AttributeTypeAndValue parameters defined in 2602 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2603 * RFC 5280 4.1.2.4</a>. 2604 * <pre> 2605 * AttributeTypeAndValue ::= SEQUENCE { 2606 * type AttributeType, 2607 * value AttributeValue } 2608 * AttributeType ::= OBJECT IDENTIFIER 2609 * AttributeValue ::= ANY -- DEFINED BY AttributeType 2610 * </pre> 2611 * <ul> 2612 * <li>{String}type - AttributeType name or OID(ex. C,O,CN)</li> 2613 * <li>{String}value - raw string of ASN.1 value of AttributeValue</li> 2614 * <li>{String}ds - DirectoryString type of AttributeValue</li> 2615 * </ul> 2616 * "ds" has one of following value: 2617 * <ul> 2618 * <li>utf8 - (0x0c) UTF8String</li> 2619 * <li>num - (0x12) NumericString</li> 2620 * <li>prn - (0x13) PrintableString</li> 2621 * <li>tel - (0x14) TeletexString</li> 2622 * <li>ia5 - (0x16) IA5String</li> 2623 * <li>vis - (0x1a) VisibleString</li> 2624 * <li>bmp - (0x1e) BMPString</li> 2625 * </ul> 2626 * @example 2627 * x = new X509(); 2628 * x.getAttrTypeAndValue("30...") → 2629 * {type:"CN",value:"john.smith@example.com",ds:"ia5"} or 2630 * {type:"O",value:"Sample Corp.",ds:"prn"} 2631 */ 2632 // unv - (0x1c??) UniversalString ... for future 2633 this.getAttrTypeAndValue = function(h) { 2634 var p = _ASN1HEX_parse(h); 2635 return _convATV(p); 2636 }; 2637 2638 /** 2639 * get RelativeDistinguishedName ASN.1 structure parameter array<br/> 2640 * @name getRDN 2641 * @memberOf X509# 2642 * @function 2643 * @param {String} h hexadecimal string of RDN 2644 * @return {Array} array of AttrTypeAndValue parameters 2645 * @since jsrsasign 9.0.0 x509 2.0.0 2646 * @see X509#getX500Name 2647 * @see X509#getRDN 2648 * @see X509#getAttrTypeAndValue 2649 * @description 2650 * This method will get RelativeDistinguishedName parameters defined in 2651 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2652 * RFC 5280 4.1.2.4</a>. 2653 * <pre> 2654 * RelativeDistinguishedName ::= 2655 * SET SIZE (1..MAX) OF AttributeTypeAndValue 2656 * </pre> 2657 * @example 2658 * x = new X509(); 2659 * x.getRDN("31...") → 2660 * [{type:"C",value:"US",ds:"prn"}] or 2661 * [{type:"O",value:"Sample Corp.",ds:"prn"}] or 2662 * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}] 2663 */ 2664 this.getRDN = function(h) { 2665 var p = _ASN1HEX_parse(h); 2666 return _convRDN(p); 2667 }; 2668 2669 /** 2670 * get X.500 Name ASN.1 structure parameter array<br/> 2671 * @name getX500NameArray 2672 * @memberOf X509# 2673 * @function 2674 * @param {String} h hexadecimal string of Name 2675 * @return {Array} array of RDN parameter array 2676 * @since jsrsasign 10.0.6 x509 2.0.9 2677 * @see X509#getX500Name 2678 * @see X509#getRDN 2679 * @see X509#getAttrTypeAndValue 2680 * @description 2681 * This method will get Name parameter defined in 2682 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2683 * RFC 5280 4.1.2.4</a>. 2684 * <pre> 2685 * Name ::= CHOICE { -- only one possibility for now -- 2686 * rdnSequence RDNSequence } 2687 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 2688 * </pre> 2689 * @example 2690 * x = new X509(); 2691 * x.getX500NameArray("30...") → 2692 * [[{type:"C",value:"US",ds:"prn"}], 2693 * [{type:"O",value:"Sample Corp.",ds:"utf8"}], 2694 * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]] 2695 */ 2696 this.getX500NameArray = function(h) { 2697 var p = _ASN1HEX_parse(h); 2698 return _convX500Name(p); 2699 }; 2700 2701 /** 2702 * get Name ASN.1 structure parameter array<br/> 2703 * @name getX500Name 2704 * @memberOf X509# 2705 * @function 2706 * @param {String} h hexadecimal string of Name 2707 * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false) 2708 * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false) 2709 * @return {Array} array of RDN parameter array 2710 * @since jsrsasign 9.0.0 x509 2.0.0 2711 * @see X509#getX500NameArray 2712 * @see X509#getRDN 2713 * @see X509#getAttrTypeAndValue 2714 * @see X509#c14nRDNArray 2715 * @see KJUR.asn1.x509.X500Name 2716 * @see KJUR.asn1.x509.GeneralName 2717 * @see KJUR.asn1.x509.GeneralNames 2718 * 2719 * @description 2720 * This method will get Name parameter defined in 2721 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2722 * RFC 5280 4.1.2.4</a>. 2723 * <pre> 2724 * Name ::= CHOICE { -- only one possibility for now -- 2725 * rdnSequence RDNSequence } 2726 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 2727 * </pre> 2728 * <br> 2729 * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 2730 * supported to conclude a canonicalized name for caseIgnoreMatch 2731 * desribed in <a href="https://tools.ietf.org/html/rfc4518"> 2732 * RFC 4518</a>. 2733 * 2734 * @example 2735 * x = new X509(); 2736 * x.getX500Name("30...") → 2737 * { array: [ 2738 * [{type:"C",value:"US",ds:"prn"}], 2739 * [{type:"O",value:"Sample Corp.",ds:"utf8"}], 2740 * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}] 2741 * ], 2742 * str: "/C=US/O=Sample Corp./CN=john.smith@example.com", 2743 * hex: "30..." } 2744 * 2745 * x.getX500Name("30...", true) → 2746 * { array: [ 2747 * [{type:"C",value:"US",ds:"prn"}], 2748 * [{type:"O",value:"Sample Corp.",ds:"utf8"}] 2749 * ], 2750 * str: "/C=US/O=Sample Corp.", 2751 * canon: "/c=us/o=sample corp.", 2752 * hex: "30..." } 2753 */ 2754 this.getX500Name = function(h, flagCanon, flagHex) { 2755 var a = this.getX500NameArray(h); 2756 var s = this.dnarraytostr(a); 2757 var result = { str: s }; 2758 2759 result.array = a; 2760 if (flagHex == true) result.hex = h; 2761 if (flagCanon == true) result.canon = this.c14nRDNArray(a); 2762 return result; 2763 }; 2764 2765 // ===== END X500Name related ===================================== 2766 2767 // ===== BEGIN read certificate ===================================== 2768 /** 2769 * read PEM formatted X.509 certificate from string.<br/> 2770 * @name readCertPEM 2771 * @memberOf X509# 2772 * @function 2773 * @param {String} sCertPEM string for PEM formatted X.509 certificate 2774 * @example 2775 * x = new X509(); 2776 * x.readCertPEM(sCertPEM); // read certificate 2777 */ 2778 this.readCertPEM = function(sCertPEM) { 2779 this.readCertHex(_pemtohex(sCertPEM)); 2780 }; 2781 2782 /** 2783 * read a hexadecimal string of X.509 certificate<br/> 2784 * @name readCertHex 2785 * @memberOf X509# 2786 * @function 2787 * @param {String} sCertHex hexadecimal string of X.509 certificate 2788 * @since jsrsasign 7.1.4 x509 1.1.13 2789 * @description 2790 * NOTE: {@link X509#parseExt} will called internally since jsrsasign 7.2.0. 2791 * @example 2792 * x = new X509(); 2793 * x.readCertHex("3082..."); // read certificate 2794 */ 2795 this.readCertHex = function(sCertHex) { 2796 this.hex = sCertHex; 2797 this.getVersion(); // set version parameter 2798 2799 try { 2800 _getIdxbyList(this.hex, 0, [0, 7], "a3"); // has [3] v3ext 2801 this.parseExt(); 2802 } catch(ex) {}; 2803 }; 2804 2805 // ===== END read certificate ===================================== 2806 2807 /** 2808 * get JSON object of certificate parameters<br/> 2809 * @name getParam 2810 * @memberOf X509# 2811 * @function 2812 * @param {Object} option optional setting for return object 2813 * @return {Object} JSON object of certificate parameters 2814 * @since jsrsasign 9.0.0 x509 2.0.0 2815 * @see KJUR.asn1.x509.X509Util.newCertPEM 2816 * 2817 * @description 2818 * This method returns a JSON object of the certificate 2819 * parameters. Return value can be passed to 2820 * {@link KJUR.asn1.x509.X509Util.newCertPEM}. 2821 * <br/> 2822 * NOTE1: From jsrsasign 10.5.16, optional argument can be applied. 2823 * It can have following members: 2824 * <ul> 2825 * <li>tbshex - (boolean) tbshex member with hex value of 2826 * tbsCertificate will be added if true (DEFAULT undefined)</li> 2827 * <li>nodnarray - (boolean) array member for subject and 2828 * issuer will be deleted to simplify it if true (DEFAULT undefined)<li> 2829 * <li>dncanon - (boolean) add canon member to subject and issuer for DN StringPrep if true(DEFAULT undefined)</li> 2830 * <li>dnhex - (boolean) add hex member to subject and issuer if true(DEFAULT undefined)</li> 2831 * </ul> 2832 * <br/> 2833 * NOTE2: From jsrsasign 10.6.0, member "dncanon" and "dnhex" supported 2834 * in the "option" argument. 2835 * 2836 * @example 2837 * x = new X509(); 2838 * x.readCertPEM("-----BEGIN CERTIFICATE..."); 2839 * x.getParam() → 2840 * {version:3, 2841 * serial:{hex:"12ab"}, 2842 * sigalg:"SHA256withRSA", 2843 * issuer: {array:[[{type:'CN',value:'CA1',ds:'prn'}]],str:"/O=CA1"}, 2844 * notbefore:"160403023700Z", 2845 * notafter:"160702023700Z", 2846 * subject: {array:[[{type:'CN',value:'Test1',ds:'prn'}]],str:"/CN=Test1"}, 2847 * sbjpubkey:"-----BEGIN PUBLIC KEY...", 2848 * ext:[ 2849 * {extname:"keyUsage",critical:true,names:["digitalSignature"]}, 2850 * {extname:"basicConstraints",critical:true}, 2851 * {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}}, 2852 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 2853 * {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]}, 2854 * {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]} 2855 * ], 2856 * sighex:"0b76...8" 2857 * }; 2858 * 2859 * x.getParam({tbshex: true}) → { ... , tbshex: "30..." } 2860 * x.getParam({nodnarray: true}) → {issuer: {str: "/C=JP"}, ...} 2861 * x.getParam({dncanon: true}) → {... {issuer: {canon: "/c=jp/o=..."} ...} ...} 2862 * x.getParam({dnhex: true}) → {... {issuer: {hex: "30..."} ...} ...} 2863 */ 2864 this.getParam = function(option) { 2865 var result = {}; 2866 if (option == undefined) option = {}; 2867 2868 result.version = this.getVersion(); 2869 result.serial = {hex: this.getSerialNumberHex()}; 2870 result.sigalg = this.getSignatureAlgorithmField(); 2871 result.issuer = this.getIssuer(option.dncanon, option.dnhex); 2872 result.notbefore = this.getNotBefore(); 2873 result.notafter = this.getNotAfter(); 2874 result.subject = this.getSubject(option.dncanon, option.dnhex); 2875 result.sbjpubkey = hextopem(this.getPublicKeyHex(), "PUBLIC KEY"); 2876 if (this.aExtInfo != undefined && 2877 this.aExtInfo.length > 0) { 2878 result.ext = this.getExtParamArray(); 2879 } 2880 result.sighex = this.getSignatureValueHex(); 2881 2882 // for options 2883 if (option.tbshex == true) { 2884 result.tbshex = _getTLVbyList(this.hex, 0, [0]); 2885 } 2886 if (option.nodnarray == true) { 2887 delete result.issuer.array; 2888 delete result.subject.array; 2889 } 2890 2891 return result; 2892 }; 2893 2894 /** 2895 * get array of certificate extension parameter JSON object<br/> 2896 * @name getExtParamArray 2897 * @memberOf X509# 2898 * @function 2899 * @param {String} hExtSeq hexadecimal string of SEQUENCE of Extension 2900 * @return {Array} array of certificate extension parameter JSON object 2901 * @since jsrsasign 9.0.0 x509 2.0.0 2902 * @see KJUR.asn1.x509.X509Util.newCertPEM 2903 * @see X509#getParam 2904 * @see X509#getExtParam 2905 * @see X509CRL#getParam 2906 * @see KJUR.asn1.csr.CSRUtil.getParam 2907 * 2908 * @description 2909 * This method returns an array of certificate extension 2910 * parameters. 2911 * <br/> 2912 * NOTE: Argument "hExtSeq" have been supported since jsrsasign 9.1.1. 2913 * 2914 * @example 2915 * x = new X509(); 2916 * x.readCertPEM("-----BEGIN CERTIFICATE..."); 2917 * x.getExtParamArray() → 2918 * [ {extname:"keyUsage",critical:true,names:["digitalSignature"]}, 2919 * {extname:"basicConstraints",critical:true}, 2920 * {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}}, 2921 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 2922 * {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]}, 2923 * {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}] 2924 */ 2925 this.getExtParamArray = function(hExtSeq) { 2926 if (hExtSeq == undefined) { 2927 // for X.509v3 certificate 2928 var idx1 = _getIdxbyListEx(this.hex, 0, [0, "[3]"]); 2929 if (idx1 != -1) { 2930 hExtSeq = _getTLVbyListEx(this.hex, 0, [0, "[3]", 0], "30"); 2931 } 2932 } 2933 var result = []; 2934 var aIdx = _getChildIdx(hExtSeq, 0); 2935 2936 for (var i = 0; i < aIdx.length; i++) { 2937 var hExt = _getTLV(hExtSeq, aIdx[i]); 2938 var extParam = this.getExtParam(hExt); 2939 if (extParam != null) result.push(extParam); 2940 } 2941 2942 return result; 2943 }; 2944 2945 /** 2946 * get a extension parameter JSON object<br/> 2947 * @name getExtParam 2948 * @memberOf X509# 2949 * @function 2950 * @param {String} hExt hexadecimal string of Extension 2951 * @return {Array} Extension parameter JSON object 2952 * @since jsrsasign 9.1.1 x509 2.0.1 2953 * @see KJUR.asn1.x509.X509Util.newCertPEM 2954 * @see X509#getParam 2955 * @see X509#getExtParamArray 2956 * @see X509CRL#getParam 2957 * @see KJUR.asn1.csr.CSRUtil.getParam 2958 * 2959 * @description 2960 * This method returns a extension parameters as JSON object. 2961 * 2962 * @example 2963 * x = new X509(); 2964 * ... 2965 * x.getExtParam("30...") → 2966 * {extname:"keyUsage",critical:true,names:["digitalSignature"]} 2967 */ 2968 this.getExtParam = function(hExt) { 2969 var result = {}; 2970 var aIdx = _getChildIdx(hExt, 0); 2971 var aIdxLen = aIdx.length; 2972 if (aIdxLen != 2 && aIdxLen != 3) 2973 throw new Error("wrong number elements in Extension: " + 2974 aIdxLen + " " + hExt); 2975 2976 var oid = _hextooidstr(_getVbyList(hExt, 0, [0], "06")); 2977 2978 var critical = false; 2979 if (aIdxLen == 3 && _getTLVbyList(hExt, 0, [1]) == "0101ff") 2980 critical = true; 2981 2982 var hExtV = _getTLVbyList(hExt, 0, [aIdxLen - 1, 0]); 2983 2984 var extParam = undefined; 2985 if (oid == "2.5.29.14") { 2986 extParam = this.getExtSubjectKeyIdentifier(hExtV, critical); 2987 } else if (oid == "2.5.29.15") { 2988 extParam = this.getExtKeyUsage(hExtV, critical); 2989 } else if (oid == "2.5.29.17") { 2990 extParam = this.getExtSubjectAltName(hExtV, critical); 2991 } else if (oid == "2.5.29.18") { 2992 extParam = this.getExtIssuerAltName(hExtV, critical); 2993 } else if (oid == "2.5.29.19") { 2994 extParam = this.getExtBasicConstraints(hExtV, critical); 2995 } else if (oid == "2.5.29.30") { 2996 extParam = this.getExtNameConstraints(hExtV, critical); 2997 } else if (oid == "2.5.29.31") { 2998 extParam = this.getExtCRLDistributionPoints(hExtV, critical); 2999 } else if (oid == "2.5.29.32") { 3000 extParam = this.getExtCertificatePolicies(hExtV, critical); 3001 } else if (oid == "2.5.29.33") { 3002 extParam = this.getExtPolicyMappings(hExtV, critical); 3003 } else if (oid == "2.5.29.35") { 3004 extParam = this.getExtAuthorityKeyIdentifier(hExtV, critical); 3005 } else if (oid == "2.5.29.36") { 3006 extParam = this.getExtPolicyConstraints(hExtV, critical); 3007 } else if (oid == "2.5.29.37") { 3008 extParam = this.getExtExtKeyUsage(hExtV, critical); 3009 } else if (oid == "2.5.29.54") { 3010 extParam = this.getExtInhibitAnyPolicy(hExtV, critical); 3011 } else if (oid == "1.3.6.1.5.5.7.1.1") { 3012 extParam = this.getExtAuthorityInfoAccess(hExtV, critical); 3013 } else if (oid == "2.5.29.20") { 3014 extParam = this.getExtCRLNumber(hExtV, critical); 3015 } else if (oid == "2.5.29.21") { 3016 extParam = this.getExtCRLReason(hExtV, critical); 3017 } else if (oid == "1.3.6.1.5.5.7.48.1.2") { 3018 extParam = this.getExtOcspNonce(hExtV, critical); 3019 } else if (oid == "1.3.6.1.5.5.7.48.1.5") { 3020 extParam = this.getExtOcspNoCheck(hExtV, critical); 3021 } else if (oid == "1.2.840.113583.1.1.9.1") { 3022 extParam = this.getExtAdobeTimeStamp(hExtV, critical); 3023 } 3024 if (extParam != undefined) return extParam; 3025 3026 var privateParam = { extname: oid, extn: hExtV }; 3027 if (critical) privateParam.critical = true; 3028 return privateParam; 3029 }; 3030 3031 /** 3032 * find extension parameter in array<br/> 3033 * @name findExt 3034 * @memberOf X509# 3035 * @function 3036 * @param {Array} aExt array of extension parameters 3037 * @param {String} extname extension name 3038 * @return {Array} extension parameter in the array or null 3039 * @since jsrsasign 10.0.3 x509 2.0.7 3040 * @see X509#getParam 3041 * 3042 * @description 3043 * This method returns an extension parameter for 3044 * specified extension name in the array. 3045 * This method is useful to update extension parameter value. 3046 * When there is no such extension with the extname, 3047 * this returns "null". 3048 * 3049 * @example 3050 * // (1) 3051 * x = new X509(CERTPEM); 3052 * params = x.getParam(); 3053 * pSKID = x.findExt(params.ext, "subjectKeyIdentifier"); 3054 * pSKID.kid = "1234abced..."; // skid in the params is updated. 3055 * // then params was updated 3056 * 3057 * // (2) another example 3058 * aExt = [ 3059 * {extname:"keyUsage",critical:true,names:["digitalSignature"]}, 3060 * {extname:"basicConstraints",critical:true}, 3061 * {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}}, 3062 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3063 * {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]}, 3064 * {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]} 3065 * ]; 3066 * var x = new X509(); 3067 * x.findExt(aExt, "authorityKeyInfoAccess").array[0].ocsp = "http://aaa.com"; 3068 * pKU = x.findExt(aExt, "keyUsage"); 3069 * delete pKU["critical"]; // clear criticla flag 3070 * pKU.names = ["keyCertSign", "cRLSign"]; 3071 * // then aExt was updated 3072 */ 3073 this.findExt = function(aExt, extname) { 3074 for (var i = 0; i < aExt.length; i++) { 3075 if (aExt[i].extname == extname) return aExt[i]; 3076 } 3077 return null; 3078 3079 }; 3080 3081 /** 3082 * update CRLDistributionPoints Full URI in parameter<br/> 3083 * @name updateCDPFullURI 3084 * @memberOf X509# 3085 * @function 3086 * @param {Array} aExt array of extension parameters 3087 * @param {String} newURI string of new uri 3088 * @since jsrsasign 10.0.4 x509 2.0.8 3089 * @see X509#findExt 3090 * @see KJUR.asn1.x509.CRLDistributionPoints 3091 * 3092 * @description 3093 * This method updates Full URI of CRLDistributionPoints extension 3094 * in the extension parameter array if it exists. 3095 * 3096 * @example 3097 * aExt = [ 3098 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3099 * {extname:"cRLDistributionPoints", 3100 * array:[{dpname:{full:[{uri:"http://example.com/a.crl"}]}}]}, 3101 * ]; 3102 * x = new X509(); 3103 * x.updateCDPFullURI(aExt, "http://crl2.example.new/b.crl"); 3104 */ 3105 this.updateExtCDPFullURI = function(aExt, newURI) { 3106 var pExt = this.findExt(aExt, "cRLDistributionPoints"); 3107 if (pExt == null) return; 3108 if (pExt.array == undefined) return; 3109 var aDP = pExt.array; 3110 for (var i = 0; i < aDP.length; i++) { 3111 if (aDP[i].dpname == undefined) continue; 3112 if (aDP[i].dpname.full == undefined) continue; 3113 var aURI = aDP[i].dpname.full; 3114 for (var j = 0; j < aURI.length; j++) { 3115 var pURI = aURI[i]; 3116 if (pURI.uri == undefined) continue; 3117 pURI.uri = newURI; 3118 } 3119 } 3120 }; 3121 3122 /** 3123 * update authorityInfoAccess ocsp in parameter<br/> 3124 * @name updateAIAOCSP 3125 * @memberOf X509# 3126 * @function 3127 * @param {Array} aExt array of extension parameters 3128 * @param {String} newURI string of new uri 3129 * @since jsrsasign 10.0.4 x509 2.0.8 3130 * @see X509#findExt 3131 * @see KJUR.asn1.x509.AuthorityInfoAccess 3132 * 3133 * @description 3134 * This method updates "ocsp" accessMethod URI of 3135 * AuthorityInfoAccess extension 3136 * in the extension parameter array if it exists. 3137 * 3138 * @example 3139 * aExt = [ 3140 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3141 * {extname:"authoriyInfoAccess", 3142 * array:[ 3143 * {ocsp: "http://ocsp1.example.com"}, 3144 * {caissuer: "http://example.com/a.crt"} 3145 * ]} 3146 * ]; 3147 * x = new X509(); 3148 * x.updateAIAOCSP(aExt, "http://ocsp2.example.net"); 3149 */ 3150 this.updateExtAIAOCSP = function(aExt, newURI) { 3151 var pExt = this.findExt(aExt, "authorityInfoAccess"); 3152 if (pExt == null) return; 3153 if (pExt.array == undefined) return; 3154 var a = pExt.array; 3155 for (var i = 0; i < a.length; i++) { 3156 if (a[i].ocsp != undefined) a[i].ocsp = newURI; 3157 } 3158 }; 3159 3160 /** 3161 * update authorityInfoAccess caIssuer in parameter<br/> 3162 * @name updateAIACAIssuer 3163 * @memberOf X509# 3164 * @function 3165 * @param {Array} aExt array of extension parameters 3166 * @param {String} newURI string of new uri 3167 * @since jsrsasign 10.0.4 x509 2.0.8 3168 * @see X509#findExt 3169 * @see KJUR.asn1.x509.AuthorityInfoAccess 3170 * 3171 * @description 3172 * This method updates "caIssuer" accessMethod URI of 3173 * AuthorityInfoAccess extension 3174 * in the extension parameter array if it exists. 3175 * 3176 * @example 3177 * aExt = [ 3178 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3179 * {extname:"authoriyInfoAccess", 3180 * array:[ 3181 * {ocsp: "http://ocsp1.example.com"}, 3182 * {caissuer: "http://example.com/a.crt"} 3183 * ]} 3184 * ]; 3185 * x = new X509(); 3186 * x.updateAIACAIssuer(aExt, "http://example.net/b.crt"); 3187 */ 3188 this.updateExtAIACAIssuer = function(aExt, newURI) { 3189 var pExt = this.findExt(aExt, "authorityInfoAccess"); 3190 if (pExt == null) return; 3191 if (pExt.array == undefined) return; 3192 var a = pExt.array; 3193 for (var i = 0; i < a.length; i++) { 3194 if (a[i].caissuer != undefined) a[i].caissuer = newURI; 3195 } 3196 }; 3197 3198 /** 3199 * convert array for X500 distinguish name to distinguish name string<br/> 3200 * @name dnarraytostr 3201 * @memberOf X509# 3202 * @function 3203 * @param {Array} aDN array for X500 distinguish name 3204 * @return {String} distinguish name 3205 * @since jsrsasign 10.0.6 x509 2.0.8 3206 * @see X509#getX500Name 3207 * @see X509#getX500NameArray 3208 * @see KJUR.asn1.x509.X500Name 3209 * 3210 * @description 3211 * This method converts from an array representation of 3212 * X.500 distinguished name to X.500 name string. 3213 * This supports multi-valued RDN. 3214 * 3215 * @example 3216 * var x = new X509(); 3217 * x.dnarraytostr( 3218 * [[{type:"C",value:"JP",ds:"prn"}], 3219 * [{type:"O",value:"T1",ds:"prn"}]]) → "/C=JP/O=T1" 3220 * x.dnarraytostr( 3221 * [[{type:"C",value:"JP",ds:"prn"}], 3222 * [{type:"O",value:"T1",ds:"prn"} 3223 * {type:"CN",value:"Bob",ds:"prn"}]]) → "/C=JP/O=T1+CN=Bob" 3224 */ 3225 this.dnarraytostr = function(aDN) { 3226 function rdnarraytostr(aRDN) { 3227 return aRDN.map(function(x){return atvtostr(x).replace(/\+/,"\\+");}).join("+"); 3228 }; 3229 3230 function atvtostr(pATV) { 3231 return pATV.type + "=" + pATV.value; 3232 }; 3233 3234 return "/" + aDN.map(function(x){return rdnarraytostr(x).replace(/\//, "\\/");}).join("/"); 3235 }; 3236 3237 /** 3238 * set canonicalized DN to a DN parameter<br/> 3239 * @name setCanonicalizedDN 3240 * @memberOf X509# 3241 * @function 3242 * @param {object} pDN DN parameter associative array 3243 * @since jsrsasign 10.6.0 x509 2.1.0 3244 * 3245 * @description 3246 * This method canonicalizes a DN string as following: 3247 * <ul> 3248 * <li>convert to lower case</li> 3249 * <li>convert from all multiple spaces to a space</li> 3250 * </ul> 3251 * 3252 * @example 3253 * var x = new X509(); 3254 * var pDN = { 3255 * array: [ 3256 * [{type:'C',value:'JP',ds:'prn'}], 3257 * [{type:'O',value:'Test 1',ds:'prn'}] ], 3258 * str: "/C=JP/O=Test 1" }; 3259 * x.setCanonicalizedDN(pDN); 3260 3261 * // pDN will become following 3262 * pDN = { 3263 * array: [ 3264 * [{type:'C',value:'JP',ds:'prn'}], 3265 * [{type:'O',value:'Test 1',ds:'prn'}] ], 3266 * str: "/C=JP/O=Test 1", 3267 * canon: "/c=jp/o=test 1" }; 3268 */ 3269 this.setCanonicalizedDN = function(pDN) { 3270 var aRDN; 3271 if (pDN.str != undefined && pDN.array == undefined) { 3272 var dDN = new KJUR.asn1.x509.X500Name({str: pDN.str}); 3273 var hDN = dDN.tohex(); 3274 aRDN = this.getX500NameArray(hDN); 3275 } else { 3276 aRDN = pDN.array; 3277 } 3278 if (pDN.canon == undefined) { 3279 pDN.canon = this.c14nRDNArray(aRDN); 3280 } 3281 }; 3282 3283 /** 3284 * simple canonicalization(c14n) for RDN array<br/> 3285 * @name c14nRDNArray 3286 * @memberOf X509# 3287 * @function 3288 * @param {array} aRDN array of RDN parameters 3289 * @return {string} canonicalized distinguish name (ex. "/c=jp/o=test ca") 3290 * @since jsrsasign 10.6.0 x509 2.1.0 3291 * 3292 * @description 3293 * This method canonicalizes a DN string according to 3294 * <a href="https://datatracker.ietf.org/doc/html/rfc4518#appendix-B"> 3295 * "RFC 4518 StringPrep Appendix B Substring Matching"</a> as following: 3296 * <ul> 3297 * <li>convert to lower case</li> 3298 * <li>convert from all sequence of spaces to a space</li> 3299 * <li>remove leading and trailing spaces</li> 3300 * </ul> 3301 * 3302 * @example 3303 * var x = new X509(); 3304 * x.c14nRDNArray([ 3305 * [{type:"C", value:"JP", ds: "prn"}], 3306 * [{type:"O", value:" Test 1234 ", ds: "utf8"}], 3307 * [{type:"OU", value:"HR 45", ds: "utf8"}] 3308 * ]) → "/c=jp/o=test 1234/ou=hr 45" 3309 */ 3310 this.c14nRDNArray = function(aRDN) { 3311 var a = []; 3312 for (var i = 0; i < aRDN.length; i++) { 3313 var aAVA = aRDN[i]; 3314 var a2 = []; 3315 for (var j = 0; j < aAVA.length; j++) { 3316 var pAVA = aAVA[j]; 3317 var value = pAVA.value; 3318 value = value.replace(/^\s*/, ''); 3319 value = value.replace(/\s*$/, ''); 3320 value = value.replace(/\s+/g, ' '); 3321 value = value.toLowerCase(); 3322 a2.push(pAVA.type.toLowerCase() + "=" + value); 3323 } 3324 a.push(a2.join("+")); 3325 } 3326 return "/" + a.join("/"); 3327 }; 3328 3329 /** 3330 * get certificate information as string.<br/> 3331 * @name getInfo 3332 * @memberOf X509# 3333 * @function 3334 * @return {String} certificate information string 3335 * @since jsrsasign 5.0.10 x509 1.1.8 3336 * @example 3337 * x = new X509(); 3338 * x.readCertPEM(certPEM); 3339 * console.log(x.getInfo()); 3340 * // this shows as following 3341 * Basic Fields 3342 * serial number: 02ac5c266a0b409b8f0b79f2ae462577 3343 * signature algorithm: SHA1withRSA 3344 * issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA 3345 * notBefore: 061110000000Z 3346 * notAfter: 311110000000Z 3347 * subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA 3348 * subject public key info: 3349 * key algorithm: RSA 3350 * n=c6cce573e6fbd4bb... 3351 * e=10001 3352 * X509v3 Extensions: 3353 * keyUsage CRITICAL: 3354 * digitalSignature,keyCertSign,cRLSign 3355 * basicConstraints CRITICAL: 3356 * cA=true 3357 * subjectKeyIdentifier : 3358 * b13ec36903f8bf4701d498261a0802ef63642bc3 3359 * authorityKeyIdentifier : 3360 * kid=b13ec36903f8bf4701d498261a0802ef63642bc3 3361 * signature algorithm: SHA1withRSA 3362 * signature: 1c1a0697dcd79c9f... 3363 */ 3364 this.getInfo = function() { 3365 var _getSubjectAltNameStr = function(params) { 3366 var s = ""; 3367 var indent = " "; 3368 var NL = "\n"; 3369 var a = params.array; 3370 for (var i = 0; i < a.length; i++) { 3371 var pGN = a[i]; 3372 if (pGN.dn != undefined) s += indent + "dn: " + pGN.dn.str + NL; 3373 if (pGN.ip != undefined) s += indent + "ip: " + pGN.ip + NL; 3374 if (pGN.rfc822 != undefined) s += indent + "rfc822: " + pGN.rfc822 + NL; 3375 if (pGN.dns != undefined) s += indent + "dns: " + pGN.dns + NL; 3376 if (pGN.uri != undefined) s += indent + "uri: " + pGN.uri + NL; 3377 if (pGN.other != undefined) { 3378 var oidname = pGN.other.oid; 3379 var value = JSON.stringify(pGN.other.value).replace(/\"/g, ''); 3380 s += indent + "other: " + oidname + "=" + value + NL; 3381 } 3382 } 3383 s = s.replace(/\n$/, ''); 3384 return s; 3385 }; 3386 var _getCertificatePoliciesStr = function(params) { 3387 var s = ""; 3388 var a = params.array; 3389 for (var i = 0; i < a.length; i++) { 3390 var pi = a[i]; 3391 s += " policy oid: " + pi.policyoid + "\n"; 3392 if (pi.array === undefined) continue; 3393 for (var j = 0; j < pi.array.length; j++) { 3394 var pqi = pi.array[j]; 3395 if (pqi.cps !== undefined) { 3396 s += " cps: " + pqi.cps + "\n"; 3397 } 3398 } 3399 } 3400 return s; 3401 }; 3402 var _getCRLDistributionPointsStr = function(params) { 3403 var s = ""; 3404 var a = params.array; 3405 for (var i = 0; i < a.length; i++) { 3406 var dp = a[i]; 3407 try { 3408 if (dp.dpname.full[0].uri !== undefined) 3409 s += " " + dp.dpname.full[0].uri + "\n"; 3410 } catch(ex) {}; 3411 try { 3412 if (dp.dname.full[0].dn.hex !== undefined) 3413 s += " " + X509.hex2dn(dp.dpname.full[0].dn.hex) + "\n"; 3414 } catch(ex) {}; 3415 } 3416 return s; 3417 } 3418 var _getAuthorityInfoAccessStr = function(params) { 3419 var s = ""; 3420 var a = params.array; 3421 for (var i = 0; i < a.length; i++) { 3422 var ad = a[i]; 3423 3424 if (ad.caissuer !== undefined) 3425 s += " caissuer: " + ad.caissuer + "\n"; 3426 if (ad.ocsp !== undefined) 3427 s += " ocsp: " + ad.ocsp + "\n"; 3428 } 3429 return s; 3430 }; 3431 var _X509 = X509; 3432 var s, pubkey, aExt; 3433 s = "Basic Fields\n"; 3434 s += " serial number: " + this.getSerialNumberHex() + "\n"; 3435 s += " signature algorithm: " + this.getSignatureAlgorithmField() + "\n"; 3436 s += " issuer: " + this.getIssuerString() + "\n"; 3437 s += " notBefore: " + this.getNotBefore() + "\n"; 3438 s += " notAfter: " + this.getNotAfter() + "\n"; 3439 s += " subject: " + this.getSubjectString() + "\n"; 3440 s += " subject public key info: " + "\n"; 3441 3442 // subject public key info 3443 pubkey = this.getPublicKey(); 3444 s += " key algorithm: " + pubkey.type + "\n"; 3445 3446 if (pubkey.type === "RSA") { 3447 s += " n=" + hextoposhex(pubkey.n.toString(16)).substr(0, 16) + "...\n"; 3448 s += " e=" + hextoposhex(pubkey.e.toString(16)) + "\n"; 3449 } 3450 3451 // X.509v3 Extensions 3452 aExt = this.aExtInfo; 3453 3454 if (aExt !== undefined && aExt !== null) { 3455 s += "X509v3 Extensions:\n"; 3456 3457 for (var i = 0; i < aExt.length; i++) { 3458 var info = aExt[i]; 3459 3460 // show extension name and critical flag 3461 var extName = KJUR.asn1.x509.OID.oid2name(info["oid"]); 3462 if (extName === '') extName = info["oid"]; 3463 3464 var critical = ''; 3465 if (info["critical"] === true) critical = "CRITICAL"; 3466 3467 s += " " + extName + " " + critical + ":\n"; 3468 3469 // show extension value if supported 3470 if (extName === "basicConstraints") { 3471 var bc = this.getExtBasicConstraints(); 3472 if (bc.cA === undefined) { 3473 s += " {}\n"; 3474 } else { 3475 s += " cA=true"; 3476 if (bc.pathLen !== undefined) 3477 s += ", pathLen=" + bc.pathLen; 3478 s += "\n"; 3479 } 3480 } else if (extName == "policyMappings") { 3481 var a = this.getExtPolicyMappings().array; 3482 var sMap = a.map(function(item){ 3483 var aPolicy = item; 3484 return aPolicy[0] + ":" + aPolicy[1]; 3485 }).join(", "); 3486 s += " " + sMap + "\n"; 3487 } else if (extName == "policyConstraints") { 3488 var p = this.getExtPolicyConstraints(); 3489 s += " "; 3490 if (p.reqexp != undefined) s += " reqexp=" + p.reqexp; 3491 if (p.inhibit != undefined) s += " inhibit=" + p.inhibit; 3492 s += "\n"; 3493 } else if (extName == "inhibitAnyPolicy") { 3494 var p = this.getExtInhibitAnyPolicy(); 3495 s += " skip=" + p.skip + "\n"; 3496 } else if (extName == "keyUsage") { 3497 s += " " + this.getExtKeyUsageString() + "\n"; 3498 } else if (extName == "subjectKeyIdentifier") { 3499 s += " " + this.getExtSubjectKeyIdentifier().kid.hex + "\n"; 3500 } else if (extName == "authorityKeyIdentifier") { 3501 var akid = this.getExtAuthorityKeyIdentifier(); 3502 if (akid.kid !== undefined) 3503 s += " kid=" + akid.kid.hex + "\n"; 3504 } else if (extName == "extKeyUsage") { 3505 var eku = this.getExtExtKeyUsage().array; 3506 s += " " + eku.join(", ") + "\n"; 3507 } else if (extName == "subjectAltName") { 3508 var san = _getSubjectAltNameStr(this.getExtSubjectAltName()); 3509 s += san + "\n"; 3510 } else if (extName == "cRLDistributionPoints") { 3511 var cdp = this.getExtCRLDistributionPoints(); 3512 s += _getCRLDistributionPointsStr(cdp); 3513 } else if (extName == "authorityInfoAccess") { 3514 var aia = this.getExtAuthorityInfoAccess(); 3515 s += _getAuthorityInfoAccessStr(aia); 3516 } else if (extName == "certificatePolicies") { 3517 s += _getCertificatePoliciesStr(this.getExtCertificatePolicies()); 3518 } 3519 } 3520 } 3521 3522 s += "signature algorithm: " + this.getSignatureAlgorithmName() + "\n"; 3523 s += "signature: " + this.getSignatureValueHex().substr(0, 16) + "...\n"; 3524 return s; 3525 }; 3526 3527 if (typeof params == "string") { 3528 if (params.indexOf("-----BEGIN") != -1) { 3529 this.readCertPEM(params); 3530 } else if (KJUR.lang.String.isHex(params)) { 3531 this.readCertHex(params); 3532 } 3533 } 3534 }; 3535 // ----- END of X509 class ----- 3536 3537 /** 3538 * get distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER X.500 name<br/> 3539 * @name hex2dn 3540 * @memberOf X509 3541 * @function 3542 * @param {String} hex hexadecimal string of ASN.1 DER distinguished name 3543 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 3544 * @return {String} OpenSSL online format distinguished name 3545 * @description 3546 * This static method converts from a hexadecimal string of 3547 * distinguished name (DN) 3548 * specified by 'hex' and 'idx' to OpenSSL oneline string representation (ex. /C=US/O=a). 3549 * @example 3550 * X509.hex2dn("3031310b3...") → /C=US/O=a/CN=b2+OU=b1 3551 */ 3552 X509.hex2dn = function(hex, idx) { 3553 if (idx === undefined) idx = 0; 3554 var x = new X509(); 3555 var hDN = ASN1HEX.getTLV(hex, idx); 3556 var pDN = x.getX500Name(hex); 3557 return pDN.str; 3558 }; 3559 3560 /** 3561 * get relative distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER RDN<br/> 3562 * @name hex2rdn 3563 * @memberOf X509 3564 * @function 3565 * @param {String} hex hexadecimal string of ASN.1 DER concludes relative distinguished name 3566 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 3567 * @return {String} OpenSSL online format relative distinguished name 3568 * @description 3569 * This static method converts from a hexadecimal string of 3570 * relative distinguished name (RDN) 3571 * specified by 'hex' and 'idx' to LDAP string representation (ex. O=test+CN=test).<br/> 3572 * NOTE: Multi-valued RDN is supported since jsnrsasign 6.2.2 x509 1.1.10. 3573 * @example 3574 * X509.hex2rdn("310a3008060355040a0c0161") → O=a 3575 * X509.hex2rdn("31143008060355040a0c01613008060355040a0c0162") → O=a+O=b 3576 */ 3577 X509.hex2rdn = function(hex, idx) { 3578 if (idx === undefined) idx = 0; 3579 if (hex.substr(idx, 2) !== "31") throw new Error("malformed RDN"); 3580 3581 var a = new Array(); 3582 3583 var aIdx = ASN1HEX.getChildIdx(hex, idx); 3584 for (var i = 0; i < aIdx.length; i++) { 3585 a.push(X509.hex2attrTypeValue(hex, aIdx[i])); 3586 } 3587 3588 a = a.map(function(s) { return s.replace("+", "\\+"); }); 3589 return a.join("+"); 3590 }; 3591 3592 /** 3593 * get string from hexadecimal string of ASN.1 DER AttributeTypeAndValue<br/> 3594 * @name hex2attrTypeValue 3595 * @memberOf X509 3596 * @function 3597 * @param {String} hex hexadecimal string of ASN.1 DER concludes AttributeTypeAndValue 3598 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 3599 * @return {String} string representation of AttributeTypeAndValue (ex. C=US) 3600 * @description 3601 * This static method converts from a hexadecimal string of AttributeTypeAndValue 3602 * specified by 'hex' and 'idx' to LDAP string representation (ex. C=US). 3603 * @example 3604 * X509.hex2attrTypeValue("3008060355040a0c0161") → O=a 3605 * X509.hex2attrTypeValue("300806035504060c0161") → C=a 3606 * X509.hex2attrTypeValue("...3008060355040a0c0161...", 128) → O=a 3607 */ 3608 X509.hex2attrTypeValue = function(hex, idx) { 3609 var _ASN1HEX = ASN1HEX; 3610 var _getV = _ASN1HEX.getV; 3611 3612 if (idx === undefined) idx = 0; 3613 if (hex.substr(idx, 2) !== "30") 3614 throw new Error("malformed attribute type and value"); 3615 3616 var aIdx = _ASN1HEX.getChildIdx(hex, idx); 3617 if (aIdx.length !== 2 || hex.substr(aIdx[0], 2) !== "06") 3618 "malformed attribute type and value"; 3619 3620 var oidHex = _getV(hex, aIdx[0]); 3621 var oidInt = KJUR.asn1.ASN1Util.oidHexToInt(oidHex); 3622 var atype = KJUR.asn1.x509.OID.oid2atype(oidInt); 3623 3624 var hV = _getV(hex, aIdx[1]); 3625 var rawV = hextorstr(hV); 3626 3627 return atype + "=" + rawV; 3628 }; 3629 3630 /** 3631 * get RSA/DSA/ECDSA public key object from X.509 certificate hexadecimal string<br/> 3632 * @name getPublicKeyFromCertHex 3633 * @memberOf X509 3634 * @function 3635 * @param {String} h hexadecimal string of X.509 certificate for RSA/ECDSA/DSA public key 3636 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key 3637 * @since jsrasign 7.1.0 x509 1.1.11 3638 */ 3639 X509.getPublicKeyFromCertHex = function(h) { 3640 var x = new X509(); 3641 x.readCertHex(h); 3642 return x.getPublicKey(); 3643 }; 3644 3645 /** 3646 * get RSA/DSA/ECDSA public key object from PEM certificate string 3647 * @name getPublicKeyFromCertPEM 3648 * @memberOf X509 3649 * @function 3650 * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate 3651 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key 3652 * @since x509 1.1.1 3653 * @description 3654 * NOTE: DSA is also supported since x509 1.1.2. 3655 */ 3656 X509.getPublicKeyFromCertPEM = function(sCertPEM) { 3657 var x = new X509(); 3658 x.readCertPEM(sCertPEM); 3659 return x.getPublicKey(); 3660 }; 3661 3662 /** 3663 * get public key information from PEM certificate 3664 * @name getPublicKeyInfoPropOfCertPEM 3665 * @memberOf X509 3666 * @function 3667 * @param {String} sCertPEM string of PEM formatted certificate 3668 * @return {Hash} hash of information for public key 3669 * @since x509 1.1.1 3670 * @description 3671 * Resulted associative array has following properties:<br/> 3672 * <ul> 3673 * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li> 3674 * <li>algparam - hexadecimal string of OID of ECC curve name or null</li> 3675 * <li>keyhex - hexadecimal string of key in the certificate</li> 3676 * </ul> 3677 * NOTE: X509v1 certificate is also supported since x509.js 1.1.9. 3678 */ 3679 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) { 3680 var _ASN1HEX = ASN1HEX; 3681 var _getVbyList = _ASN1HEX.getVbyList; 3682 3683 var result = {}; 3684 var x, hSPKI, pubkey; 3685 result.algparam = null; 3686 3687 x = new X509(); 3688 x.readCertPEM(sCertPEM); 3689 3690 hSPKI = x.getPublicKeyHex(); 3691 result.keyhex = _getVbyList(hSPKI, 0, [1], "03").substr(2); 3692 result.algoid = _getVbyList(hSPKI, 0, [0, 0], "06"); 3693 3694 if (result.algoid === "2a8648ce3d0201") { // ecPublicKey 3695 result.algparam = _getVbyList(hSPKI, 0, [0, 1], "06"); 3696 }; 3697 3698 return result; 3699 }; 3700 3701 /* ====================================================================== 3702 * Specific V3 Extensions 3703 * ====================================================================== */ 3704 3705 X509.KEYUSAGE_NAME = [ 3706 "digitalSignature", 3707 "nonRepudiation", 3708 "keyEncipherment", 3709 "dataEncipherment", 3710 "keyAgreement", 3711 "keyCertSign", 3712 "cRLSign", 3713 "encipherOnly", 3714 "decipherOnly" 3715 ]; 3716