1 /*! x509-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * x509.js - X509 class to read subject public key from certificate. 5 * 6 * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * http://kjur.github.com/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 x509 1.1.6 (2015-May-20) 20 * @since jsrsasign 1.x.x 21 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a> 22 */ 23 24 /* 25 * Depends: 26 * base64.js 27 * rsa.js 28 * asn1hex.js 29 */ 30 31 /** 32 * X.509 certificate class.<br/> 33 * @class X.509 certificate class 34 * @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object 35 * @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key 36 * @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key 37 * @property {String} hex hexacedimal string for X.509 certificate. 38 * @author Kenji Urushima 39 * @version 1.0.1 (08 May 2012) 40 * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a> 41 */ 42 function X509() { 43 this.subjectPublicKeyRSA = null; 44 this.subjectPublicKeyRSA_hN = null; 45 this.subjectPublicKeyRSA_hE = null; 46 this.hex = null; 47 48 // ===== get basic fields from hex ===================================== 49 50 /** 51 * get hexadecimal string of serialNumber field of certificate.<br/> 52 * @name getSerialNumberHex 53 * @memberOf X509# 54 * @function 55 */ 56 this.getSerialNumberHex = function() { 57 return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]); 58 }; 59 60 /** 61 * get hexadecimal string of issuer field TLV of certificate.<br/> 62 * @name getIssuerHex 63 * @memberOf X509# 64 * @function 65 */ 66 this.getIssuerHex = function() { 67 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]); 68 }; 69 70 /** 71 * get string of issuer field of certificate.<br/> 72 * @name getIssuerString 73 * @memberOf X509# 74 * @function 75 */ 76 this.getIssuerString = function() { 77 return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3])); 78 }; 79 80 /** 81 * get hexadecimal string of subject field of certificate.<br/> 82 * @name getSubjectHex 83 * @memberOf X509# 84 * @function 85 */ 86 this.getSubjectHex = function() { 87 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]); 88 }; 89 90 /** 91 * get string of subject field of certificate.<br/> 92 * @name getSubjectString 93 * @memberOf X509# 94 * @function 95 */ 96 this.getSubjectString = function() { 97 return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5])); 98 }; 99 100 /** 101 * get notBefore field string of certificate.<br/> 102 * @name getNotBefore 103 * @memberOf X509# 104 * @function 105 */ 106 this.getNotBefore = function() { 107 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]); 108 s = s.replace(/(..)/g, "%$1"); 109 s = decodeURIComponent(s); 110 return s; 111 }; 112 113 /** 114 * get notAfter field string of certificate.<br/> 115 * @name getNotAfter 116 * @memberOf X509# 117 * @function 118 */ 119 this.getNotAfter = function() { 120 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]); 121 s = s.replace(/(..)/g, "%$1"); 122 s = decodeURIComponent(s); 123 return s; 124 }; 125 126 // ===== read certificate public key ========================== 127 128 // ===== read certificate ===================================== 129 /** 130 * read PEM formatted X.509 certificate from string.<br/> 131 * @name readCertPEM 132 * @memberOf X509# 133 * @function 134 * @param {String} sCertPEM string for PEM formatted X.509 certificate 135 */ 136 this.readCertPEM = function(sCertPEM) { 137 var hCert = X509.pemToHex(sCertPEM); 138 var a = X509.getPublicKeyHexArrayFromCertHex(hCert); 139 var rsa = new RSAKey(); 140 rsa.setPublic(a[0], a[1]); 141 this.subjectPublicKeyRSA = rsa; 142 this.subjectPublicKeyRSA_hN = a[0]; 143 this.subjectPublicKeyRSA_hE = a[1]; 144 this.hex = hCert; 145 }; 146 147 this.readCertPEMWithoutRSAInit = function(sCertPEM) { 148 var hCert = X509.pemToHex(sCertPEM); 149 var a = X509.getPublicKeyHexArrayFromCertHex(hCert); 150 this.subjectPublicKeyRSA.setPublic(a[0], a[1]); 151 this.subjectPublicKeyRSA_hN = a[0]; 152 this.subjectPublicKeyRSA_hE = a[1]; 153 this.hex = hCert; 154 }; 155 }; 156 157 X509.pemToBase64 = function(sCertPEM) { 158 var s = sCertPEM; 159 s = s.replace("-----BEGIN CERTIFICATE-----", ""); 160 s = s.replace("-----END CERTIFICATE-----", ""); 161 s = s.replace(/[ \n]+/g, ""); 162 return s; 163 }; 164 165 X509.pemToHex = function(sCertPEM) { 166 var b64Cert = X509.pemToBase64(sCertPEM); 167 var hCert = b64tohex(b64Cert); 168 return hCert; 169 }; 170 171 // NOTE: Without BITSTRING encapsulation. 172 X509.getSubjectPublicKeyPosFromCertHex = function(hCert) { 173 var pInfo = X509.getSubjectPublicKeyInfoPosFromCertHex(hCert); 174 if (pInfo == -1) return -1; 175 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 176 if (a.length != 2) return -1; 177 var pBitString = a[1]; 178 if (hCert.substring(pBitString, pBitString + 2) != '03') return -1; 179 var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString); 180 181 if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1; 182 return pBitStringV + 2; 183 }; 184 185 // NOTE: privateKeyUsagePeriod field of X509v2 not supported. 186 // NOTE: v1 and v3 supported 187 X509.getSubjectPublicKeyInfoPosFromCertHex = function(hCert) { 188 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0); 189 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 190 if (a.length < 1) return -1; 191 if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3 192 if (a.length < 6) return -1; 193 return a[6]; 194 } else { 195 if (a.length < 5) return -1; 196 return a[5]; 197 } 198 }; 199 200 X509.getPublicKeyHexArrayFromCertHex = function(hCert) { 201 var p = X509.getSubjectPublicKeyPosFromCertHex(hCert); 202 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 203 if (a.length != 2) return []; 204 var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]); 205 var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]); 206 if (hN != null && hE != null) { 207 return [hN, hE]; 208 } else { 209 return []; 210 } 211 }; 212 213 X509.getHexTbsCertificateFromCert = function(hCert) { 214 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0); 215 return pTbsCert; 216 }; 217 218 X509.getPublicKeyHexArrayFromCertPEM = function(sCertPEM) { 219 var hCert = X509.pemToHex(sCertPEM); 220 var a = X509.getPublicKeyHexArrayFromCertHex(hCert); 221 return a; 222 }; 223 224 X509.hex2dn = function(hDN) { 225 var s = ""; 226 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0); 227 for (var i = 0; i < a.length; i++) { 228 var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]); 229 s = s + "/" + X509.hex2rdn(hRDN); 230 } 231 return s; 232 }; 233 234 X509.hex2rdn = function(hRDN) { 235 var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]); 236 var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]); 237 var type = ""; 238 try { type = X509.DN_ATTRHEX[hType]; } catch (ex) { type = hType; } 239 hValue = hValue.replace(/(..)/g, "%$1"); 240 var value = decodeURIComponent(hValue); 241 return type + "=" + value; 242 }; 243 244 X509.DN_ATTRHEX = { 245 "0603550406": "C", 246 "060355040a": "O", 247 "060355040b": "OU", 248 "0603550403": "CN", 249 "0603550405": "SN", 250 "0603550408": "ST", 251 "0603550407": "L", 252 }; 253 254 /** 255 * get RSAKey/ECDSA public key object from PEM certificate string 256 * @name getPublicKeyFromCertPEM 257 * @memberOf X509 258 * @function 259 * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate 260 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key 261 * @since x509 1.1.1 262 * @description 263 * NOTE: DSA is also supported since x509 1.1.2. 264 */ 265 X509.getPublicKeyFromCertPEM = function(sCertPEM) { 266 var info = X509.getPublicKeyInfoPropOfCertPEM(sCertPEM); 267 268 if (info.algoid == "2a864886f70d010101") { // RSA 269 var aRSA = KEYUTIL.parsePublicRawRSAKeyHex(info.keyhex); 270 var key = new RSAKey(); 271 key.setPublic(aRSA.n, aRSA.e); 272 return key; 273 } else if (info.algoid == "2a8648ce3d0201") { // ECC 274 var curveName = KJUR.crypto.OID.oidhex2name[info.algparam]; 275 var key = new KJUR.crypto.ECDSA({'curve': curveName, 'info': info.keyhex}); 276 key.setPublicKeyHex(info.keyhex); 277 return key; 278 } else if (info.algoid == "2a8648ce380401") { // DSA 1.2.840.10040.4.1 279 var p = ASN1HEX.getVbyList(info.algparam, 0, [0], "02"); 280 var q = ASN1HEX.getVbyList(info.algparam, 0, [1], "02"); 281 var g = ASN1HEX.getVbyList(info.algparam, 0, [2], "02"); 282 var y = ASN1HEX.getHexOfV_AtObj(info.keyhex, 0); 283 y = y.substr(2); 284 var key = new KJUR.crypto.DSA(); 285 key.setPublic(new BigInteger(p, 16), 286 new BigInteger(q, 16), 287 new BigInteger(g, 16), 288 new BigInteger(y, 16)); 289 return key; 290 } else { 291 throw "unsupported key"; 292 } 293 }; 294 295 /** 296 * get public key information from PEM certificate 297 * @name getPublicKeyInfoPropOfCertPEM 298 * @memberOf X509 299 * @function 300 * @param {String} sCertPEM string of PEM formatted certificate 301 * @return {Hash} hash of information for public key 302 * @since x509 1.1.1 303 * @description 304 * Resulted associative array has following properties: 305 * <ul> 306 * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li> 307 * <li>algparam - hexadecimal string of OID of ECC curve name or null</li> 308 * <li>keyhex - hexadecimal string of key in the certificate</li> 309 * </ul> 310 * @since x509 1.1.1 311 */ 312 X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) { 313 var result = {}; 314 result.algparam = null; 315 var hCert = X509.pemToHex(sCertPEM); 316 317 // 1. Certificate ASN.1 318 var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 319 if (a1.length != 3) 320 throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert 321 322 // 2. tbsCertificate 323 if (hCert.substr(a1[0], 2) != "30") 324 throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 325 326 var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 327 328 // 3. subjectPublicKeyInfo 329 if (a2.length < 7) 330 throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo 331 332 var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[6]); 333 334 if (a3.length != 2) 335 throw "malformed X.509 certificate PEM (code:004)"; // not AlgId and PubKey 336 337 // 4. AlgId 338 var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]); 339 340 if (a4.length != 2) 341 throw "malformed X.509 certificate PEM (code:005)"; // not 2 item in AlgId 342 343 result.algoid = ASN1HEX.getHexOfV_AtObj(hCert, a4[0]); 344 345 if (hCert.substr(a4[1], 2) == "06") { // EC 346 result.algparam = ASN1HEX.getHexOfV_AtObj(hCert, a4[1]); 347 } else if (hCert.substr(a4[1], 2) == "30") { // DSA 348 result.algparam = ASN1HEX.getHexOfTLV_AtObj(hCert, a4[1]); 349 } 350 351 // 5. Public Key Hex 352 if (hCert.substr(a3[1], 2) != "03") 353 throw "malformed X.509 certificate PEM (code:006)"; // not bitstring 354 355 var unusedBitAndKeyHex = ASN1HEX.getHexOfV_AtObj(hCert, a3[1]); 356 result.keyhex = unusedBitAndKeyHex.substr(2); 357 358 return result; 359 }; 360 361 /** 362 * get position of subjectPublicKeyInfo field from HEX certificate 363 * @name getPublicKeyInfoPosOfCertHEX 364 * @memberOf X509 365 * @function 366 * @param {String} hCert hexadecimal string of certificate 367 * @return {Integer} position in hexadecimal string 368 * @since x509 1.1.4 369 * @description 370 * get position for SubjectPublicKeyInfo field in the hexadecimal string of 371 * certificate. 372 */ 373 X509.getPublicKeyInfoPosOfCertHEX = function(hCert) { 374 // 1. Certificate ASN.1 375 var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 376 if (a1.length != 3) 377 throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert 378 379 // 2. tbsCertificate 380 if (hCert.substr(a1[0], 2) != "30") 381 throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 382 383 var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 384 385 // 3. subjectPublicKeyInfo 386 if (a2.length < 7) 387 throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo 388 389 return a2[6]; 390 }; 391 392 /** 393 * get array of X.509 V3 extension value information in hex string of certificate 394 * @name getV3ExtInfoListOfCertHex 395 * @memberOf X509 396 * @function 397 * @param {String} hCert hexadecimal string of X.509 certificate binary 398 * @return {Array} array of result object by {@link X509.getV3ExtInfoListOfCertHex} 399 * @since x509 1.1.5 400 * @description 401 * This method will get all extension information of a X.509 certificate. 402 * Items of resulting array has following properties: 403 * <ul> 404 * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li> 405 * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li> 406 * <li>critical - critical flag value for this extension</li> 407 * <li>posV - index of ASN.1 TLV for the extension value. 408 * This is a position of a content of ENCAPSULATED OCTET STRING.</li> 409 * </ul> 410 * @example 411 * hCert = X509.pemToHex(certGithubPEM); 412 * a = X509.getV3ExtInfoListOfCertHex(hCert); 413 * // Then a will be an array of like following: 414 * [{posTLV: 1952, oid: "2.5.29.35", critical: false, posV: 1968}, 415 * {posTLV: 1974, oid: "2.5.29.19", critical: true, posV: 1986}, ...] 416 */ 417 X509.getV3ExtInfoListOfCertHex = function(hCert) { 418 // 1. Certificate ASN.1 419 var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 420 if (a1.length != 3) 421 throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert 422 423 // 2. tbsCertificate 424 if (hCert.substr(a1[0], 2) != "30") 425 throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 426 427 var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 428 429 // 3. v3Extension EXPLICIT Tag [3] 430 // ver, seri, alg, iss, validity, subj, spki, (iui,) (sui,) ext 431 if (a2.length < 8) 432 throw "malformed X.509 certificate PEM (code:003)"; // tbsCert num field too short 433 434 if (hCert.substr(a2[7], 2) != "a3") 435 throw "malformed X.509 certificate PEM (code:004)"; // not [3] tag 436 437 var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[7]); 438 if (a3.length != 1) 439 throw "malformed X.509 certificate PEM (code:005)"; // [3]tag numChild!=1 440 441 // 4. v3Extension SEQUENCE 442 if (hCert.substr(a3[0], 2) != "30") 443 throw "malformed X.509 certificate PEM (code:006)"; // not SEQ 444 445 var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]); 446 447 // 5. v3Extension item position 448 var numExt = a4.length; 449 var aInfo = new Array(numExt); 450 for (var i = 0; i < numExt; i++) { 451 aInfo[i] = X509.getV3ExtItemInfo_AtObj(hCert, a4[i]); 452 } 453 return aInfo; 454 }; 455 456 /** 457 * get X.509 V3 extension value information at the specified position 458 * @name getV3ExtItemInfo_AtObj 459 * @memberOf X509 460 * @function 461 * @param {String} hCert hexadecimal string of X.509 certificate binary 462 * @param {Integer} pos index of hexadecimal string for the extension 463 * @return {Object} properties for the extension 464 * @since x509 1.1.5 465 * @description 466 * This method will get some information of a X.509 V extension 467 * which is referred by an index of hexadecimal string of X.509 468 * certificate. 469 * Resulting object has following properties: 470 * <ul> 471 * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li> 472 * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li> 473 * <li>critical - critical flag value for this extension</li> 474 * <li>posV - index of ASN.1 TLV for the extension value. 475 * This is a position of a content of ENCAPSULATED OCTET STRING.</li> 476 * </ul> 477 * This method is used by {@link X509.getV3ExtInfoListOfCertHex} internally. 478 */ 479 X509.getV3ExtItemInfo_AtObj = function(hCert, pos) { 480 var info = {}; 481 482 // posTLV - extension TLV 483 info.posTLV = pos; 484 485 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos); 486 if (a.length != 2 && a.length != 3) 487 throw "malformed X.509v3 Ext (code:001)"; // oid,(critical,)val 488 489 // oid - extension OID 490 if (hCert.substr(a[0], 2) != "06") 491 throw "malformed X.509v3 Ext (code:002)"; // not OID "06" 492 var valueHex = ASN1HEX.getHexOfV_AtObj(hCert, a[0]); 493 info.oid = ASN1HEX.hextooidstr(valueHex); 494 495 // critical - extension critical flag 496 info.critical = false; // critical false by default 497 if (a.length == 3) info.critical = true; 498 499 // posV - content TLV position of encapsulated 500 // octet string of V3 extension value. 501 var posExtV = a[a.length - 1]; 502 if (hCert.substr(posExtV, 2) != "04") 503 throw "malformed X.509v3 Ext (code:003)"; // not EncapOctet "04" 504 info.posV = ASN1HEX.getStartPosOfV_AtObj(hCert, posExtV); 505 506 return info; 507 }; 508 509 /** 510 * get X.509 V3 extension value ASN.1 TLV for specified oid or name 511 * @name getHexOfTLV_V3ExtValue 512 * @memberOf X509 513 * @function 514 * @param {String} hCert hexadecimal string of X.509 certificate binary 515 * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15') 516 * @return {String} hexadecimal string of extension ASN.1 TLV 517 * @since x509 1.1.6 518 * @description 519 * This method will get X.509v3 extension value of ASN.1 TLV 520 * which is specifyed by extension name or oid. 521 * @example 522 * hExtValue = X509.getHexOfTLV_V3ExtValue(hCert, "keyUsage"); 523 * // hExtValue will be such like '030205a0'. 524 */ 525 X509.getHexOfTLV_V3ExtValue = function(hCert, oidOrName) { 526 var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName); 527 if (pos == -1) return ''; 528 return ASN1HEX.getHexOfTLV_AtObj(hCert, pos); 529 }; 530 531 /** 532 * get X.509 V3 extension value ASN.1 V for specified oid or name 533 * @name getHexOfV_V3ExtValue 534 * @memberOf X509 535 * @function 536 * @param {String} hCert hexadecimal string of X.509 certificate binary 537 * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15') 538 * @return {String} hexadecimal string of extension ASN.1 TLV 539 * @since x509 1.1.6 540 * @description 541 * This method will get X.509v3 extension value of ASN.1 value 542 * which is specifyed by extension name or oid. 543 * If there is no such extension in the certificate, 544 * it returns empty string (i.e. ''). 545 * Available extension names and oids are defined 546 * in the {@link KJUR.asn1.x509.OID} class. 547 * @example 548 * hExtValue = X509.getHexOfV_V3ExtValue(hCert, "keyUsage"); 549 * // hExtValue will be such like '05a0'. 550 */ 551 X509.getHexOfV_V3ExtValue = function(hCert, oidOrName) { 552 var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName); 553 if (pos == -1) return ''; 554 return ASN1HEX.getHexOfV_AtObj(hCert, pos); 555 }; 556 557 /** 558 * get index in the certificate hexa string for specified oid or name specified extension 559 * @name getPosOfTLV_V3ExtValue 560 * @memberOf X509 561 * @function 562 * @param {String} hCert hexadecimal string of X.509 certificate binary 563 * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15') 564 * @return {Integer} index in the hexadecimal string of certficate for specified extension 565 * @since x509 1.1.6 566 * @description 567 * This method will get X.509v3 extension value of ASN.1 V(value) 568 * which is specifyed by extension name or oid. 569 * If there is no such extension in the certificate, 570 * it returns empty string (i.e. ''). 571 * Available extension names and oids are defined 572 * in the {@link KJUR.asn1.x509.OID} class. 573 * @example 574 * idx = X509.getPosOfV_V3ExtValue(hCert, "keyUsage"); 575 * // The 'idx' will be index in the string for keyUsage value ASN.1 TLV. 576 */ 577 X509.getPosOfTLV_V3ExtValue = function(hCert, oidOrName) { 578 var oid = oidOrName; 579 if (! oidOrName.match(/^[0-9.]+$/)) oid = KJUR.asn1.x509.OID.name2oid(oidOrName); 580 if (oid == '') return -1; 581 582 var infoList = X509.getV3ExtInfoListOfCertHex(hCert); 583 for (var i = 0; i < infoList.length; i++) { 584 var info = infoList[i]; 585 if (info.oid == oid) return info.posV; 586 } 587 return -1; 588 }; 589 590 X509.KEYUSAGE_NAME = [ 591 "digitalSignature", 592 "nonRepudiation", 593 "keyEncipherment", 594 "dataEncipherment", 595 "keyAgreement", 596 "keyCertSign", 597 "cRLSign", 598 "encipherOnly", 599 "decipherOnly" 600 ]; 601 602 /** 603 * get KeyUsage extension value as binary string in the certificate 604 * @name getExtKeyUsageBin 605 * @memberOf X509 606 * @function 607 * @param {String} hCert hexadecimal string of X.509 certificate binary 608 * @return {String} binary string of key usage bits (ex. '101') 609 * @since x509 1.1.6 610 * @description 611 * This method will get key usage extension value 612 * as binary string such like '101'. 613 * Key usage bits definition is in the RFC 5280. 614 * If there is no key usage extension in the certificate, 615 * it returns empty string (i.e. ''). 616 * @example 617 * bKeyUsage = X509.getExtKeyUsageBin(hCert); 618 * // bKeyUsage will be such like '101'. 619 * // 1 - digitalSignature 620 * // 0 - nonRepudiation 621 * // 1 - keyEncipherment 622 */ 623 X509.getExtKeyUsageBin = function(hCert) { 624 var hKeyUsage = X509.getHexOfV_V3ExtValue(hCert, "keyUsage"); 625 if (hKeyUsage == '') return ''; 626 if (hKeyUsage.length % 2 != 0 || hKeyUsage.length <= 2) 627 throw "malformed key usage value"; 628 var unusedBits = parseInt(hKeyUsage.substr(0, 2)); 629 var bKeyUsage = parseInt(hKeyUsage.substr(2), 16).toString(2); 630 return bKeyUsage.substr(0, bKeyUsage.length - unusedBits); 631 }; 632 633 /** 634 * get KeyUsage extension value as names in the certificate 635 * @name getExtKeyUsageString 636 * @memberOf X509 637 * @function 638 * @param {String} hCert hexadecimal string of X.509 certificate binary 639 * @return {String} comma separated string of key usage 640 * @since x509 1.1.6 641 * @description 642 * This method will get key usage extension value 643 * as comma separated string of usage names. 644 * If there is no key usage extension in the certificate, 645 * it returns empty string (i.e. ''). 646 * @example 647 * sKeyUsage = X509.getExtKeyUsageString(hCert); 648 * // sKeyUsage will be such like 'digitalSignature,keyEncipherment'. 649 */ 650 X509.getExtKeyUsageString = function(hCert) { 651 var bKeyUsage = X509.getExtKeyUsageBin(hCert); 652 var a = new Array(); 653 for (var i = 0; i < bKeyUsage.length; i++) { 654 if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]); 655 } 656 return a.join(","); 657 }; 658 659 /** 660 * get AuthorityInfoAccess extension value in the certificate as associative array 661 * @name getExtAIAInfo 662 * @memberOf X509 663 * @function 664 * @param {String} hCert hexadecimal string of X.509 certificate binary 665 * @return {Object} associative array of AIA extension properties 666 * @since x509 1.1.6 667 * @description 668 * This method will get authority info access value 669 * as associate array which has following properties: 670 * <ul> 671 * <li>ocsp - array of string for OCSP responder URL</li> 672 * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li> 673 * </ul> 674 * If there is no key usage extension in the certificate, 675 * it returns null; 676 * @example 677 * oAIA = X509.getExtAIAInfo(hCert); 678 * // result will be such like: 679 * // oAIA.ocsp = ["http://ocsp.foo.com"]; 680 * // oAIA.caissuer = ["http://rep.foo.com/aaa.p8m"]; 681 */ 682 X509.getExtAIAInfo = function(hCert) { 683 var result = {}; 684 result.ocsp = []; 685 result.caissuer = []; 686 var pos1 = X509.getPosOfTLV_V3ExtValue(hCert, "authorityInfoAccess"); 687 if (pos1 == -1) return null; 688 if (hCert.substr(pos1, 2) != "30") // extnValue SEQUENCE 689 throw "malformed AIA Extn Value"; 690 691 var posAccDescList = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos1); 692 for (var i = 0; i < posAccDescList.length; i++) { 693 var p = posAccDescList[i]; 694 var posAccDescChild = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 695 if (posAccDescChild.length != 2) 696 throw "malformed AccessDescription of AIA Extn"; 697 var pOID = posAccDescChild[0]; 698 var pName = posAccDescChild[1]; 699 if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073001") { 700 if (hCert.substr(pName, 2) == "86") { 701 result.ocsp.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName))); 702 } 703 } 704 if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073002") { 705 if (hCert.substr(pName, 2) == "86") { 706 result.caissuer.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName))); 707 } 708 } 709 } 710 return result; 711 }; 712 713 /* 714 X509.prototype.readCertPEM = _x509_readCertPEM; 715 X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit; 716 X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex; 717 X509.prototype.getIssuerHex = _x509_getIssuerHex; 718 X509.prototype.getSubjectHex = _x509_getSubjectHex; 719 X509.prototype.getIssuerString = _x509_getIssuerString; 720 X509.prototype.getSubjectString = _x509_getSubjectString; 721 X509.prototype.getNotBefore = _x509_getNotBefore; 722 X509.prototype.getNotAfter = _x509_getNotAfter; 723 */ 724