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