1 /* x509-2.1.6.js (c) 2012-2023 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-2023 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.8.6 x509 2.1.6 (2023-Apr-26) 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 * @see KJUR.asn1.x509.UserNotice 2008 * 2009 * @description 2010 * This method will get 2011 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4"> 2012 * UserNotice</a> parameters. 2013 * <pre> 2014 * UserNotice ::= SEQUENCE { 2015 * noticeRef NoticeReference OPTIONAL, 2016 * explicitText DisplayText OPTIONAL } 2017 * NoticeReference ::= SEQUENCE { 2018 * organization DisplayText, 2019 * noticeNumbers SEQUENCE OF INTEGER } 2020 * </pre> 2021 * Result of this method can be passed to 2022 * {@link KJUR.asn1.x509.UserNotice} constructor. 2023 * <br/> 2024 * NOTE: NoticeReference supported from jsrsasign 10.8.0. 2025 * 2026 * @example 2027 * x = new X509(); 2028 * x.getUserNotice("30...") → { 2029 * noticeref: { 2030 * org: {type: 'utf8', str: 'test org'}, 2031 * noticenum: [1] 2032 * }, 2033 * exptext: {type: 'utf8', str: 'test text'} 2034 * } 2035 */ 2036 this.getUserNotice = function(h) { 2037 var pASN1 = null; 2038 var result = {}; 2039 try { 2040 pASN1 = _ASN1HEX.parse(h); 2041 var pUnotice = this._asn1ToUnotice(pASN1); 2042 return pUnotice; 2043 } catch(ex) { 2044 return undefined; 2045 } 2046 }; 2047 2048 this._asn1ToUnotice = function(p) { 2049 try { 2050 var result = {}; 2051 var a = aryval(p, "seq"); 2052 for (var i = 0; i < a.length; i++) { 2053 var pNoticeRef = this._asn1ToNoticeRef(a[i]); 2054 if (pNoticeRef != undefined) result.noticeref = pNoticeRef; 2055 var pExpText = this.asn1ToDisplayText(a[i]); 2056 if (pExpText != undefined) result.exptext = pExpText; 2057 } 2058 if (Object.keys(result).length > 0) return result; 2059 return undefined; 2060 } catch(ex) { 2061 return undefined; 2062 } 2063 } 2064 2065 this._asn1ToNoticeRef = function(p) { 2066 try { 2067 var result = {}; 2068 var a = aryval(p, "seq"); 2069 for (var i = 0; i < a.length; i++) { 2070 var pNoticeNum = this._asn1ToNoticeNum(a[i]); 2071 if (pNoticeNum != undefined) result.noticenum = pNoticeNum; 2072 var pOrg = this.asn1ToDisplayText(a[i]); 2073 if (pOrg != undefined) result.org = pOrg; 2074 } 2075 if (Object.keys(result).length > 0) return result; 2076 return undefined; 2077 } catch(ex) { 2078 return undefined; 2079 } 2080 } 2081 2082 this._asn1ToNoticeNum = function(p) { 2083 try { 2084 var a = aryval(p, "seq"); 2085 var result = []; 2086 for (var i = 0; i < a.length; i++) { 2087 var item = a[i]; 2088 result.push(parseInt(aryval(item, "int.hex"), 16)); 2089 } 2090 return result; 2091 } catch(ex) { 2092 return undefined; 2093 } 2094 } 2095 2096 /** 2097 * get DisplayText ASN.1 structure parameter as JSON object 2098 * @name getDisplayText 2099 * @memberOf X509# 2100 * @function 2101 * @param {String} h hexadecimal string of DisplayText 2102 * @return {Object} JSON object of DisplayText parameters 2103 * @since jsrsasign 9.0.0 x509 2.0.0 2104 * @see X509#getExtCertificatePolicies 2105 * @see X509#getPolicyInformation 2106 * @description 2107 * This method will get 2108 * <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4"> 2109 * DisplayText</a> parameters. 2110 * <pre> 2111 * DisplayText ::= CHOICE { 2112 * ia5String IA5String (SIZE (1..200)), 2113 * visibleString VisibleString (SIZE (1..200)), 2114 * bmpString BMPString (SIZE (1..200)), 2115 * utf8String UTF8String (SIZE (1..200)) } 2116 * </pre> 2117 * Result of this method can be passed to 2118 * {@link KJUR.asn1.x509.DisplayText} constructor. 2119 * @example 2120 * x = new X509(); 2121 * x.getDisplayText("0c03616161") &rarr {type: 'utf8', str: 'aaa'} 2122 * x.getDisplayText("1e03616161") &rarr {type: 'bmp', str: 'aaa'} 2123 */ 2124 this.getDisplayText = function(h) { 2125 var _DISPLAYTEXTTAG = {"0c": "utf8", "16": "ia5", "1a": "vis" , "1e": "bmp"}; 2126 var result = {}; 2127 result.type = _DISPLAYTEXTTAG[h.substr(0, 2)]; 2128 result.str = hextorstr(_getV(h, 0)); 2129 return result; 2130 }; 2131 2132 /** 2133 * convert ASN1Object parameter to DisplayText parameter 2134 * @name asn1ToDisplayText 2135 * @memberOf X509# 2136 * @function 2137 * @param {Object} pASN1 ASN1Object paramter for DisplayText 2138 * @return {Object} DisplayText paramter 2139 * @since jsrsasign 10.8.0 x509 2.1.3 2140 * @see X509#getDisplayText 2141 * @see KJUR.asn1.x509.DisplayText 2142 * @see KJUR.asn1.ASN1Util#newObject 2143 * 2144 * @description 2145 * This method converts from {@link KJUR.asn1.ASN1Util#newObject} paramter to 2146 * {@link KJUR.asn1.x509.DisplayText} paramter 2147 * for <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.4"> 2148 * DisplayText</a> ASN.1 structure. 2149 * <pre> 2150 * DisplayText ::= CHOICE { 2151 * ia5String IA5String (SIZE (1..200)), 2152 * visibleString VisibleString (SIZE (1..200)), 2153 * bmpString BMPString (SIZE (1..200)), 2154 * utf8String UTF8String (SIZE (1..200)) } 2155 * </pre> 2156 * Result of this method can be passed to 2157 * {@link KJUR.asn1.x509.DisplayText} constructor. 2158 * 2159 * @example 2160 * x = new X509(); 2161 * x.asn1ToDisplayText({utf8str: {str: "aaa"}}) &rarr {type: 'utf8', str: 'aaa'} 2162 * x.asn1ToDisplayText({bmpstr: {str: "aaa"}}) &rarr {type: 'bmp', str: 'aaa'} 2163 */ 2164 this.asn1ToDisplayText = function(pASN1) { 2165 if (pASN1.utf8str != undefined) return { type: "utf8", str: pASN1.utf8str.str }; 2166 if (pASN1.ia5str != undefined) return { type: "ia5", str: pASN1.ia5str.str }; 2167 if (pASN1.visstr != undefined) return { type: "vis", str: pASN1.visstr.str }; 2168 if (pASN1.bmpstr != undefined) return { type: "bmp", str: pASN1.bmpstr.str }; 2169 if (pASN1.prnstr != undefined) return { type: "prn", str: pASN1.prnstr.str }; 2170 return undefined; 2171 } 2172 2173 /** 2174 * get PolicyMappings extension value as JSON object<br/> 2175 * @name getExtPolicyMappings 2176 * @memberOf X509# 2177 * @function 2178 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 2179 * @param {Boolean} critical flag (OPTIONAL) 2180 * @return {Object} JSON object of PolicyMappings parameters or undefined 2181 * @since jsrsasign 10.6.1 x509 2.1.1 2182 * @see KJUR.asn1.x509.PolicyMappings 2183 * 2184 * @description 2185 * This method will get certificate policies value 2186 * as an array of JSON object which has properties defined 2187 * in {@link KJUR.asn1.x509.PolicyMappings}. 2188 * Result of this method can be passed to 2189 * {@link KJUR.asn1.x509.PolicyMappings} constructor. 2190 * If there is no this extension in the certificate, 2191 * it returns undefined. 2192 * <br> 2193 * When hExtV and critical specified as arguments, return value 2194 * will be generated from them. 2195 * @example 2196 * x = new X509(sCertPEM); 2197 * x.getExtPolicyMappings() → 2198 * { extname: "policyMappings", 2199 * critical: true, 2200 * array: [["1.2.3", "1.4.5"],["0.1.2", "anyPolicy"]]} 2201 */ 2202 this.getExtPolicyMappings = function(hExtV, critical) { 2203 var aExtVCritical = this.getCriticalExtV("policyMappings", hExtV, critical); 2204 hExtV = aExtVCritical[0]; 2205 critical = aExtVCritical[1]; 2206 if (hExtV == null) return undefined; 2207 var result = {extname: "policyMappings"}; 2208 if (critical) result.critical = true; 2209 2210 try { 2211 var p = _ASN1HEX_parse(hExtV); 2212 //result._asn1 = p; 2213 var aPair = p.seq; 2214 var a = []; 2215 for (var i = 0; i < aPair.length; i++) { 2216 var aOid = aPair[i].seq; 2217 a.push([aOid[0].oid, aOid[1].oid]); 2218 } 2219 result.array = a; 2220 } catch(ex) { 2221 throw new _Error("malformed policyMappings"); 2222 } 2223 2224 return result; 2225 }; 2226 2227 /** 2228 * get PolicyConstraints extension value as JSON object<br/> 2229 * @name getExtPolicyConstraints 2230 * @memberOf X509# 2231 * @function 2232 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 2233 * @param {Boolean} critical flag (OPTIONAL) 2234 * @return {Object} JSON object of PolicyConstraints parameters or undefined 2235 * @since jsrsasign 10.6.1 x509 2.1.1 2236 * @see KJUR.asn1.x509.PolicyConstraints 2237 * 2238 * @description 2239 * This method will get certificate policies value 2240 * as an array of JSON object which has properties defined 2241 * in {@link KJUR.asn1.x509.PolicyConstraints}. 2242 * Result of this method can be passed to 2243 * {@link KJUR.asn1.x509.PolicyConstraints} constructor. 2244 * If there is no this extension in the certificate, 2245 * it returns undefined. 2246 * <br> 2247 * When hExtV and critical specified as arguments, return value 2248 * will be generated from them. 2249 * @example 2250 * x = new X509(sCertPEM); 2251 * x.getExtPolicyConstraints() → 2252 * { extname: "policyConstraints", 2253 * critical: true, 2254 * reqexp: 3, 2255 * inhibit: 3 } 2256 */ 2257 this.getExtPolicyConstraints = function(hExtV, critical) { 2258 var aExtVCritical = this.getCriticalExtV("policyConstraints", hExtV, critical); 2259 hExtV = aExtVCritical[0]; 2260 critical = aExtVCritical[1]; 2261 if (hExtV == null) return undefined; 2262 var result = {extname: "policyConstraints"}; 2263 if (critical) result.critical = true; 2264 2265 var p = _ASN1HEX_parse(hExtV); 2266 try { 2267 var aItem = p.seq; 2268 for (var i = 0; i < aItem.length; i++) { 2269 var pTag = aItem[i].tag; 2270 if (pTag.explicit != false) continue; 2271 if (pTag.tag == "80") result.reqexp = parseInt(pTag.hex, 16); 2272 if (pTag.tag == "81") result.inhibit = parseInt(pTag.hex, 16); 2273 } 2274 } catch(ex) { 2275 return new _Error("malformed policyConstraints value"); 2276 } 2277 return result; 2278 }; 2279 2280 /** 2281 * get InhibitAnyPolicy extension value as JSON object<br/> 2282 * @name getExtInhibitAnyPolicy 2283 * @memberOf X509# 2284 * @function 2285 * @param {String} hExtV hexadecimal string of extension value (OPTIONAL) 2286 * @param {Boolean} critical flag (OPTIONAL) 2287 * @return {Object} JSON object of InhibitAnyPolicy parameters or undefined 2288 * @since jsrsasign 10.6.1 x509 2.1.1 2289 * @see KJUR.asn1.x509.InhibitAnyPolicy 2290 * 2291 * @description 2292 * This method will get certificate policies value 2293 * as an array of JSON object which has properties defined 2294 * in {@link KJUR.asn1.x509.InhibitAnyPolicy}. 2295 * Result of this method can be passed to 2296 * {@link KJUR.asn1.x509.InhibitAnyPolicy} constructor. 2297 * If there is no this extension in the certificate, 2298 * it returns undefined. 2299 * <br> 2300 * When hExtV and critical specified as arguments, return value 2301 * will be generated from them. 2302 * @example 2303 * x = new X509(sCertPEM); 2304 * x.getExtInhibitAnyPolicy() → 2305 * { extname: "policyConstraints", 2306 * critical: true, 2307 * skip: 3 } 2308 * 2309 * x.getExtInhibitAnyPolicy("020103", true) → same as above 2310 */ 2311 this.getExtInhibitAnyPolicy = function(hExtV, critical) { 2312 var aExtVCritical = this.getCriticalExtV("inhibitAnyPolicy", hExtV, critical); 2313 hExtV = aExtVCritical[0]; 2314 critical = aExtVCritical[1]; 2315 if (hExtV == null) return undefined; 2316 var result = {extname: "inhibitAnyPolicy"}; 2317 if (critical) result.critical = true; 2318 2319 var skip = _getInt(hExtV, 0); 2320 if (skip == -1) return new _Error("wrong value"); 2321 result.skip = skip; 2322 return result; 2323 }; 2324 2325 /** 2326 * parse cRLNumber CRL extension as JSON object<br/> 2327 * @name getExtCRLNumber 2328 * @memberOf X509# 2329 * @function 2330 * @param {String} hExtV hexadecimal string of extension value 2331 * @param {Boolean} critical flag 2332 * @since jsrsasign 9.1.1 x509 2.0.1 2333 * @see KJUR.asn1.x509.CRLNumber 2334 * @see X509#getExtParamArray 2335 * @description 2336 * This method parses 2337 * CRLNumber CRL extension value defined in 2338 * <a href="https://tools.ietf.org/html/rfc5280#section-5.2.3"> 2339 * RFC 5280 5.2.3</a> as JSON object. 2340 * <pre> 2341 * id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } 2342 * CRLNumber ::= INTEGER (0..MAX) 2343 * </pre> 2344 * <br/> 2345 * Result of this method can be passed to 2346 * {@link KJUR.asn1.x509.CRLNumber} constructor. 2347 * @example 2348 * crl = X509CRL("-----BEGIN X509 CRL..."); 2349 * ... get hExtV and critical flag ... 2350 * crl.getExtCRLNumber("02...", false) → 2351 * {extname: "cRLNumber", num: {hex: "12af"}} 2352 */ 2353 this.getExtCRLNumber = function(hExtV, critical) { 2354 var result = {extname:"cRLNumber"}; 2355 if (critical) result.critical = true; 2356 2357 if (hExtV.substr(0, 2) == "02") { 2358 result.num = {hex: _getV(hExtV, 0)}; 2359 return result; 2360 } 2361 throw new _Error("hExtV parse error: " + hExtV); 2362 }; 2363 2364 /** 2365 * parse cRLReason CRL entry extension as JSON object<br/> 2366 * @name getExtCRLReason 2367 * @memberOf X509# 2368 * @function 2369 * @param {String} hExtV hexadecimal string of extension value 2370 * @param {Boolean} critical flag 2371 * @since jsrsasign 9.1.1 x509 2.0.1 2372 * @see KJUR.asn1.x509.CRLReason 2373 * @see X509#getExtParamArray 2374 * @description 2375 * This method parses 2376 * CRLReason CRL entry extension value defined in 2377 * <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1"> 2378 * RFC 5280 5.3.1</a> as JSON object. 2379 * <pre> 2380 * id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 } 2381 * -- reasonCode ::= { CRLReason } 2382 * CRLReason ::= ENUMERATED { 2383 * unspecified (0), 2384 * keyCompromise (1), 2385 * cACompromise (2), 2386 * affiliationChanged (3), 2387 * superseded (4), 2388 * cessationOfOperation (5), 2389 * certificateHold (6), 2390 * removeFromCRL (8), 2391 * privilegeWithdrawn (9), 2392 * aACompromise (10) } 2393 * </pre> 2394 * <br/> 2395 * Result of this method can be passed to 2396 * {@link KJUR.asn1.x509.CRLReason} constructor. 2397 * @example 2398 * crl = X509CRL("-----BEGIN X509 CRL..."); 2399 * ... get hExtV and critical flag ... 2400 * crl.getExtCRLReason("02...", false) → 2401 * {extname: "cRLReason", code: 3} 2402 */ 2403 this.getExtCRLReason = function(hExtV, critical) { 2404 var result = {extname:"cRLReason"}; 2405 if (critical) result.critical = true; 2406 2407 if (hExtV.substr(0, 2) == "0a") { 2408 result.code = parseInt(_getV(hExtV, 0), 16); 2409 return result; 2410 } 2411 throw new Error("hExtV parse error: " + hExtV); 2412 }; 2413 2414 /** 2415 * parse OCSPNonce OCSP extension as JSON object<br/> 2416 * @name getExtOcspNonce 2417 * @memberOf X509# 2418 * @function 2419 * @param {String} hExtV hexadecimal string of extension value 2420 * @param {Boolean} critical flag 2421 * @return {Array} JSON object of parsed OCSPNonce extension 2422 * @since jsrsasign 9.1.6 x509 2.0.3 2423 * @see KJUR.asn1.x509.OCSPNonce 2424 * @see X509#getExtParamArray 2425 * @see X509#getExtParam 2426 * @description 2427 * This method parses 2428 * Nonce OCSP extension value defined in 2429 * <a href="https://tools.ietf.org/html/rfc6960#section-4.4.1"> 2430 * RFC 6960 4.4.1</a> as JSON object. 2431 * <pre> 2432 * id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp } 2433 * id-pkix-ocsp-nonce OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 } 2434 * Nonce ::= OCTET STRING 2435 * </pre> 2436 * <br/> 2437 * Result of this method can be passed to 2438 * {@link KJUR.asn1.x509.OCSPNonce} constructor. 2439 * @example 2440 * x = new X509(); 2441 * x.getExtOcspNonce(<<extn hex value >>) → 2442 * { extname: "ocspNonce", hex: "1a2b..." } 2443 */ 2444 this.getExtOcspNonce = function(hExtV, critical) { 2445 var result = {extname:"ocspNonce"}; 2446 if (critical) result.critical = true; 2447 2448 var hNonce = _getV(hExtV, 0); 2449 result.hex = hNonce; 2450 2451 return result; 2452 }; 2453 2454 /** 2455 * parse OCSPNoCheck OCSP extension as JSON object<br/> 2456 * @name getExtOcspNoCheck 2457 * @memberOf X509# 2458 * @function 2459 * @param {String} hExtV hexadecimal string of extension value 2460 * @param {Boolean} critical flag 2461 * @return {Array} JSON object of parsed OCSPNoCheck extension 2462 * @since jsrsasign 9.1.6 x509 2.0.3 2463 * @see KJUR.asn1.x509.OCSPNoCheck 2464 * @see X509#getExtParamArray 2465 * @see X509#getExtParam 2466 * @description 2467 * This method parses 2468 * OCSPNoCheck extension value defined in 2469 * <a href="https://tools.ietf.org/html/rfc6960#section-4.2.2.2.1"> 2470 * RFC 6960 4.2.2.2.1</a> as JSON object. 2471 * <pre> 2472 * id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 } 2473 * </pre> 2474 * <br/> 2475 * Result of this method can be passed to 2476 * {@link KJUR.asn1.x509.OCSPNoCheck} constructor. 2477 * @example 2478 * x = new X509(); 2479 * x.getExtOcspNoCheck(<<extn hex value >>) → 2480 * { extname: "ocspNoCheck" } 2481 */ 2482 this.getExtOcspNoCheck = function(hExtV, critical) { 2483 var result = {extname:"ocspNoCheck"}; 2484 if (critical) result.critical = true; 2485 2486 return result; 2487 }; 2488 2489 /** 2490 * parse AdobeTimeStamp extension as JSON object<br/> 2491 * @name getExtAdobeTimeStamp 2492 * @memberOf X509# 2493 * @function 2494 * @param {String} hExtV hexadecimal string of extension value 2495 * @param {Boolean} critical flag 2496 * @return {Array} JSON object of parsed AdobeTimeStamp extension 2497 * @since jsrsasign 10.0.1 x509 2.0.5 2498 * @see KJUR.asn1.x509.AdobeTimeStamp 2499 * @see X509#getExtParamArray 2500 * @see X509#getExtParam 2501 * @description 2502 * This method parses 2503 * X.509v3 AdobeTimeStamp private extension value defined in the 2504 * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSigDC/oids.html"> 2505 * Adobe site</a> as JSON object. 2506 * This extension provides the URL location for time stamp service. 2507 * <pre> 2508 * adbe- OBJECT IDENTIFIER ::= { adbe(1.2.840.113583) acrobat(1) security(1) x509Ext(9) 1 } 2509 * ::= SEQUENCE { 2510 * version INTEGER { v1(1) }, -- extension version 2511 * location GeneralName (In v1 GeneralName can be only uniformResourceIdentifier) 2512 * requiresAuth boolean (default false), OPTIONAL } 2513 * </pre> 2514 * <br/> 2515 * Result of this method can be passed to 2516 * {@link KJUR.asn1.x509.AdobeTimeStamp} constructor. 2517 * <br/> 2518 * NOTE: This extesion doesn't seem to have official name. This may be called as "pdfTimeStamp". 2519 * @example 2520 * x.getExtAdobeTimeStamp(<<extn hex value >>) → 2521 * { extname: "adobeTimeStamp", uri: "http://tsa.example.com/" reqauth: true } 2522 */ 2523 this.getExtAdobeTimeStamp = function(hExtV, critical) { 2524 if (hExtV === undefined && critical === undefined) { 2525 var info = this.getExtInfo("adobeTimeStamp"); 2526 if (info === undefined) return undefined; 2527 hExtV = _getTLV(this.hex, info.vidx); 2528 critical = info.critical; 2529 } 2530 2531 var result = {extname:"adobeTimeStamp"}; 2532 if (critical) result.critical = true; 2533 2534 var a = _getChildIdx(hExtV, 0); 2535 if (a.length > 1) { 2536 var hGN = _getTLV(hExtV, a[1]) 2537 var gnParam = this.getGeneralName(hGN); 2538 if (gnParam.uri != undefined) { 2539 result.uri = gnParam.uri; 2540 } 2541 } 2542 if (a.length > 2) { 2543 var hBool = _getTLV(hExtV, a[2]); 2544 if (hBool == "0101ff") result.reqauth = true; 2545 if (hBool == "010100") result.reqauth = false; 2546 } 2547 2548 return result; 2549 }; 2550 2551 /** 2552 * parse SubjectDirectoryAttributes extension as JSON object<br/> 2553 * @name getExtSubjectDirectoryAttributes 2554 * @memberOf X509# 2555 * @function 2556 * @param {String} hExtV hexadecimal string of extension value 2557 * @param {Boolean} critical flag 2558 * @return {Array} JSON object of parsed SubjectDirectoryAttributes extension 2559 * @since jsrsasign 10.8.4 x509 2.1.4 2560 * @see KJUR.asn1.x509.SubjectDirectoryAttributes 2561 * @see X509#getExtParamArray 2562 * @see X509#getExtParam 2563 * 2564 * @description 2565 * This method parses 2566 * SubjectDirectoryAttributes extension value defined in the 2567 * defined in <a href="https://tools.ietf.org/html/rfc3739#section-3.3.2"> 2568 * RFC 3739 Qualified Certificate Profile section 3.3.2</a> as JSON object. 2569 * <pre> 2570 * SubjectDirectoryAttributes ::= Attributes 2571 * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute 2572 * Attribute ::= SEQUENCE { 2573 * type AttributeType 2574 * values SET OF AttributeValue } 2575 * AttributeType ::= OBJECT IDENTIFIER 2576 * AttributeValue ::= ANY DEFINED BY AttributeType 2577 * </pre> 2578 * <br/> 2579 * Result of this method can be passed to 2580 * {@link KJUR.asn1.x509.SubjectDirectoryAttributes} constructor. 2581 * 2582 * @example 2583 * x.getExtSubjectDirectoryAttributes(<<extn hex value >>) → 2584 * { "extname": "SubjectDirectoryAttributes", 2585 * "array": [ 2586 * { "attr": "gender", "array": [{"prnstr": {"str": "female"}}] }, 2587 * { "attr": "1.2.3.4.5", "array": [{"prnstr": {"str": "aaa"}}, {"utf8str": {"str": "bbb"}}] } 2588 * ] } 2589 */ 2590 this.getExtSubjectDirectoryAttributes = function(hExtV, critical) { 2591 if (hExtV === undefined && critical === undefined) { 2592 var info = this.getExtInfo("subjectDirectoryAttributes"); 2593 if (info === undefined) return undefined; 2594 hExtV = _getTLV(this.hex, info.vidx); 2595 critical = info.critical; 2596 } 2597 2598 var result = { extname: "subjectDirectoryAttributes" }; 2599 if (critical) result.critical = true; 2600 try { 2601 var pASN1 = _ASN1HEX_parse(hExtV); 2602 var aValue = []; 2603 for (var i = 0; i < pASN1.seq.length; i++) { 2604 var aASN1Attribute = pASN1.seq[i]; 2605 var attrType = aryval(aASN1Attribute, "seq.0.oid"); 2606 var attrValue = aryval(aASN1Attribute, "seq.1.set"); 2607 if (attrType == undefined || attrValue == undefined) throw "error"; 2608 aValue.push({ attr: attrType, array: attrValue }); 2609 } 2610 result.array = aValue; 2611 return result; 2612 } catch(ex) { 2613 throw new Error("malformed subjectDirectoryAttributes extension value"); 2614 } 2615 } 2616 2617 // ===== BEGIN X500Name related ===================================== 2618 /* 2619 * convert ASN.1 parsed object to attrTypeAndValue assoc array<br/> 2620 * @name _convATV 2621 * @param p associative array of parsed attrTypeAndValue object 2622 * @return attrTypeAndValue associative array 2623 * @since jsrsasign 10.5.12 x509 2.0.14 2624 * @example 2625 * _convATV({seq: [...]} &rarr: {type:"C",value:"JP",ds:"prn"} 2626 */ 2627 var _convATV = function(p) { 2628 var result = {}; 2629 try { 2630 var name = p.seq[0].oid; 2631 var oid = KJUR.asn1.x509.OID.name2oid(name); 2632 result.type = KJUR.asn1.x509.OID.oid2atype(oid); 2633 var item1 = p.seq[1]; 2634 if (item1.utf8str != undefined) { 2635 result.ds = "utf8"; 2636 result.value = item1.utf8str.str; 2637 } else if (item1.numstr != undefined) { 2638 result.ds = "num"; 2639 result.value = item1.numstr.str; 2640 } else if (item1.telstr != undefined) { 2641 result.ds = "tel"; 2642 result.value = item1.telstr.str; 2643 } else if (item1.prnstr != undefined) { 2644 result.ds = "prn"; 2645 result.value = item1.prnstr.str; 2646 } else if (item1.ia5str != undefined) { 2647 result.ds = "ia5"; 2648 result.value = item1.ia5str.str; 2649 } else if (item1.visstr != undefined) { 2650 result.ds = "vis"; 2651 result.value = item1.visstr.str; 2652 } else if (item1.bmpstr != undefined) { 2653 result.ds = "bmp"; 2654 result.value = item1.bmpstr.str; 2655 } else { 2656 throw "error"; 2657 } 2658 return result; 2659 } catch(ex) { 2660 throw new Erorr("improper ASN.1 parsed AttrTypeAndValue"); 2661 } 2662 }; 2663 2664 /* 2665 * convert ASN.1 parsed object to RDN array<br/> 2666 * @name _convRDN 2667 * @param p associative array of parsed RDN object 2668 * @return RDN array 2669 * @since jsrsasign 10.5.12 x509 2.0.14 2670 * @example 2671 * _convRDN({set: [...]} &rarr: [{type:"C",value:"JP",ds:"prn"}] 2672 */ 2673 var _convRDN = function(p) { 2674 try { 2675 return p.set.map(function(pATV){return _convATV(pATV)}); 2676 } catch(ex) { 2677 throw new Error("improper ASN.1 parsed RDN: " + ex); 2678 } 2679 }; 2680 2681 /* 2682 * convert ASN.1 parsed object to X500Name array<br/> 2683 * @name _convX500Name 2684 * @param p associative array of parsed X500Name array object 2685 * @return RDN array 2686 * @since jsrsasign 10.5.12 x509 2.0.14 2687 * @example 2688 * _convX500Name({seq: [...]} &rarr: [[{type:"C",value:"JP",ds:"prn"}]] 2689 */ 2690 var _convX500Name = function(p) { 2691 try { 2692 return p.seq.map(function(pRDN){return _convRDN(pRDN)}); 2693 } catch(ex) { 2694 throw new Error("improper ASN.1 parsed X500Name: " + ex); 2695 } 2696 }; 2697 2698 this.getX500NameRule = function(aDN) { 2699 var isPRNRule = true; 2700 var isUTF8Rule = true; 2701 var isMixedRule = false; 2702 var logfull = ""; 2703 var logcheck = ""; 2704 var lasttag = null; 2705 2706 var a = []; 2707 for (var i = 0; i < aDN.length; i++) { 2708 var aRDN = aDN[i]; 2709 for (var j = 0; j < aRDN.length; j++) { 2710 a.push(aRDN[j]); 2711 } 2712 } 2713 2714 for (var i = 0; i < a.length; i++) { 2715 var item = a[i]; 2716 var tag = item.ds; 2717 var value = item.value; 2718 var type = item.type; 2719 logfull += ":" + tag; 2720 2721 if (tag != "prn" && tag != "utf8" && tag != "ia5") { 2722 return "mixed"; 2723 } 2724 if (tag == "ia5") { 2725 if (type != "CN") { 2726 return "mixed"; 2727 } else { 2728 if (! KJUR.lang.String.isMail(value)) { 2729 return "mixed"; 2730 } else { 2731 continue; 2732 } 2733 } 2734 } 2735 if (type == "C") { 2736 if (tag == "prn") { 2737 continue; 2738 } else { 2739 return "mixed"; 2740 } 2741 } 2742 logcheck += ":" + tag; 2743 if (lasttag == null) { 2744 lasttag = tag; 2745 } else { 2746 if (lasttag !== tag) return "mixed"; 2747 } 2748 } 2749 if (lasttag == null) { 2750 return "prn"; 2751 } else { 2752 return lasttag; 2753 } 2754 }; 2755 2756 /** 2757 * get AttributeTypeAndValue ASN.1 structure parameter as JSON object<br/> 2758 * @name getAttrTypeAndValue 2759 * @memberOf X509# 2760 * @function 2761 * @param {String} h hexadecimal string of AttributeTypeAndValue 2762 * @return {Object} JSON object of AttributeTypeAndValue parameters 2763 * @since jsrsasign 9.0.0 x509 2.0.0 2764 * @see X509#getX500Name 2765 * @see X509#getRDN 2766 * @description 2767 * This method will get AttributeTypeAndValue parameters defined in 2768 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2769 * RFC 5280 4.1.2.4</a>. 2770 * <pre> 2771 * AttributeTypeAndValue ::= SEQUENCE { 2772 * type AttributeType, 2773 * value AttributeValue } 2774 * AttributeType ::= OBJECT IDENTIFIER 2775 * AttributeValue ::= ANY -- DEFINED BY AttributeType 2776 * </pre> 2777 * <ul> 2778 * <li>{String}type - AttributeType name or OID(ex. C,O,CN)</li> 2779 * <li>{String}value - raw string of ASN.1 value of AttributeValue</li> 2780 * <li>{String}ds - DirectoryString type of AttributeValue</li> 2781 * </ul> 2782 * "ds" has one of following value: 2783 * <ul> 2784 * <li>utf8 - (0x0c) UTF8String</li> 2785 * <li>num - (0x12) NumericString</li> 2786 * <li>prn - (0x13) PrintableString</li> 2787 * <li>tel - (0x14) TeletexString</li> 2788 * <li>ia5 - (0x16) IA5String</li> 2789 * <li>vis - (0x1a) VisibleString</li> 2790 * <li>bmp - (0x1e) BMPString</li> 2791 * </ul> 2792 * @example 2793 * x = new X509(); 2794 * x.getAttrTypeAndValue("30...") → 2795 * {type:"CN",value:"john.smith@example.com",ds:"ia5"} or 2796 * {type:"O",value:"Sample Corp.",ds:"prn"} 2797 */ 2798 // unv - (0x1c??) UniversalString ... for future 2799 this.getAttrTypeAndValue = function(h) { 2800 var p = _ASN1HEX_parse(h); 2801 return _convATV(p); 2802 }; 2803 2804 /** 2805 * get RelativeDistinguishedName ASN.1 structure parameter array<br/> 2806 * @name getRDN 2807 * @memberOf X509# 2808 * @function 2809 * @param {String} h hexadecimal string of RDN 2810 * @return {Array} array of AttrTypeAndValue parameters 2811 * @since jsrsasign 9.0.0 x509 2.0.0 2812 * @see X509#getX500Name 2813 * @see X509#getRDN 2814 * @see X509#getAttrTypeAndValue 2815 * @description 2816 * This method will get RelativeDistinguishedName parameters defined in 2817 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2818 * RFC 5280 4.1.2.4</a>. 2819 * <pre> 2820 * RelativeDistinguishedName ::= 2821 * SET SIZE (1..MAX) OF AttributeTypeAndValue 2822 * </pre> 2823 * @example 2824 * x = new X509(); 2825 * x.getRDN("31...") → 2826 * [{type:"C",value:"US",ds:"prn"}] or 2827 * [{type:"O",value:"Sample Corp.",ds:"prn"}] or 2828 * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}] 2829 */ 2830 this.getRDN = function(h) { 2831 var p = _ASN1HEX_parse(h); 2832 return _convRDN(p); 2833 }; 2834 2835 /** 2836 * get X.500 Name ASN.1 structure parameter array<br/> 2837 * @name getX500NameArray 2838 * @memberOf X509# 2839 * @function 2840 * @param {String} h hexadecimal string of Name 2841 * @return {Array} array of RDN parameter array 2842 * @since jsrsasign 10.0.6 x509 2.0.9 2843 * @see X509#getX500Name 2844 * @see X509#getRDN 2845 * @see X509#getAttrTypeAndValue 2846 * @description 2847 * This method will get Name parameter defined in 2848 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2849 * RFC 5280 4.1.2.4</a>. 2850 * <pre> 2851 * Name ::= CHOICE { -- only one possibility for now -- 2852 * rdnSequence RDNSequence } 2853 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 2854 * </pre> 2855 * @example 2856 * x = new X509(); 2857 * x.getX500NameArray("30...") → 2858 * [[{type:"C",value:"US",ds:"prn"}], 2859 * [{type:"O",value:"Sample Corp.",ds:"utf8"}], 2860 * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}]] 2861 */ 2862 this.getX500NameArray = function(h) { 2863 var p = _ASN1HEX_parse(h); 2864 return _convX500Name(p); 2865 }; 2866 2867 /** 2868 * get Name ASN.1 structure parameter array<br/> 2869 * @name getX500Name 2870 * @memberOf X509# 2871 * @function 2872 * @param {String} h hexadecimal string of Name 2873 * @param {boolean} flagCanon flag to conclude canonicalized name (DEFAULT false) 2874 * @param {boolean} flagHex flag to conclude hexadecimal string (DEFAULT false) 2875 * @return {Array} array of RDN parameter array 2876 * @since jsrsasign 9.0.0 x509 2.0.0 2877 * @see X509#getX500NameArray 2878 * @see X509#getRDN 2879 * @see X509#getAttrTypeAndValue 2880 * @see X509#c14nRDNArray 2881 * @see KJUR.asn1.x509.X500Name 2882 * @see KJUR.asn1.x509.GeneralName 2883 * @see KJUR.asn1.x509.GeneralNames 2884 * 2885 * @description 2886 * This method will get Name parameter defined in 2887 * <a href="https://tools.ietf.org/html/rfc5280#section-4.1.2.4"> 2888 * RFC 5280 4.1.2.4</a>. 2889 * <pre> 2890 * Name ::= CHOICE { -- only one possibility for now -- 2891 * rdnSequence RDNSequence } 2892 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 2893 * </pre> 2894 * <br> 2895 * NOTE: From jsrsasign 10.6.0, flagHex and flagCanon has been 2896 * supported to conclude a canonicalized name for caseIgnoreMatch 2897 * desribed in <a href="https://tools.ietf.org/html/rfc4518"> 2898 * RFC 4518</a>. 2899 * 2900 * @example 2901 * x = new X509(); 2902 * x.getX500Name("30...") → 2903 * { array: [ 2904 * [{type:"C",value:"US",ds:"prn"}], 2905 * [{type:"O",value:"Sample Corp.",ds:"utf8"}], 2906 * [{type:"CN",value:"john.smith@example.com",ds:"ia5"}] 2907 * ], 2908 * str: "/C=US/O=Sample Corp./CN=john.smith@example.com", 2909 * hex: "30..." } 2910 * 2911 * x.getX500Name("30...", true) → 2912 * { array: [ 2913 * [{type:"C",value:"US",ds:"prn"}], 2914 * [{type:"O",value:"Sample Corp.",ds:"utf8"}] 2915 * ], 2916 * str: "/C=US/O=Sample Corp.", 2917 * canon: "/c=us/o=sample corp.", 2918 * hex: "30..." } 2919 */ 2920 this.getX500Name = function(h, flagCanon, flagHex) { 2921 var a = this.getX500NameArray(h); 2922 var s = this.dnarraytostr(a); 2923 var result = { str: s }; 2924 2925 result.array = a; 2926 if (flagHex == true) result.hex = h; 2927 if (flagCanon == true) result.canon = this.c14nRDNArray(a); 2928 return result; 2929 }; 2930 2931 // ===== END X500Name related ===================================== 2932 2933 // ===== BEGIN read certificate ===================================== 2934 /** 2935 * read PEM formatted X.509 certificate from string.<br/> 2936 * @name readCertPEM 2937 * @memberOf X509# 2938 * @function 2939 * @param {String} sCertPEM string for PEM formatted X.509 certificate 2940 * @example 2941 * x = new X509(); 2942 * x.readCertPEM(sCertPEM); // read certificate 2943 */ 2944 this.readCertPEM = function(sCertPEM) { 2945 this.readCertHex(_pemtohex(sCertPEM)); 2946 }; 2947 2948 /** 2949 * read a hexadecimal string of X.509 certificate<br/> 2950 * @name readCertHex 2951 * @memberOf X509# 2952 * @function 2953 * @param {String} sCertHex hexadecimal string of X.509 certificate 2954 * @since jsrsasign 7.1.4 x509 1.1.13 2955 * @description 2956 * NOTE: {@link X509#parseExt} will called internally since jsrsasign 7.2.0. 2957 * @example 2958 * x = new X509(); 2959 * x.readCertHex("3082..."); // read certificate 2960 */ 2961 this.readCertHex = function(sCertHex) { 2962 this.hex = sCertHex; 2963 this.getVersion(); // set version parameter 2964 2965 try { 2966 _getIdxbyList(this.hex, 0, [0, 7], "a3"); // has [3] v3ext 2967 this.parseExt(); 2968 } catch(ex) {}; 2969 }; 2970 2971 // ===== END read certificate ===================================== 2972 2973 /** 2974 * get JSON object of certificate parameters<br/> 2975 * @name getParam 2976 * @memberOf X509# 2977 * @function 2978 * @param {Object} option optional setting for return object 2979 * @return {Object} JSON object of certificate parameters 2980 * @since jsrsasign 9.0.0 x509 2.0.0 2981 * @see KJUR.asn1.x509.X509Util.newCertPEM 2982 * 2983 * @description 2984 * This method returns a JSON object of the certificate 2985 * parameters. Return value can be passed to 2986 * {@link KJUR.asn1.x509.X509Util.newCertPEM}. 2987 * <br/> 2988 * NOTE1: From jsrsasign 10.5.16, optional argument can be applied. 2989 * It can have following members: 2990 * <ul> 2991 * <li>tbshex - (boolean) tbshex member with hex value of 2992 * tbsCertificate will be added if true (DEFAULT undefined)</li> 2993 * <li>nodnarray - (boolean) array member for subject and 2994 * issuer will be deleted to simplify it if true (DEFAULT undefined)<li> 2995 * <li>dncanon - (boolean) add canon member to subject and issuer for DN StringPrep if true(DEFAULT undefined)</li> 2996 * <li>dnhex - (boolean) add hex member to subject and issuer if true(DEFAULT undefined)</li> 2997 * </ul> 2998 * <br/> 2999 * NOTE2: From jsrsasign 10.6.0, member "dncanon" and "dnhex" supported 3000 * in the "option" argument. 3001 * 3002 * @example 3003 * x = new X509(); 3004 * x.readCertPEM("-----BEGIN CERTIFICATE..."); 3005 * x.getParam() → 3006 * {version:3, 3007 * serial:{hex:"12ab"}, 3008 * sigalg:"SHA256withRSA", 3009 * issuer: {array:[[{type:'CN',value:'CA1',ds:'prn'}]],str:"/O=CA1"}, 3010 * notbefore:"160403023700Z", 3011 * notafter:"160702023700Z", 3012 * subject: {array:[[{type:'CN',value:'Test1',ds:'prn'}]],str:"/CN=Test1"}, 3013 * sbjpubkey:"-----BEGIN PUBLIC KEY...", 3014 * ext:[ 3015 * {extname:"keyUsage",critical:true,names:["digitalSignature"]}, 3016 * {extname:"basicConstraints",critical:true}, 3017 * {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}}, 3018 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3019 * {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]}, 3020 * {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]} 3021 * ], 3022 * sighex:"0b76...8" 3023 * }; 3024 * 3025 * x.getParam({tbshex: true}) → { ... , tbshex: "30..." } 3026 * x.getParam({nodnarray: true}) → {issuer: {str: "/C=JP"}, ...} 3027 * x.getParam({dncanon: true}) → {... {issuer: {canon: "/c=jp/o=..."} ...} ...} 3028 * x.getParam({dnhex: true}) → {... {issuer: {hex: "30..."} ...} ...} 3029 */ 3030 this.getParam = function(option) { 3031 var result = {}; 3032 if (option == undefined) option = {}; 3033 3034 result.version = this.getVersion(); 3035 result.serial = {hex: this.getSerialNumberHex()}; 3036 result.sigalg = this.getSignatureAlgorithmField(); 3037 result.issuer = this.getIssuer(option.dncanon, option.dnhex); 3038 result.notbefore = this.getNotBefore(); 3039 result.notafter = this.getNotAfter(); 3040 result.subject = this.getSubject(option.dncanon, option.dnhex); 3041 result.sbjpubkey = hextopem(this.getPublicKeyHex(), "PUBLIC KEY"); 3042 if (this.aExtInfo != undefined && 3043 this.aExtInfo.length > 0) { 3044 result.ext = this.getExtParamArray(); 3045 } 3046 result.sighex = this.getSignatureValueHex(); 3047 3048 // for options 3049 if (option.tbshex == true) { 3050 result.tbshex = _getTLVbyList(this.hex, 0, [0]); 3051 } 3052 if (option.nodnarray == true) { 3053 delete result.issuer.array; 3054 delete result.subject.array; 3055 } 3056 3057 return result; 3058 }; 3059 3060 /** 3061 * get array of certificate extension parameter JSON object<br/> 3062 * @name getExtParamArray 3063 * @memberOf X509# 3064 * @function 3065 * @param {String} hExtSeq hexadecimal string of SEQUENCE of Extension 3066 * @return {Array} array of certificate extension parameter JSON object 3067 * @since jsrsasign 9.0.0 x509 2.0.0 3068 * @see KJUR.asn1.x509.X509Util.newCertPEM 3069 * @see X509#getParam 3070 * @see X509#getExtParam 3071 * @see X509CRL#getParam 3072 * @see KJUR.asn1.csr.CSRUtil.getParam 3073 * 3074 * @description 3075 * This method returns an array of certificate extension 3076 * parameters. 3077 * <br/> 3078 * NOTE: Argument "hExtSeq" have been supported since jsrsasign 9.1.1. 3079 * 3080 * @example 3081 * x = new X509(); 3082 * x.readCertPEM("-----BEGIN CERTIFICATE..."); 3083 * x.getExtParamArray() → 3084 * [ {extname:"keyUsage",critical:true,names:["digitalSignature"]}, 3085 * {extname:"basicConstraints",critical:true}, 3086 * {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}}, 3087 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3088 * {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]}, 3089 * {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]}] 3090 */ 3091 this.getExtParamArray = function(hExtSeq) { 3092 if (hExtSeq == undefined) { 3093 // for X.509v3 certificate 3094 var idx1 = _getIdxbyListEx(this.hex, 0, [0, "[3]"]); 3095 if (idx1 != -1) { 3096 hExtSeq = _getTLVbyListEx(this.hex, 0, [0, "[3]", 0], "30"); 3097 } 3098 } 3099 var result = []; 3100 var aIdx = _getChildIdx(hExtSeq, 0); 3101 3102 for (var i = 0; i < aIdx.length; i++) { 3103 var hExt = _getTLV(hExtSeq, aIdx[i]); 3104 var extParam = this.getExtParam(hExt); 3105 if (extParam != null) result.push(extParam); 3106 } 3107 3108 return result; 3109 }; 3110 3111 /** 3112 * get a extension parameter JSON object<br/> 3113 * @name getExtParam 3114 * @memberOf X509# 3115 * @function 3116 * @param {String} hExt hexadecimal string of Extension 3117 * @return {Array} Extension parameter JSON object 3118 * @since jsrsasign 9.1.1 x509 2.0.1 3119 * @see KJUR.asn1.x509.X509Util.newCertPEM 3120 * @see X509#getParam 3121 * @see X509#getExtParamArray 3122 * @see X509CRL#getParam 3123 * @see KJUR.asn1.csr.CSRUtil.getParam 3124 * 3125 * @description 3126 * This method returns a extension parameters as JSON object. 3127 * 3128 * @example 3129 * x = new X509(); 3130 * ... 3131 * x.getExtParam("30...") → 3132 * {extname:"keyUsage",critical:true,names:["digitalSignature"]} 3133 */ 3134 this.getExtParam = function(hExt) { 3135 var result = {}; 3136 var aIdx = _getChildIdx(hExt, 0); 3137 var aIdxLen = aIdx.length; 3138 if (aIdxLen != 2 && aIdxLen != 3) 3139 throw new Error("wrong number elements in Extension: " + 3140 aIdxLen + " " + hExt); 3141 3142 var oid = _hextooidstr(_getVbyList(hExt, 0, [0], "06")); 3143 3144 var critical = false; 3145 if (aIdxLen == 3 && _getTLVbyList(hExt, 0, [1]) == "0101ff") 3146 critical = true; 3147 3148 var hExtV = _getTLVbyList(hExt, 0, [aIdxLen - 1, 0]); 3149 3150 var extParam = undefined; 3151 if (oid == "2.5.29.14") { 3152 extParam = this.getExtSubjectKeyIdentifier(hExtV, critical); 3153 } else if (oid == "2.5.29.15") { 3154 extParam = this.getExtKeyUsage(hExtV, critical); 3155 } else if (oid == "2.5.29.17") { 3156 extParam = this.getExtSubjectAltName(hExtV, critical); 3157 } else if (oid == "2.5.29.18") { 3158 extParam = this.getExtIssuerAltName(hExtV, critical); 3159 } else if (oid == "2.5.29.19") { 3160 extParam = this.getExtBasicConstraints(hExtV, critical); 3161 } else if (oid == "2.5.29.30") { 3162 extParam = this.getExtNameConstraints(hExtV, critical); 3163 } else if (oid == "2.5.29.31") { 3164 extParam = this.getExtCRLDistributionPoints(hExtV, critical); 3165 } else if (oid == "2.5.29.32") { 3166 extParam = this.getExtCertificatePolicies(hExtV, critical); 3167 } else if (oid == "2.5.29.33") { 3168 extParam = this.getExtPolicyMappings(hExtV, critical); 3169 } else if (oid == "2.5.29.35") { 3170 extParam = this.getExtAuthorityKeyIdentifier(hExtV, critical); 3171 } else if (oid == "2.5.29.36") { 3172 extParam = this.getExtPolicyConstraints(hExtV, critical); 3173 } else if (oid == "2.5.29.37") { 3174 extParam = this.getExtExtKeyUsage(hExtV, critical); 3175 } else if (oid == "2.5.29.54") { 3176 extParam = this.getExtInhibitAnyPolicy(hExtV, critical); 3177 } else if (oid == "1.3.6.1.5.5.7.1.1") { 3178 extParam = this.getExtAuthorityInfoAccess(hExtV, critical); 3179 } else if (oid == "2.5.29.20") { 3180 extParam = this.getExtCRLNumber(hExtV, critical); 3181 } else if (oid == "2.5.29.21") { 3182 extParam = this.getExtCRLReason(hExtV, critical); 3183 } else if (oid == "2.5.29.9") { 3184 extParam = this.getExtSubjectDirectoryAttributes(hExtV, critical); 3185 } else if (oid == "1.3.6.1.5.5.7.48.1.2") { 3186 extParam = this.getExtOcspNonce(hExtV, critical); 3187 } else if (oid == "1.3.6.1.5.5.7.48.1.5") { 3188 extParam = this.getExtOcspNoCheck(hExtV, critical); 3189 } else if (oid == "1.2.840.113583.1.1.9.1") { 3190 extParam = this.getExtAdobeTimeStamp(hExtV, critical); 3191 } else if (X509.EXT_PARSER[oid] != undefined) { 3192 extParam = X509.EXT_PARSER[oid](oid, critical, hExtV); 3193 } 3194 if (extParam != undefined) return extParam; 3195 3196 // for private or unsupported extension 3197 var privateParam = { extname: oid, extn: hExtV }; 3198 try { 3199 privateParam.extn = _ASN1HEX_parse(hExtV); 3200 } catch(ex) {} 3201 if (critical) privateParam.critical = true; 3202 return privateParam; 3203 }; 3204 3205 /** 3206 * find extension parameter in array<br/> 3207 * @name findExt 3208 * @memberOf X509# 3209 * @function 3210 * @param {Array} aExt array of extension parameters 3211 * @param {String} extname extension name 3212 * @return {Array} extension parameter in the array or null 3213 * @since jsrsasign 10.0.3 x509 2.0.7 3214 * @see X509#getParam 3215 * 3216 * @description 3217 * This method returns an extension parameter for 3218 * specified extension name in the array. 3219 * This method is useful to update extension parameter value. 3220 * When there is no such extension with the extname, 3221 * this returns "null". 3222 * 3223 * @example 3224 * // (1) 3225 * x = new X509(CERTPEM); 3226 * params = x.getParam(); 3227 * pSKID = x.findExt(params.ext, "subjectKeyIdentifier"); 3228 * pSKID.kid = "1234abced..."; // skid in the params is updated. 3229 * // then params was updated 3230 * 3231 * // (2) another example 3232 * aExt = [ 3233 * {extname:"keyUsage",critical:true,names:["digitalSignature"]}, 3234 * {extname:"basicConstraints",critical:true}, 3235 * {extname:"subjectKeyIdentifier",kid:{hex:"f2eb..."}}, 3236 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3237 * {extname:"authorityInfoAccess",array:[{ocsp:"http://ocsp.example.com/"}]}, 3238 * {extname:"certificatePolicies",array:[{policyoid:"2.23.140.1.2.1"}]} 3239 * ]; 3240 * var x = new X509(); 3241 * x.findExt(aExt, "authorityKeyInfoAccess").array[0].ocsp = "http://aaa.com"; 3242 * pKU = x.findExt(aExt, "keyUsage"); 3243 * delete pKU["critical"]; // clear criticla flag 3244 * pKU.names = ["keyCertSign", "cRLSign"]; 3245 * // then aExt was updated 3246 */ 3247 this.findExt = function(aExt, extname) { 3248 for (var i = 0; i < aExt.length; i++) { 3249 if (aExt[i].extname == extname) return aExt[i]; 3250 } 3251 return null; 3252 3253 }; 3254 3255 /** 3256 * update CRLDistributionPoints Full URI in parameter<br/> 3257 * @name updateCDPFullURI 3258 * @memberOf X509# 3259 * @function 3260 * @param {Array} aExt array of extension parameters 3261 * @param {String} newURI string of new uri 3262 * @since jsrsasign 10.0.4 x509 2.0.8 3263 * @see X509#findExt 3264 * @see KJUR.asn1.x509.CRLDistributionPoints 3265 * 3266 * @description 3267 * This method updates Full URI of CRLDistributionPoints extension 3268 * in the extension parameter array if it exists. 3269 * 3270 * @example 3271 * aExt = [ 3272 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3273 * {extname:"cRLDistributionPoints", 3274 * array:[{dpname:{full:[{uri:"http://example.com/a.crl"}]}}]}, 3275 * ]; 3276 * x = new X509(); 3277 * x.updateCDPFullURI(aExt, "http://crl2.example.new/b.crl"); 3278 */ 3279 this.updateExtCDPFullURI = function(aExt, newURI) { 3280 var pExt = this.findExt(aExt, "cRLDistributionPoints"); 3281 if (pExt == null) return; 3282 if (pExt.array == undefined) return; 3283 var aDP = pExt.array; 3284 for (var i = 0; i < aDP.length; i++) { 3285 if (aDP[i].dpname == undefined) continue; 3286 if (aDP[i].dpname.full == undefined) continue; 3287 var aURI = aDP[i].dpname.full; 3288 for (var j = 0; j < aURI.length; j++) { 3289 var pURI = aURI[i]; 3290 if (pURI.uri == undefined) continue; 3291 pURI.uri = newURI; 3292 } 3293 } 3294 }; 3295 3296 /** 3297 * update authorityInfoAccess ocsp in parameter<br/> 3298 * @name updateAIAOCSP 3299 * @memberOf X509# 3300 * @function 3301 * @param {Array} aExt array of extension parameters 3302 * @param {String} newURI string of new uri 3303 * @since jsrsasign 10.0.4 x509 2.0.8 3304 * @see X509#findExt 3305 * @see KJUR.asn1.x509.AuthorityInfoAccess 3306 * 3307 * @description 3308 * This method updates "ocsp" accessMethod URI of 3309 * AuthorityInfoAccess extension 3310 * in the extension parameter array if it exists. 3311 * 3312 * @example 3313 * aExt = [ 3314 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3315 * {extname:"authoriyInfoAccess", 3316 * array:[ 3317 * {ocsp: "http://ocsp1.example.com"}, 3318 * {caissuer: "http://example.com/a.crt"} 3319 * ]} 3320 * ]; 3321 * x = new X509(); 3322 * x.updateAIAOCSP(aExt, "http://ocsp2.example.net"); 3323 */ 3324 this.updateExtAIAOCSP = function(aExt, newURI) { 3325 var pExt = this.findExt(aExt, "authorityInfoAccess"); 3326 if (pExt == null) return; 3327 if (pExt.array == undefined) return; 3328 var a = pExt.array; 3329 for (var i = 0; i < a.length; i++) { 3330 if (a[i].ocsp != undefined) a[i].ocsp = newURI; 3331 } 3332 }; 3333 3334 /** 3335 * update authorityInfoAccess caIssuer in parameter<br/> 3336 * @name updateAIACAIssuer 3337 * @memberOf X509# 3338 * @function 3339 * @param {Array} aExt array of extension parameters 3340 * @param {String} newURI string of new uri 3341 * @since jsrsasign 10.0.4 x509 2.0.8 3342 * @see X509#findExt 3343 * @see KJUR.asn1.x509.AuthorityInfoAccess 3344 * 3345 * @description 3346 * This method updates "caIssuer" accessMethod URI of 3347 * AuthorityInfoAccess extension 3348 * in the extension parameter array if it exists. 3349 * 3350 * @example 3351 * aExt = [ 3352 * {extname:"authorityKeyIdentifier",kid:{hex:"12ab..."}}, 3353 * {extname:"authoriyInfoAccess", 3354 * array:[ 3355 * {ocsp: "http://ocsp1.example.com"}, 3356 * {caissuer: "http://example.com/a.crt"} 3357 * ]} 3358 * ]; 3359 * x = new X509(); 3360 * x.updateAIACAIssuer(aExt, "http://example.net/b.crt"); 3361 */ 3362 this.updateExtAIACAIssuer = function(aExt, newURI) { 3363 var pExt = this.findExt(aExt, "authorityInfoAccess"); 3364 if (pExt == null) return; 3365 if (pExt.array == undefined) return; 3366 var a = pExt.array; 3367 for (var i = 0; i < a.length; i++) { 3368 if (a[i].caissuer != undefined) a[i].caissuer = newURI; 3369 } 3370 }; 3371 3372 /** 3373 * convert array for X500 distinguish name to distinguish name string<br/> 3374 * @name dnarraytostr 3375 * @memberOf X509# 3376 * @function 3377 * @param {Array} aDN array for X500 distinguish name 3378 * @return {String} distinguish name 3379 * @since jsrsasign 10.0.6 x509 2.0.8 3380 * @see X509#getX500Name 3381 * @see X509#getX500NameArray 3382 * @see KJUR.asn1.x509.X500Name 3383 * 3384 * @description 3385 * This method converts from an array representation of 3386 * X.500 distinguished name to X.500 name string. 3387 * This supports multi-valued RDN. 3388 * 3389 * @example 3390 * var x = new X509(); 3391 * x.dnarraytostr( 3392 * [[{type:"C",value:"JP",ds:"prn"}], 3393 * [{type:"O",value:"T1",ds:"prn"}]]) → "/C=JP/O=T1" 3394 * x.dnarraytostr( 3395 * [[{type:"C",value:"JP",ds:"prn"}], 3396 * [{type:"O",value:"T1",ds:"prn"} 3397 * {type:"CN",value:"Bob",ds:"prn"}]]) → "/C=JP/O=T1+CN=Bob" 3398 */ 3399 this.dnarraytostr = function(aDN) { 3400 function rdnarraytostr(aRDN) { 3401 return aRDN.map(function(x){return atvtostr(x).replace(/\+/,"\\+");}).join("+"); 3402 }; 3403 3404 function atvtostr(pATV) { 3405 return pATV.type + "=" + pATV.value; 3406 }; 3407 3408 return "/" + aDN.map(function(x){return rdnarraytostr(x).replace(/\//, "\\/");}).join("/"); 3409 }; 3410 3411 /** 3412 * set canonicalized DN to a DN parameter<br/> 3413 * @name setCanonicalizedDN 3414 * @memberOf X509# 3415 * @function 3416 * @param {object} pDN DN parameter associative array 3417 * @since jsrsasign 10.6.0 x509 2.1.0 3418 * 3419 * @description 3420 * This method canonicalizes a DN string as following: 3421 * <ul> 3422 * <li>convert to lower case</li> 3423 * <li>convert from all multiple spaces to a space</li> 3424 * </ul> 3425 * 3426 * @example 3427 * var x = new X509(); 3428 * var pDN = { 3429 * array: [ 3430 * [{type:'C',value:'JP',ds:'prn'}], 3431 * [{type:'O',value:'Test 1',ds:'prn'}] ], 3432 * str: "/C=JP/O=Test 1" }; 3433 * x.setCanonicalizedDN(pDN); 3434 3435 * // pDN will become following 3436 * pDN = { 3437 * array: [ 3438 * [{type:'C',value:'JP',ds:'prn'}], 3439 * [{type:'O',value:'Test 1',ds:'prn'}] ], 3440 * str: "/C=JP/O=Test 1", 3441 * canon: "/c=jp/o=test 1" }; 3442 */ 3443 this.setCanonicalizedDN = function(pDN) { 3444 var aRDN; 3445 if (pDN.str != undefined && pDN.array == undefined) { 3446 var dDN = new KJUR.asn1.x509.X500Name({str: pDN.str}); 3447 var hDN = dDN.tohex(); 3448 aRDN = this.getX500NameArray(hDN); 3449 } else { 3450 aRDN = pDN.array; 3451 } 3452 if (pDN.canon == undefined) { 3453 pDN.canon = this.c14nRDNArray(aRDN); 3454 } 3455 }; 3456 3457 /** 3458 * simple canonicalization(c14n) for RDN array<br/> 3459 * @name c14nRDNArray 3460 * @memberOf X509# 3461 * @function 3462 * @param {array} aRDN array of RDN parameters 3463 * @return {string} canonicalized distinguish name (ex. "/c=jp/o=test ca") 3464 * @since jsrsasign 10.6.0 x509 2.1.0 3465 * 3466 * @description 3467 * This method canonicalizes a DN string according to 3468 * <a href="https://datatracker.ietf.org/doc/html/rfc4518#appendix-B"> 3469 * "RFC 4518 StringPrep Appendix B Substring Matching"</a> as following: 3470 * <ul> 3471 * <li>convert to lower case</li> 3472 * <li>convert from all sequence of spaces to a space</li> 3473 * <li>remove leading and trailing spaces</li> 3474 * </ul> 3475 * 3476 * @example 3477 * var x = new X509(); 3478 * x.c14nRDNArray([ 3479 * [{type:"C", value:"JP", ds: "prn"}], 3480 * [{type:"O", value:" Test 1234 ", ds: "utf8"}], 3481 * [{type:"OU", value:"HR 45", ds: "utf8"}] 3482 * ]) → "/c=jp/o=test 1234/ou=hr 45" 3483 */ 3484 this.c14nRDNArray = function(aRDN) { 3485 var a = []; 3486 for (var i = 0; i < aRDN.length; i++) { 3487 var aAVA = aRDN[i]; 3488 var a2 = []; 3489 for (var j = 0; j < aAVA.length; j++) { 3490 var pAVA = aAVA[j]; 3491 var value = pAVA.value; 3492 value = value.replace(/^\s*/, ''); 3493 value = value.replace(/\s*$/, ''); 3494 value = value.replace(/\s+/g, ' '); 3495 value = value.toLowerCase(); 3496 a2.push(pAVA.type.toLowerCase() + "=" + value); 3497 } 3498 a.push(a2.join("+")); 3499 } 3500 return "/" + a.join("/"); 3501 }; 3502 3503 /** 3504 * get certificate information as string.<br/> 3505 * @name getInfo 3506 * @memberOf X509# 3507 * @function 3508 * @return {String} certificate information string 3509 * @since jsrsasign 5.0.10 x509 1.1.8 3510 * @example 3511 * x = new X509(); 3512 * x.readCertPEM(certPEM); 3513 * console.log(x.getInfo()); 3514 * // this shows as following 3515 * Basic Fields 3516 * serial number: 02ac5c266a0b409b8f0b79f2ae462577 3517 * signature algorithm: SHA1withRSA 3518 * issuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA 3519 * notBefore: 061110000000Z 3520 * notAfter: 311110000000Z 3521 * subject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA 3522 * subject public key info: 3523 * key algorithm: RSA 3524 * n=c6cce573e6fbd4bb... 3525 * e=10001 3526 * X509v3 Extensions: 3527 * keyUsage CRITICAL: 3528 * digitalSignature,keyCertSign,cRLSign 3529 * basicConstraints CRITICAL: 3530 * cA=true 3531 * subjectKeyIdentifier : 3532 * b13ec36903f8bf4701d498261a0802ef63642bc3 3533 * authorityKeyIdentifier : 3534 * kid=b13ec36903f8bf4701d498261a0802ef63642bc3 3535 * signature algorithm: SHA1withRSA 3536 * signature: 1c1a0697dcd79c9f... 3537 */ 3538 this.getInfo = function() { 3539 var _getSubjectAltNameStr = function(params) { 3540 var s = ""; 3541 var indent = " "; 3542 var NL = "\n"; 3543 var a = params.array; 3544 for (var i = 0; i < a.length; i++) { 3545 var pGN = a[i]; 3546 if (pGN.dn != undefined) s += indent + "dn: " + pGN.dn.str + NL; 3547 if (pGN.ip != undefined) s += indent + "ip: " + pGN.ip + NL; 3548 if (pGN.rfc822 != undefined) s += indent + "rfc822: " + pGN.rfc822 + NL; 3549 if (pGN.dns != undefined) s += indent + "dns: " + pGN.dns + NL; 3550 if (pGN.uri != undefined) s += indent + "uri: " + pGN.uri + NL; 3551 if (pGN.other != undefined) { 3552 var oidname = pGN.other.oid; 3553 var value = JSON.stringify(pGN.other.value).replace(/\"/g, ''); 3554 s += indent + "other: " + oidname + "=" + value + NL; 3555 } 3556 } 3557 s = s.replace(/\n$/, ''); 3558 return s; 3559 }; 3560 var _getCertificatePoliciesStr = function(params) { 3561 var s = ""; 3562 var a = params.array; 3563 for (var i = 0; i < a.length; i++) { 3564 var pi = a[i]; 3565 s += " policy oid: " + pi.policyoid + "\n"; 3566 if (pi.array === undefined) continue; 3567 for (var j = 0; j < pi.array.length; j++) { 3568 var pqi = pi.array[j]; 3569 if (pqi.cps !== undefined) { 3570 s += " cps: " + pqi.cps + "\n"; 3571 } 3572 } 3573 } 3574 return s; 3575 }; 3576 var _getCRLDistributionPointsStr = function(params) { 3577 var s = ""; 3578 var a = params.array; 3579 for (var i = 0; i < a.length; i++) { 3580 var dp = a[i]; 3581 try { 3582 if (dp.dpname.full[0].uri !== undefined) 3583 s += " " + dp.dpname.full[0].uri + "\n"; 3584 } catch(ex) {}; 3585 try { 3586 if (dp.dname.full[0].dn.hex !== undefined) 3587 s += " " + X509.hex2dn(dp.dpname.full[0].dn.hex) + "\n"; 3588 } catch(ex) {}; 3589 } 3590 return s; 3591 } 3592 var _getAuthorityInfoAccessStr = function(params) { 3593 var s = ""; 3594 var a = params.array; 3595 for (var i = 0; i < a.length; i++) { 3596 var ad = a[i]; 3597 3598 if (ad.caissuer !== undefined) 3599 s += " caissuer: " + ad.caissuer + "\n"; 3600 if (ad.ocsp !== undefined) 3601 s += " ocsp: " + ad.ocsp + "\n"; 3602 } 3603 return s; 3604 }; 3605 var _X509 = X509; 3606 var s, pubkey, aExt; 3607 s = "Basic Fields\n"; 3608 s += " serial number: " + this.getSerialNumberHex() + "\n"; 3609 s += " signature algorithm: " + this.getSignatureAlgorithmField() + "\n"; 3610 s += " issuer: " + this.getIssuerString() + "\n"; 3611 s += " notBefore: " + this.getNotBefore() + "\n"; 3612 s += " notAfter: " + this.getNotAfter() + "\n"; 3613 s += " subject: " + this.getSubjectString() + "\n"; 3614 s += " subject public key info: " + "\n"; 3615 3616 // subject public key info 3617 pubkey = this.getPublicKey(); 3618 s += " key algorithm: " + pubkey.type + "\n"; 3619 3620 if (pubkey.type === "RSA") { 3621 s += " n=" + hextoposhex(pubkey.n.toString(16)).substr(0, 16) + "...\n"; 3622 s += " e=" + hextoposhex(pubkey.e.toString(16)) + "\n"; 3623 } 3624 3625 // X.509v3 Extensions 3626 aExt = this.aExtInfo; 3627 3628 if (aExt !== undefined && aExt !== null) { 3629 s += "X509v3 Extensions:\n"; 3630 3631 for (var i = 0; i < aExt.length; i++) { 3632 var info = aExt[i]; 3633 3634 // show extension name and critical flag 3635 var extName = KJUR.asn1.x509.OID.oid2name(info["oid"]); 3636 if (extName === '') extName = info["oid"]; 3637 3638 var critical = ''; 3639 if (info["critical"] === true) critical = "CRITICAL"; 3640 3641 s += " " + extName + " " + critical + ":\n"; 3642 3643 // show extension value if supported 3644 if (extName === "basicConstraints") { 3645 var bc = this.getExtBasicConstraints(); 3646 if (bc.cA === undefined) { 3647 s += " {}\n"; 3648 } else { 3649 s += " cA=true"; 3650 if (bc.pathLen !== undefined) 3651 s += ", pathLen=" + bc.pathLen; 3652 s += "\n"; 3653 } 3654 } else if (extName == "policyMappings") { 3655 var a = this.getExtPolicyMappings().array; 3656 var sMap = a.map(function(item){ 3657 var aPolicy = item; 3658 return aPolicy[0] + ":" + aPolicy[1]; 3659 }).join(", "); 3660 s += " " + sMap + "\n"; 3661 } else if (extName == "policyConstraints") { 3662 var p = this.getExtPolicyConstraints(); 3663 s += " "; 3664 if (p.reqexp != undefined) s += " reqexp=" + p.reqexp; 3665 if (p.inhibit != undefined) s += " inhibit=" + p.inhibit; 3666 s += "\n"; 3667 } else if (extName == "inhibitAnyPolicy") { 3668 var p = this.getExtInhibitAnyPolicy(); 3669 s += " skip=" + p.skip + "\n"; 3670 } else if (extName == "keyUsage") { 3671 s += " " + this.getExtKeyUsageString() + "\n"; 3672 } else if (extName == "subjectKeyIdentifier") { 3673 s += " " + this.getExtSubjectKeyIdentifier().kid.hex + "\n"; 3674 } else if (extName == "authorityKeyIdentifier") { 3675 var akid = this.getExtAuthorityKeyIdentifier(); 3676 if (akid.kid !== undefined) 3677 s += " kid=" + akid.kid.hex + "\n"; 3678 } else if (extName == "extKeyUsage") { 3679 var eku = this.getExtExtKeyUsage().array; 3680 s += " " + eku.join(", ") + "\n"; 3681 } else if (extName == "subjectAltName") { 3682 var san = _getSubjectAltNameStr(this.getExtSubjectAltName()); 3683 s += san + "\n"; 3684 } else if (extName == "cRLDistributionPoints") { 3685 var cdp = this.getExtCRLDistributionPoints(); 3686 s += _getCRLDistributionPointsStr(cdp); 3687 } else if (extName == "authorityInfoAccess") { 3688 var aia = this.getExtAuthorityInfoAccess(); 3689 s += _getAuthorityInfoAccessStr(aia); 3690 } else if (extName == "certificatePolicies") { 3691 s += _getCertificatePoliciesStr(this.getExtCertificatePolicies()); 3692 } 3693 } 3694 } 3695 3696 s += "signature algorithm: " + this.getSignatureAlgorithmName() + "\n"; 3697 s += "signature: " + this.getSignatureValueHex().substr(0, 16) + "...\n"; 3698 return s; 3699 }; 3700 3701 if (typeof params == "string") { 3702 if (params.indexOf("-----BEGIN") != -1) { 3703 this.readCertPEM(params); 3704 } else if (KJUR.lang.String.isHex(params)) { 3705 this.readCertHex(params); 3706 } 3707 } 3708 }; 3709 // ----- END of X509 class ----- 3710 3711 /** 3712 * additional definition for X.509 extension parsers<br/> 3713 * @see X509.registExtParser 3714 */ 3715 X509.EXT_PARSER = { 3716 }; 3717 3718 /** 3719 * define X.509 extension parser for specified OID<br/> 3720 * @name registExtParser 3721 * @memberOf X509 3722 * @function 3723 * @param {string} oid extension OID string (ex. "1.2.3.4") 3724 * @param {function} func registering func extension value parsing function 3725 * @return unspecified 3726 * @since jsrsasign 10.7.0 x509 2.1.2 3727 * 3728 * @description 3729 * <p> 3730 * This static method specifies a X.509 extension value parsing function 3731 * for specified an extension OID. 3732 * </p> 3733 * <p> 3734 * Extension parser function must have following three arguments: 3735 * <ul> 3736 * <li>{string} oid - OID for extension (ex. "1.2.3.4")</li> 3737 * <li>{boolean} critical - critical flag of extension</li> 3738 * <li>{string} hExtV - hexadecimal string of extension value</li> 3739 * </ul> 3740 * The funcition must return an associative array for the extension 3741 * when hExtV can be parsed properly. Otherwise it must return 3742 * value "undefined". 3743 * </p> 3744 * 3745 * @example 3746 * function _extparser1(oid, critical, hExtV) { 3747 * try { 3748 * var result = { extname: oid, value: ASN1HEX.parse(hExtV).utf8str.str }; 3749 * if (critical) result.critical = true; 3750 * return result; 3751 * } catch(ex) { 3752 * return undefined; 3753 * } 3754 * } 3755 * X509.registExtParser("1.2.3.4", _extparser1); 3756 */ 3757 X509.registExtParser = function(oid, func) { 3758 X509.EXT_PARSER[oid] = func; 3759 }; 3760 3761 /** 3762 * get distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER X.500 name<br/> 3763 * @name hex2dn 3764 * @memberOf X509 3765 * @function 3766 * @param {String} hex hexadecimal string of ASN.1 DER distinguished name 3767 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 3768 * @return {String} OpenSSL online format distinguished name 3769 * @description 3770 * This static method converts from a hexadecimal string of 3771 * distinguished name (DN) 3772 * specified by 'hex' and 'idx' to OpenSSL oneline string representation (ex. /C=US/O=a). 3773 * @example 3774 * X509.hex2dn("3031310b3...") → /C=US/O=a/CN=b2+OU=b1 3775 */ 3776 X509.hex2dn = function(hex, idx) { 3777 if (idx === undefined) idx = 0; 3778 var x = new X509(); 3779 var hDN = ASN1HEX.getTLV(hex, idx); 3780 var pDN = x.getX500Name(hex); 3781 return pDN.str; 3782 }; 3783 3784 /** 3785 * get relative distinguished name string in OpenSSL online format from hexadecimal string of ASN.1 DER RDN<br/> 3786 * @name hex2rdn 3787 * @memberOf X509 3788 * @function 3789 * @param {String} hex hexadecimal string of ASN.1 DER concludes relative distinguished name 3790 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 3791 * @return {String} OpenSSL online format relative distinguished name 3792 * @description 3793 * This static method converts from a hexadecimal string of 3794 * relative distinguished name (RDN) 3795 * specified by 'hex' and 'idx' to LDAP string representation (ex. O=test+CN=test).<br/> 3796 * NOTE: Multi-valued RDN is supported since jsnrsasign 6.2.2 x509 1.1.10. 3797 * @example 3798 * X509.hex2rdn("310a3008060355040a0c0161") → O=a 3799 * X509.hex2rdn("31143008060355040a0c01613008060355040a0c0162") → O=a+O=b 3800 */ 3801 X509.hex2rdn = function(hex, idx) { 3802 if (idx === undefined) idx = 0; 3803 if (hex.substr(idx, 2) !== "31") throw new Error("malformed RDN"); 3804 3805 var a = new Array(); 3806 3807 var aIdx = ASN1HEX.getChildIdx(hex, idx); 3808 for (var i = 0; i < aIdx.length; i++) { 3809 a.push(X509.hex2attrTypeValue(hex, aIdx[i])); 3810 } 3811 3812 a = a.map(function(s) { return s.replace("+", "\\+"); }); 3813 return a.join("+"); 3814 }; 3815 3816 /** 3817 * get string from hexadecimal string of ASN.1 DER AttributeTypeAndValue<br/> 3818 * @name hex2attrTypeValue 3819 * @memberOf X509 3820 * @function 3821 * @param {String} hex hexadecimal string of ASN.1 DER concludes AttributeTypeAndValue 3822 * @param {Integer} idx index of hexadecimal string (DEFAULT=0) 3823 * @return {String} string representation of AttributeTypeAndValue (ex. C=US) 3824 * @description 3825 * This static method converts from a hexadecimal string of AttributeTypeAndValue 3826 * specified by 'hex' and 'idx' to LDAP string representation (ex. C=US). 3827 * @example 3828 * X509.hex2attrTypeValue("3008060355040a0c0161") → O=a 3829 * X509.hex2attrTypeValue("300806035504060c0161") → C=a 3830 * X509.hex2attrTypeValue("...3008060355040a0c0161...", 128) → O=a 3831 */ 3832 X509.hex2attrTypeValue = function(hex, idx) { 3833 var _ASN1HEX = ASN1HEX; 3834 var _getV = _ASN1HEX.getV; 3835 3836 if (idx === undefined) idx = 0; 3837 if (hex.substr(idx, 2) !== "30") 3838 throw new Error("malformed attribute type and value"); 3839 3840 var aIdx = _ASN1HEX.getChildIdx(hex, idx); 3841 if (aIdx.length !== 2 || hex.substr(aIdx[0], 2) !== "06") 3842 "malformed attribute type and value"; 3843 3844 var oidHex = _getV(hex, aIdx[0]); 3845 var oidInt = KJUR.asn1.ASN1Util.oidHexToInt(oidHex); 3846 var atype = KJUR.asn1.x509.OID.oid2atype(oidInt); 3847 3848 var hV = _getV(hex, aIdx[1]); 3849 var rawV = hextorstr(hV); 3850 3851 return atype + "=" + rawV; 3852 }; 3853 3854 /** 3855 * get RSA/DSA/ECDSA public key object from X.509 certificate hexadecimal string<br/> 3856 * @name getPublicKeyFromCertHex 3857 * @memberOf X509 3858 * @function 3859 * @param {String} h hexadecimal string of X.509 certificate for RSA/ECDSA/DSA public key 3860 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key 3861 * @since jsrasign 7.1.0 x509 1.1.11 3862 */ 3863 X509.getPublicKeyFromCertHex = function(h) { 3864 var x = new X509(); 3865 x.readCertHex(h); 3866 return x.getPublicKey(); 3867 }; 3868 3869 /** 3870 * get RSA/DSA/ECDSA public key object from PEM certificate string 3871 * @name getPublicKeyFromCertPEM 3872 * @memberOf X509 3873 * @function 3874 * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate 3875 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key 3876 * @since x509 1.1.1 3877 * @description 3878 * NOTE: DSA is also supported since x509 1.1.2. 3879 */ 3880 X509.getPublicKeyFromCertPEM = function(sCertPEM) { 3881 var x = new X509(); 3882 x.readCertPEM(sCertPEM); 3883 return x.getPublicKey(); 3884 }; 3885 3886 /** 3887 * get public key information from PEM certificate 3888 * @name getPublicKeyInfoPropOfCertPEM 3889 * @memberOf X509 3890 * @function 3891 * @param {String} sCertPEM string of PEM formatted certificate 3892 * @return {Hash} hash of information for public key 3893 * @since x509 1.1.1 3894 * @description 3895 * Resulted associative array has following properties:<br/> 3896 * <ul> 3897 * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li> 3898 * <li>algparam - hexadecimal string of OID of ECC curve name or null</li> 3899 * <li>keyhex - hexadecimal string of key in the certificate</li> 3900 * </ul> 3901 * NOTE: X509v1 certificate is also supported since x509.js 1.1.9. 3902 */ 3903 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) { 3904 var _ASN1HEX = ASN1HEX; 3905 var _getVbyList = _ASN1HEX.getVbyList; 3906 3907 var result = {}; 3908 var x, hSPKI, pubkey; 3909 result.algparam = null; 3910 3911 x = new X509(); 3912 x.readCertPEM(sCertPEM); 3913 3914 hSPKI = x.getPublicKeyHex(); 3915 result.keyhex = _getVbyList(hSPKI, 0, [1], "03").substr(2); 3916 result.algoid = _getVbyList(hSPKI, 0, [0, 0], "06"); 3917 3918 if (result.algoid === "2a8648ce3d0201") { // ecPublicKey 3919 result.algparam = _getVbyList(hSPKI, 0, [0, 1], "06"); 3920 }; 3921 3922 return result; 3923 }; 3924 3925 /* ====================================================================== 3926 * Specific V3 Extensions 3927 * ====================================================================== */ 3928 3929 X509.KEYUSAGE_NAME = [ 3930 "digitalSignature", 3931 "nonRepudiation", 3932 "keyEncipherment", 3933 "dataEncipherment", 3934 "keyAgreement", 3935 "keyCertSign", 3936 "cRLSign", 3937 "encipherOnly", 3938 "decipherOnly" 3939 ]; 3940