1 /* asn1hex-1.2.6.js (c) 2012-2020 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * asn1hex.js - Hexadecimal represented ASN.1 string library 5 * 6 * Copyright (c) 2010-2020 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * https://kjur.github.io/jsrsasign/license/ 10 * 11 * The above copyright and license notice shall be 12 * included in all copies or substantial portions of the Software. 13 */ 14 15 /** 16 * @fileOverview 17 * @name asn1hex-1.1.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version jsrsasign 9.1.6 asn1hex 1.2.6 (2020-Sep-04) 20 * @license <a href="https://kjur.github.io/jsrsasign/license/">MIT License</a> 21 */ 22 23 /* 24 * MEMO: 25 * f('3082025b02...', 2) ... 82025b ... 3bytes 26 * f('020100', 2) ... 01 ... 1byte 27 * f('0203001...', 2) ... 03 ... 1byte 28 * f('02818003...', 2) ... 8180 ... 2bytes 29 * f('3080....0000', 2) ... 80 ... -1 30 * 31 * Requirements: 32 * - ASN.1 type octet length MUST be 1. 33 * (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...) 34 */ 35 36 /** 37 * ASN.1 DER encoded hexadecimal string utility class 38 * @name ASN1HEX 39 * @class ASN.1 DER encoded hexadecimal string utility class 40 * @since jsrsasign 1.1 41 * @description 42 * This class provides a parser for hexadecimal string of 43 * DER encoded ASN.1 binary data. 44 * Here are major methods of this class. 45 * <ul> 46 * <li><b>ACCESS BY POSITION</b> 47 * <ul> 48 * <li>{@link ASN1HEX.getTLV} - get ASN.1 TLV at specified position</li> 49 * <li>{@link ASN1HEX.getTLVblen} - get byte length of ASN.1 TLV at specified position</li> 50 * <li>{@link ASN1HEX.getV} - get ASN.1 V at specified position</li> 51 * <li>{@link ASN1HEX.getVblen} - get integer ASN.1 L at specified position</li> 52 * <li>{@link ASN1HEX.getVidx} - get ASN.1 V position from its ASN.1 TLV position</li> 53 * <li>{@link ASN1HEX.getL} - get hexadecimal ASN.1 L at specified position</li> 54 * <li>{@link ASN1HEX.getLblen} - get byte length for ASN.1 L(length) bytes</li> 55 * </ul> 56 * </li> 57 * <li><b>ACCESS FOR CHILD ITEM</b> 58 * <ul> 59 * <li>{@link ASN1HEX.getNthChildIdx} - get nth child index at specified position</li> 60 * <li>{@link ASN1HEX.getChildIdx} - get indexes of children</li> 61 * <li>{@link ASN1HEX.getNextSiblingIdx} - get position of next sibling (DEPRECATED)</li> 62 * </ul> 63 * </li> 64 * <li><b>ACCESS NESTED ASN.1 STRUCTURE</b> 65 * <ul> 66 * <li>{@link ASN1HEX.getTLVbyList} - get ASN.1 TLV at specified list index</li> 67 * <li>{@link ASN1HEX.getVbyList} - get ASN.1 V at specified nth list index with checking expected tag</li> 68 * <li>{@link ASN1HEX.getIdxbyList} - get index at specified list index</li> 69 * </ul> 70 * </li> 71 * <li><b>(NEW)ACCESS NESTED ASN.1 STRUCTURE</b> 72 * <ul> 73 * <li>{@link ASN1HEX.getTLVbyListEx} - get ASN.1 TLV at specified list index</li> 74 * <li>{@link ASN1HEX.getVbyListEx} - get ASN.1 V at specified nth list index with checking expected tag</li> 75 * <li>{@link ASN1HEX.getIdxbyListEx} - get index at specified list index</li> 76 * </ul> 77 * </li> 78 * <li><b>UTILITIES</b> 79 * <ul> 80 * <li>{@link ASN1HEX.dump} - dump ASN.1 structure</li> 81 * <li>{@link ASN1HEX.isContextTag} - check if a hexadecimal tag is a specified ASN.1 context specific tag</li> 82 * <li>{@link ASN1HEX.isASN1HEX} - simple ASN.1 DER hexadecimal string checker</li> 83 * <li>{@link ASN1HEX.checkStrictDER} - strict ASN.1 DER hexadecimal string checker</li> 84 * <li>{@link ASN1HEX.hextooidstr} - convert hexadecimal string of OID to dotted integer list</li> 85 * </ul> 86 * </li> 87 * </ul> 88 */ 89 var ASN1HEX = new function() { 90 }; 91 92 /** 93 * get byte length for ASN.1 L(length) bytes<br/> 94 * @name getLblen 95 * @memberOf ASN1HEX 96 * @function 97 * @param {String} s hexadecimal string of ASN.1 DER encoded data 98 * @param {Number} idx string index 99 * @return byte length for ASN.1 L(length) bytes 100 * @since jsrsasign 7.2.0 asn1hex 1.1.11 101 * @example 102 * ASN1HEX.getLblen('020100', 0) → 1 for '01' 103 * ASN1HEX.getLblen('020200', 0) → 1 for '02' 104 * ASN1HEX.getLblen('02818003...', 0) → 2 for '8180' 105 * ASN1HEX.getLblen('0282025b03...', 0) → 3 for '82025b' 106 * ASN1HEX.getLblen('0280020100...', 0) → -1 for '80' BER indefinite length 107 * ASN1HEX.getLblen('02ffab...', 0) → -2 for malformed ASN.1 length 108 */ 109 ASN1HEX.getLblen = function(s, idx) { 110 if (s.substr(idx + 2, 1) != '8') return 1; 111 var i = parseInt(s.substr(idx + 3, 1)); 112 if (i == 0) return -1; // length octet '80' indefinite length 113 if (0 < i && i < 10) return i + 1; // including '8?' octet; 114 return -2; // malformed format 115 }; 116 117 /** 118 * get hexadecimal string for ASN.1 L(length) bytes<br/> 119 * @name getL 120 * @memberOf ASN1HEX 121 * @function 122 * @param {String} s hexadecimal string of ASN.1 DER encoded data 123 * @param {Number} idx string index to get L of ASN.1 object 124 * @return {String} hexadecimal string for ASN.1 L(length) bytes 125 * @since jsrsasign 7.2.0 asn1hex 1.1.11 126 */ 127 ASN1HEX.getL = function(s, idx) { 128 var len = ASN1HEX.getLblen(s, idx); 129 if (len < 1) return ''; 130 return s.substr(idx + 2, len * 2); 131 }; 132 133 /** 134 * get integer value of ASN.1 length for ASN.1 data<br/> 135 * @name getVblen 136 * @memberOf ASN1HEX 137 * @function 138 * @param {String} s hexadecimal string of ASN.1 DER encoded data 139 * @param {Number} idx string index 140 * @return {Number} ASN.1 L(length) integer value 141 * @since jsrsasign 7.2.0 asn1hex 1.1.11 142 */ 143 /* 144 getting ASN.1 length value at the position 'idx' of 145 hexa decimal string 's'. 146 f('3082025b02...', 0) ... 82025b ... ??? 147 f('020100', 0) ... 01 ... 1 148 f('0203001...', 0) ... 03 ... 3 149 f('02818003...', 0) ... 8180 ... 128 150 */ 151 ASN1HEX.getVblen = function(s, idx) { 152 var hLen, bi; 153 hLen = ASN1HEX.getL(s, idx); 154 if (hLen == '') return -1; 155 if (hLen.substr(0, 1) === '8') { 156 bi = new BigInteger(hLen.substr(2), 16); 157 } else { 158 bi = new BigInteger(hLen, 16); 159 } 160 return bi.intValue(); 161 }; 162 163 /** 164 * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'. 165 * @name getVidx 166 * @memberOf ASN1HEX 167 * @function 168 * @param {String} s hexadecimal string of ASN.1 DER encoded data 169 * @param {Number} idx string index 170 * @since jsrsasign 7.2.0 asn1hex 1.1.11 171 */ 172 ASN1HEX.getVidx = function(s, idx) { 173 var l_len = ASN1HEX.getLblen(s, idx); 174 if (l_len < 0) return l_len; 175 return idx + (l_len + 1) * 2; 176 }; 177 178 /** 179 * get hexadecimal string of ASN.1 V(value)<br/> 180 * @name getV 181 * @memberOf ASN1HEX 182 * @function 183 * @param {String} s hexadecimal string of ASN.1 DER encoded data 184 * @param {Number} idx string index 185 * @return {String} hexadecimal string of ASN.1 value. 186 * @since jsrsasign 7.2.0 asn1hex 1.1.11 187 */ 188 ASN1HEX.getV = function(s, idx) { 189 var idx1 = ASN1HEX.getVidx(s, idx); 190 var blen = ASN1HEX.getVblen(s, idx); 191 return s.substr(idx1, blen * 2); 192 }; 193 194 /** 195 * get hexadecimal string of ASN.1 TLV at<br/> 196 * @name getTLV 197 * @memberOf ASN1HEX 198 * @function 199 * @param {String} s hexadecimal string of ASN.1 DER encoded data 200 * @param {Number} idx string index 201 * @return {String} hexadecimal string of ASN.1 TLV. 202 * @since jsrsasign 7.2.0 asn1hex 1.1.11 203 */ 204 ASN1HEX.getTLV = function(s, idx) { 205 return s.substr(idx, 2) + ASN1HEX.getL(s, idx) + ASN1HEX.getV(s, idx); 206 }; 207 208 /** 209 * get byte length of ASN.1 TLV at specified string index<br/> 210 * @name getTLVblen 211 * @memberOf ASN1HEX 212 * @function 213 * @param {String} h hexadecimal string of ASN.1 DER encoded data 214 * @param {Number} idx string index to get ASN.1 TLV byte length 215 * @return {Number} byte length of ASN.1 TLV 216 * @since jsrsasign 9.1.5 asn1hex 1.1.11 217 * 218 * @description 219 * This method returns a byte length of ASN.1 TLV at 220 * specified string index. 221 * 222 * @example 223 * v string indx=42 224 * ASN1HEX.getTLVblen("...1303616161...", 42) → 10 (PrintableString 'aaa') 225 */ 226 ASN1HEX.getTLVblen = function(h, idx) { 227 return 2 + ASN1HEX.getLblen(h, idx) * 2 + ASN1HEX.getVblen(h, idx) * 2; 228 }; 229 230 // ========== sibling methods ================================ 231 232 /** 233 * get next sibling starting index for ASN.1 object string (DEPRECATED)<br/> 234 * @name getNextSiblingIdx 235 * @memberOf ASN1HEX 236 * @function 237 * @param {String} s hexadecimal string of ASN.1 DER encoded data 238 * @param {Number} idx string index 239 * @return {Number} next sibling starting index for ASN.1 object string 240 * @since jsrsasign 7.2.0 asn1hex 1.1.11 241 * @deprecated jsrsasign 9.1.5 asn1hex 1.2.5 Please use {@link ASN1HEX.getTLVblen} 242 * 243 * @example 244 * SEQUENCE { INTEGER 3, INTEGER 4 } 245 * 3006 246 * 020103 :idx=4 247 * 020104 :next sibling idx=10 248 * getNextSiblingIdx("3006020103020104", 4) & rarr 10 249 */ 250 ASN1HEX.getNextSiblingIdx = function(s, idx) { 251 var idx1 = ASN1HEX.getVidx(s, idx); 252 var blen = ASN1HEX.getVblen(s, idx); 253 return idx1 + blen * 2; 254 }; 255 256 // ========== children methods =============================== 257 /** 258 * get array of string indexes of child ASN.1 objects<br/> 259 * @name getChildIdx 260 * @memberOf ASN1HEX 261 * @function 262 * @param {String} h hexadecimal string of ASN.1 DER encoded data 263 * @param {Number} idx start string index of ASN.1 object 264 * @return {Array of Number} array of indexes for childen of ASN.1 objects 265 * @since jsrsasign 7.2.0 asn1hex 1.1.11 266 * @description 267 * This method returns array of integers for a concatination of ASN.1 objects 268 * in a ASN.1 value. As for BITSTRING, one byte of unusedbits is skipped. 269 * As for other ASN.1 simple types such as INTEGER, OCTET STRING or PRINTABLE STRING, 270 * it returns a array of a string index of its ASN.1 value.<br/> 271 * NOTE: Since asn1hex 1.1.7 of jsrsasign 6.1.2, Encapsulated BitString is supported. 272 * @example 273 * ASN1HEX.getChildIdx("0203012345", 0) ⇒ [4] // INTEGER 012345 274 * ASN1HEX.getChildIdx("1303616161", 0) ⇒ [4] // PrintableString aaa 275 * ASN1HEX.getChildIdx("030300ffff", 0) ⇒ [6] // BITSTRING ffff (unusedbits=00a) 276 * ASN1HEX.getChildIdx("3006020104020105", 0) ⇒ [4, 10] // SEQUENCE(INT4,INT5) 277 */ 278 ASN1HEX.getChildIdx = function(h, idx) { 279 var _ASN1HEX = ASN1HEX; 280 var a = []; 281 var idxStart, totalChildBlen, currentChildBlen; 282 283 idxStart = _ASN1HEX.getVidx(h, idx); 284 totalChildBlen = _ASN1HEX.getVblen(h, idx) * 2; 285 if (h.substr(idx, 2) == "03") { // BITSTRING without unusedbits 286 idxStart += 2; 287 totalChildBlen -= 2; 288 } 289 290 currentChildBlen = 0; 291 var i = idxStart; 292 while (currentChildBlen <= totalChildBlen) { 293 var tlvBlen = _ASN1HEX.getTLVblen(h, i); 294 currentChildBlen += tlvBlen; 295 if (currentChildBlen <= totalChildBlen) a.push(i); 296 i += tlvBlen; 297 if (currentChildBlen >= totalChildBlen) break; 298 } 299 return a; 300 }; 301 302 /** 303 * get string index of nth child object of ASN.1 object refered by h, idx<br/> 304 * @name getNthChildIdx 305 * @memberOf ASN1HEX 306 * @function 307 * @param {String} h hexadecimal string of ASN.1 DER encoded data 308 * @param {Number} idx start string index of ASN.1 object 309 * @param {Number} nth for child 310 * @return {Number} string index of nth child. 311 * @since jsrsasign 7.2.0 asn1hex 1.1.11 312 */ 313 ASN1HEX.getNthChildIdx = function(h, idx, nth) { 314 var a = ASN1HEX.getChildIdx(h, idx); 315 return a[nth]; 316 }; 317 318 // ========== decendant methods ============================== 319 /** 320 * get string index of nth child object of ASN.1 object refered by h, idx<br/> 321 * @name getIdxbyList 322 * @memberOf ASN1HEX 323 * @function 324 * @param {String} h hexadecimal string of ASN.1 DER encoded data 325 * @param {Number} currentIndex start string index of ASN.1 object 326 * @param {Array of Number} nthList array list of nth 327 * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList 328 * @return {Number} string index refered by nthList 329 * @since jsrsasign 7.1.4 asn1hex 1.1.10. 330 * @description 331 * @example 332 * The "nthList" is a index list of structured ASN.1 object 333 * reference. Here is a sample structure and "nthList"s which 334 * refers each objects. 335 * 336 * SQUENCE - 337 * SEQUENCE - [0] 338 * IA5STRING 000 - [0, 0] 339 * UTF8STRING 001 - [0, 1] 340 * SET - [1] 341 * IA5STRING 010 - [1, 0] 342 * UTF8STRING 011 - [1, 1] 343 */ 344 ASN1HEX.getIdxbyList = function(h, currentIndex, nthList, checkingTag) { 345 var _ASN1HEX = ASN1HEX; 346 var firstNth, a; 347 if (nthList.length == 0) { 348 if (checkingTag !== undefined) { 349 if (h.substr(currentIndex, 2) !== checkingTag) return -1; 350 } 351 return currentIndex; 352 } 353 firstNth = nthList.shift(); 354 a = _ASN1HEX.getChildIdx(h, currentIndex); 355 if (firstNth >= a.length) return -1; 356 357 return _ASN1HEX.getIdxbyList(h, a[firstNth], nthList, checkingTag); 358 }; 359 360 /** 361 * get string index of nth child object of ASN.1 object refered by h, idx<br/> 362 * @name getIdxbyListEx 363 * @memberOf ASN1HEX 364 * @function 365 * @param {String} h hexadecimal string of ASN.1 DER encoded data 366 * @param {Number} currentIndex start string index of ASN.1 object 367 * @param {Array of Object} nthList array list of nth index value or context specific tag string (ex. "[0]") 368 * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList 369 * @return {Number} string index refered by nthList. return -1 if not found 370 * @since jsrsasign 8.0.21 asn1hex 1.2.2 371 * @see <a href="https://github.com/kjur/jsrsasign/wiki/Tutorial-for-accessing-deep-inside-of-ASN.1-structure-by-using-new-ASN1HEX.getIdxbyListEx">ASN1HEX.getIdxbyListEx tutorial wiki page</a> 372 * 373 * @description 374 * This method returns the string index in h specified by currentIndex and 375 * nthList. This is useful to dig into a deep structured ASN.1 object 376 * by indexes called nthList. 377 * <br/> 378 * A nthList consists of a position number in children of ASN.1 379 * structured data or a context specific tag string (ex. "[1]"). 380 * Here is a sample deep structured ASN.1 data and 381 * nthLists referring decendent objects. 382 * <blockquote><pre> 383 * SQUENCE - referring nthList is below: 384 * SEQUENCE - [0] 385 * IA5STRING "a1" - [0, 0] 386 * UTF8STRING "a2" - [0, 1] 387 * SET - [1] 388 * IA5STRING "b1" - [1, 0] 389 * UTF8STRING "b2" - [1, 1] 390 * [0] "b3" - [1, "[0]"] // optional since context tag 391 * [1] "b4" - [1, "[1]"] // optional since context tag 392 * IA5STRING "b5" - [1, 2] // context is skipped. next is 2 393 * UTF8STRING "b6" - [1, 3] 394 * </pre></blockquote> 395 * 396 * <br/> 397 * This method can dig into ASN.1 object encapsulated by 398 * OctetString or BitString with unused bits. 399 * 400 * @example 401 * 3014 seq idx=0 402 * 3012 seq idx=4 403 * 020101 int:1 idx=8 404 * 020102 int:2 idx=14 405 * 800103 [0]:3 idx=20 406 * 810104 [1]:4 idx=26 407 * 020105 int:5 idx=32 408 * 020106 int:6 idx=38 409 * h = "30140412020101020102800103810104020105020106"; 410 * ASN1HEX.getIdxbyListEx(h, 0, [0, "[0]"]) → 16 411 * ASN1HEX.getIdxbyListEx(h, 0, [0, 2]) → 28 412 * ASN1HEX.getIdxbyListEx(h, 0, [0, 2], "0c") → -1 //not UTF8String(0c) 413 */ 414 ASN1HEX.getIdxbyListEx = function(h, currentIndex, nthList, checkingTag) { 415 var _ASN1HEX = ASN1HEX; 416 var firstNth, a; 417 if (nthList.length == 0) { 418 if (checkingTag !== undefined) { 419 if (h.substr(currentIndex, 2) !== checkingTag) { 420 return -1; 421 } 422 } 423 return currentIndex; 424 } 425 firstNth = nthList.shift(); 426 a = _ASN1HEX.getChildIdx(h, currentIndex); 427 428 var count = 0; 429 for (var i = 0; i < a.length; i++) { 430 var childTag = h.substr(a[i], 2); 431 432 if ((typeof firstNth == "number" && 433 (! _ASN1HEX.isContextTag(childTag)) && 434 count == firstNth) || 435 (typeof firstNth == "string" && 436 _ASN1HEX.isContextTag(childTag, firstNth))) { 437 return _ASN1HEX.getIdxbyListEx(h, a[i], nthList, checkingTag); 438 } 439 if (! _ASN1HEX.isContextTag(childTag)) count++; 440 } 441 return -1; 442 }; 443 444 /** 445 * get ASN.1 TLV by nthList<br/> 446 * @name getTLVbyList 447 * @memberOf ASN1HEX 448 * @function 449 * @param {String} h hexadecimal string of ASN.1 structure 450 * @param {Integer} currentIndex string index to start searching in hexadecimal string "h" 451 * @param {Array} nthList array of nth list index 452 * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList 453 * @return {String} referred hexadecimal string of ASN.1 TLV or null 454 * @since jsrsasign 7.1.4 asn1hex 1.1.10 455 * 456 * @description 457 * This static method is to get a ASN.1 value which specified "nthList" position 458 * with checking expected tag "checkingTag". 459 * <br/> 460 * When referring value can't be found, this returns null. 461 */ 462 ASN1HEX.getTLVbyList = function(h, currentIndex, nthList, checkingTag) { 463 var _ASN1HEX = ASN1HEX; 464 var idx = _ASN1HEX.getIdxbyList(h, currentIndex, nthList, checkingTag); 465 466 if (idx == -1) return null; 467 if (idx >= h.length) return null; 468 469 return _ASN1HEX.getTLV(h, idx); 470 }; 471 472 /** 473 * get ASN.1 TLV by nthList<br/> 474 * @name getTLVbyListEx 475 * @memberOf ASN1HEX 476 * @function 477 * @param {String} h hexadecimal string of ASN.1 structure 478 * @param {Integer} currentIndex string index to start searching in hexadecimal string "h" 479 * @param {Array of Object} nthList array list of nth index value or context specific tag string (ex. "[0]") 480 * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList 481 * @return {String} hexadecimal ASN.1 TLV string refered by nthList. return null if not found 482 * @since jsrsasign 8.0.21 asn1hex 1.2.2 483 * @see <a href="https://github.com/kjur/jsrsasign/wiki/Tutorial-for-accessing-deep-inside-of-ASN.1-structure-by-using-new-ASN1HEX.getIdxbyListEx">ASN1HEX.getIdxbyListEx tutorial wiki page</a> 484 * @see {@link ASN1HEX.getIdxbyListEx} 485 * @description 486 * This static method is to get a ASN.1 value which specified "nthList" position 487 * with checking expected tag "checkingTag". 488 * This method can dig into ASN.1 object encapsulated by 489 * OctetString or BitString with unused bits. 490 * @example 491 * 3014 seq idx=0 492 * 0312 seq idx=4 493 * 020101 int:1 idx=8 494 * 020102 int:2 idx=14 495 * 800103 [0]:3 idx=20 496 * 810104 [1]:4 idx=26 497 * 020105 int:5 idx=32 498 * 020106 int:6 idx=38 499 * h = "30140412020101020102800103810104020105020106"; 500 * ASN1HEX.getTLVbyList(h, 0, [0, "[0]"]) → 800103 501 * ASN1HEX.getTLVbyList(h, 0, [0, 2]) → 020105 502 * ASN1HEX.getTLVbyList(h, 0, [0, 2], "0c") → null //not UTF8String(0c) 503 */ 504 ASN1HEX.getTLVbyListEx = function(h, currentIndex, nthList, checkingTag) { 505 var _ASN1HEX = ASN1HEX; 506 var idx = _ASN1HEX.getIdxbyListEx(h, currentIndex, nthList, checkingTag); 507 if (idx == -1) return null; 508 return _ASN1HEX.getTLV(h, idx); 509 }; 510 511 /** 512 * get ASN.1 value by nthList<br/> 513 * @name getVbyList 514 * @memberOf ASN1HEX 515 * @function 516 * @param {String} h hexadecimal string of ASN.1 structure 517 * @param {Integer} currentIndex string index to start searching in hexadecimal string "h" 518 * @param {Array} nthList array of nth list index 519 * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList 520 * @param {Boolean} removeUnusedbits (OPTIONAL) flag for remove first byte for value (DEFAULT false) 521 * @return {String} referred hexadecimal string of ASN.1 value(V) or null 522 * @since asn1hex 1.1.4 523 * @see ASN1HEX.getIdxbyList 524 * @see ASN1HEX.getVbyListEx 525 * 526 * @description 527 * This static method is to get a ASN.1 value which specified "nthList" position 528 * with checking expected tag "checkingTag". 529 * <br/> 530 * When referring value can't be found, this returns null. 531 * <br/> 532 * NOTE: 'removeUnusedbits' flag has been supported since 533 * jsrsasign 7.1.14 asn1hex 1.1.10. 534 */ 535 ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag, removeUnusedbits) { 536 var _ASN1HEX = ASN1HEX; 537 var idx, v; 538 idx = _ASN1HEX.getIdxbyList(h, currentIndex, nthList, checkingTag); 539 540 if (idx == -1) return null; 541 if (idx >= h.length) return null; 542 543 v = _ASN1HEX.getV(h, idx); 544 if (removeUnusedbits === true) v = v.substr(2); 545 return v; 546 }; 547 548 /** 549 * get ASN.1 V by nthList<br/> 550 * @name getVbyListEx 551 * @memberOf ASN1HEX 552 * @function 553 * @param {String} h hexadecimal string of ASN.1 structure 554 * @param {Integer} currentIndex string index to start searching in hexadecimal string "h" 555 * @param {Array of Object} nthList array list of nth index value or context specific tag string (ex. "[0]") 556 * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList (default is undefined) 557 * @param {Boolean} removeUnusedbits (OPTIONAL) flag for trim unused bit from result value (default is undefined) 558 * @return {String} hexadecimal ASN.1 V string refered by nthList. return null if not found 559 * @since jsrsasign 8.0.21 asn1hex 1.2.2 560 * @see <a href="https://github.com/kjur/jsrsasign/wiki/Tutorial-for-accessing-deep-inside-of-ASN.1-structure-by-using-new-ASN1HEX.getIdxbyListEx">ASN1HEX.getIdxbyListEx tutorial wiki page</a> 561 * @see {@link ASN1HEX.getIdxbyListEx} 562 * 563 * @description 564 * This static method is to get a ASN.1 value which specified "nthList" position 565 * with checking expected tag "checkingTag". 566 * This method can dig into ASN.1 object encapsulated by 567 * OctetString or BitString with unused bits. 568 * 569 * @example 570 * 3014 seq idx=0 571 * 3012 seq idx=4 572 * 020101 int:1 idx=8 573 * 020102 int:2 idx=14 574 * 800103 [0]:3 idx=20 575 * 810104 [1]:4 idx=26 576 * 020105 int:5 idx=32 577 * 020106 int:6 idx=38 578 * h = "30140412020101020102800103810104020105020106"; 579 * ASN1HEX.getTLVbyList(h, 0, [0, "[0]"]) → 03 580 * ASN1HEX.getTLVbyList(h, 0, [0, 2]) → 05 581 * ASN1HEX.getTLVbyList(h, 0, [0, 2], "0c") → null //not UTF8String(0c) 582 */ 583 ASN1HEX.getVbyListEx = function(h, currentIndex, nthList, checkingTag, removeUnusedbits) { 584 var _ASN1HEX = ASN1HEX; 585 var idx, tlv, v; 586 idx = _ASN1HEX.getIdxbyListEx(h, currentIndex, nthList, checkingTag); 587 if (idx == -1) return null; 588 v = _ASN1HEX.getV(h, idx); 589 if (h.substr(idx, 2) == "03" && removeUnusedbits !== false) v = v.substr(2); 590 return v; 591 }; 592 593 /** 594 * get OID string from hexadecimal encoded value<br/> 595 * @name hextooidstr 596 * @memberOf ASN1HEX 597 * @function 598 * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value 599 * @return {String} OID string (ex. '1.2.3.4.567') 600 * @since asn1hex 1.1.5 601 * @see {@link KJUR.asn1.ASN1Util.oidIntToHex} 602 * @description 603 * This static method converts from ASN.1 DER encoded 604 * hexadecimal object identifier value to dot concatinated OID value. 605 * {@link KJUR.asn1.ASN1Util.oidIntToHex} is a reverse function of this. 606 * @example 607 * ASN1HEX.hextooidstr("550406") → "2.5.4.6" 608 */ 609 ASN1HEX.hextooidstr = function(hex) { 610 var zeroPadding = function(s, len) { 611 if (s.length >= len) return s; 612 return new Array(len - s.length + 1).join('0') + s; 613 }; 614 615 var a = []; 616 617 // a[0], a[1] 618 var hex0 = hex.substr(0, 2); 619 var i0 = parseInt(hex0, 16); 620 a[0] = new String(Math.floor(i0 / 40)); 621 a[1] = new String(i0 % 40); 622 623 // a[2]..a[n] 624 var hex1 = hex.substr(2); 625 var b = []; 626 for (var i = 0; i < hex1.length / 2; i++) { 627 b.push(parseInt(hex1.substr(i * 2, 2), 16)); 628 } 629 var c = []; 630 var cbin = ""; 631 for (var i = 0; i < b.length; i++) { 632 if (b[i] & 0x80) { 633 cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7); 634 } else { 635 cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7); 636 c.push(new String(parseInt(cbin, 2))); 637 cbin = ""; 638 } 639 } 640 641 var s = a.join("."); 642 if (c.length > 0) s = s + "." + c.join("."); 643 return s; 644 }; 645 646 /** 647 * get string of simple ASN.1 dump from hexadecimal ASN.1 data<br/> 648 * @name dump 649 * @memberOf ASN1HEX 650 * @function 651 * @param {Object} hexOrObj hexadecmal string of ASN.1 data or ASN1Object object 652 * @param {Array} flags associative array of flags for dump (OPTION) 653 * @param {Number} idx string index for starting dump (OPTION) 654 * @param {String} indent indent string (OPTION) 655 * @return {String} string of simple ASN.1 dump 656 * @since jsrsasign 4.8.3 asn1hex 1.1.6 657 * @description 658 * This method will get an ASN.1 dump from 659 * hexadecmal string of ASN.1 DER encoded data. 660 * Here are features: 661 * <ul> 662 * <li>ommit long hexadecimal string</li> 663 * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li> 664 * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li> 665 * <li>automatic decode for implicit primitive context specific tag 666 * (good for X.509v3 extension value) 667 * <ul> 668 * <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li> 669 * <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag 670 * value will be encoded as utf8 string</li> 671 * <li>otherwise it shows as hexadecimal string</li> 672 * </ul> 673 * </li> 674 * </ul> 675 * NOTE1: Argument {@link KJUR.asn1.ASN1Object} object is supported since 676 * jsrsasign 6.2.4 asn1hex 1.0.8 677 * @example 678 * // 1) ASN.1 INTEGER 679 * ASN1HEX.dump('0203012345') 680 * ↓ 681 * INTEGER 012345 682 * 683 * // 2) ASN.1 Object Identifier 684 * ASN1HEX.dump('06052b0e03021a') 685 * ↓ 686 * ObjectIdentifier sha1 (1 3 14 3 2 26) 687 * 688 * // 3) ASN.1 SEQUENCE 689 * ASN1HEX.dump('3006020101020102') 690 * ↓ 691 * SEQUENCE 692 * INTEGER 01 693 * INTEGER 02 694 * 695 * // 4) ASN.1 SEQUENCE since jsrsasign 6.2.4 696 * o = KJUR.asn1.ASN1Util.newObject({seq: [{int: 1}, {int: 2}]}); 697 * ASN1HEX.dump(o) 698 * ↓ 699 * SEQUENCE 700 * INTEGER 01 701 * INTEGER 02 702 * // 5) ASN.1 DUMP FOR X.509 CERTIFICATE 703 * ASN1HEX.dump(pemtohex(certPEM)) 704 * ↓ 705 * SEQUENCE 706 * SEQUENCE 707 * [0] 708 * INTEGER 02 709 * INTEGER 0c009310d206dbe337553580118ddc87 710 * SEQUENCE 711 * ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11) 712 * NULL 713 * SEQUENCE 714 * SET 715 * SEQUENCE 716 * ObjectIdentifier countryName (2 5 4 6) 717 * PrintableString 'US' 718 * : 719 */ 720 ASN1HEX.dump = function(hexOrObj, flags, idx, indent) { 721 var _ASN1HEX = ASN1HEX; 722 var _getV = _ASN1HEX.getV; 723 var _dump = _ASN1HEX.dump; 724 var _getChildIdx = _ASN1HEX.getChildIdx; 725 726 var hex = hexOrObj; 727 if (hexOrObj instanceof KJUR.asn1.ASN1Object) 728 hex = hexOrObj.getEncodedHex(); 729 730 var _skipLongHex = function(hex, limitNumOctet) { 731 if (hex.length <= limitNumOctet * 2) { 732 return hex; 733 } else { 734 var s = hex.substr(0, limitNumOctet) + 735 "..(total " + hex.length / 2 + "bytes).." + 736 hex.substr(hex.length - limitNumOctet, limitNumOctet); 737 return s; 738 }; 739 }; 740 741 if (flags === undefined) flags = { "ommit_long_octet": 32 }; 742 if (idx === undefined) idx = 0; 743 if (indent === undefined) indent = ""; 744 var skipLongHex = flags.ommit_long_octet; 745 746 var tag = hex.substr(idx, 2); 747 748 if (tag == "01") { 749 var v = _getV(hex, idx); 750 if (v == "00") { 751 return indent + "BOOLEAN FALSE\n"; 752 } else { 753 return indent + "BOOLEAN TRUE\n"; 754 } 755 } 756 if (tag == "02") { 757 var v = _getV(hex, idx); 758 return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n"; 759 } 760 if (tag == "03") { 761 var v = _getV(hex, idx); 762 if (_ASN1HEX.isASN1HEX(v.substr(2))) { 763 var s = indent + "BITSTRING, encapsulates\n"; 764 s = s + _dump(v.substr(2), flags, 0, indent + " "); 765 return s; 766 } else { 767 return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n"; 768 } 769 } 770 if (tag == "04") { 771 var v = _getV(hex, idx); 772 if (_ASN1HEX.isASN1HEX(v)) { 773 var s = indent + "OCTETSTRING, encapsulates\n"; 774 s = s + _dump(v, flags, 0, indent + " "); 775 return s; 776 } else { 777 return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n"; 778 } 779 } 780 if (tag == "05") { 781 return indent + "NULL\n"; 782 } 783 if (tag == "06") { 784 var hV = _getV(hex, idx); 785 var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV); 786 var oidName = KJUR.asn1.x509.OID.oid2name(oidDot); 787 var oidSpc = oidDot.replace(/\./g, ' '); 788 if (oidName != '') { 789 return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n"; 790 } else { 791 return indent + "ObjectIdentifier (" + oidSpc + ")\n"; 792 } 793 } 794 if (tag == "0a") { 795 return indent + "ENUMERATED " + parseInt(_getV(hex, idx)) + "\n"; 796 } 797 if (tag == "0c") { 798 return indent + "UTF8String '" + hextoutf8(_getV(hex, idx)) + "'\n"; 799 } 800 if (tag == "13") { 801 return indent + "PrintableString '" + hextoutf8(_getV(hex, idx)) + "'\n"; 802 } 803 if (tag == "14") { 804 return indent + "TeletexString '" + hextoutf8(_getV(hex, idx)) + "'\n"; 805 } 806 if (tag == "16") { 807 return indent + "IA5String '" + hextoutf8(_getV(hex, idx)) + "'\n"; 808 } 809 if (tag == "17") { 810 return indent + "UTCTime " + hextoutf8(_getV(hex, idx)) + "\n"; 811 } 812 if (tag == "18") { 813 return indent + "GeneralizedTime " + hextoutf8(_getV(hex, idx)) + "\n"; 814 } 815 if (tag == "1a") { 816 return indent + "VisualString '" + hextoutf8(_getV(hex, idx)) + "'\n"; 817 } 818 if (tag == "1e") { 819 return indent + "BMPString '" + hextoutf8(_getV(hex, idx)) + "'\n"; 820 } 821 if (tag == "30") { 822 if (hex.substr(idx, 4) == "3000") { 823 return indent + "SEQUENCE {}\n"; 824 } 825 826 var s = indent + "SEQUENCE\n"; 827 var aIdx = _getChildIdx(hex, idx); 828 829 var flagsTemp = flags; 830 831 if ((aIdx.length == 2 || aIdx.length == 3) && 832 hex.substr(aIdx[0], 2) == "06" && 833 hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension 834 var oidName = _ASN1HEX.oidname(_getV(hex, aIdx[0])); 835 var flagsClone = JSON.parse(JSON.stringify(flags)); 836 flagsClone.x509ExtName = oidName; 837 flagsTemp = flagsClone; 838 } 839 840 for (var i = 0; i < aIdx.length; i++) { 841 s = s + _dump(hex, flagsTemp, aIdx[i], indent + " "); 842 } 843 return s; 844 } 845 if (tag == "31") { 846 var s = indent + "SET\n"; 847 var aIdx = _getChildIdx(hex, idx); 848 for (var i = 0; i < aIdx.length; i++) { 849 s = s + _dump(hex, flags, aIdx[i], indent + " "); 850 } 851 return s; 852 } 853 var tag = parseInt(tag, 16); 854 if ((tag & 128) != 0) { // context specific 855 var tagNumber = tag & 31; 856 if ((tag & 32) != 0) { // structured tag 857 var s = indent + "[" + tagNumber + "]\n"; 858 var aIdx = _getChildIdx(hex, idx); 859 for (var i = 0; i < aIdx.length; i++) { 860 s = s + _dump(hex, flags, aIdx[i], indent + " "); 861 } 862 return s; 863 } else { // primitive tag 864 var v = _getV(hex, idx); 865 if (ASN1HEX.isASN1HEX(v)) { 866 var s = indent + "[" + tagNumber + "]\n"; 867 s = s + _dump(v, flags, 0, indent + " "); 868 return s; 869 } else if (v.substr(0, 8) == "68747470") { // http 870 v = hextoutf8(v); 871 } else if (flags.x509ExtName === "subjectAltName" && 872 tagNumber == 2) { 873 v = hextoutf8(v); 874 } 875 // else if (ASN1HEX.isASN1HEX(v)) 876 877 var s = indent + "[" + tagNumber + "] " + v + "\n"; 878 return s; 879 } 880 } 881 return indent + "UNKNOWN(" + tag + ") " + 882 _getV(hex, idx) + "\n"; 883 }; 884 885 /** 886 * check if a hexadecimal tag is a specified ASN.1 context specific tag 887 * @name isContextTag 888 * @memberOf ASN1HEX 889 * @function 890 * @param {hTag} hex string of a hexadecimal ASN.1 tag consists by two characters (e.x. "a0") 891 * @param {sTag} context specific tag in string represention (OPTION) (e.x. "[0]") 892 * @return {Boolean} true if hTag is a ASN.1 context specific tag specified by sTag value. 893 * @since jsrsasign 8.0.21 asn1hex 1.2.2 894 * @description 895 * This method checks if a hexadecimal tag is a specified ASN.1 context specific tag. 896 * Structured and non-structured type of tag have the same string representation 897 * of context specific tag. For example tag "a0" and "80" have the same string 898 * representation "[0]". 899 * The sTag has a range from from "[0]" to "[31]". 900 * @example 901 * ASN1HEX.isContextTag('a0', '[0]') → true // structured 902 * ASN1HEX.isContextTag('a1', '[1]') → true // structured 903 * ASN1HEX.isContextTag('a2', '[2]') → true // structured 904 * ASN1HEX.isContextTag('80', '[0]') → true // non structured 905 * ASN1HEX.isContextTag('81', '[1]') → true // non structured 906 * ASN1HEX.isContextTag('82', '[2]') → true // non structured 907 * ASN1HEX.isContextTag('a0', '[3]') → false 908 * ASN1HEX.isContextTag('80', '[15]') → false 909 * 910 * ASN.1 tag bits 911 * 12345679 912 * ++ tag class(universal:00, context specific:10) 913 * + structured:1, primitive:0 914 * +++++ tag number (0 - 31) 915 */ 916 ASN1HEX.isContextTag = function(hTag, sTag) { 917 hTag = hTag.toLowerCase(); 918 var ihtag, istag; 919 920 try { 921 ihtag = parseInt(hTag, 16); 922 } catch (ex) { 923 return -1; 924 } 925 926 if (sTag === undefined) { 927 if ((ihtag & 192) == 128) { 928 return true; 929 } else { 930 return false; 931 } 932 } 933 934 try { 935 var result = sTag.match(/^\[[0-9]+\]$/); 936 if (result == null) return false; 937 istag = parseInt(sTag.substr(1,sTag.length - 1), 10); 938 if (istag > 31) return false; 939 if (((ihtag & 192) == 128) && // ihtag & b11000000 == b10000000 940 ((ihtag & 31) == istag)) { // ihtag & b00011111 == istag (0-31) 941 return true; 942 } 943 return false; 944 } catch (ex) { 945 return false; 946 } 947 }; 948 949 /** 950 * simple ASN.1 DER hexadecimal string checker 951 * @name isASN1HEX 952 * @memberOf ASN1HEX 953 * @function 954 * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not 955 * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false 956 * @since jsrsasign 4.8.3 asn1hex 1.1.6 957 * @description 958 * This method checks wheather the argument 'hex' is a hexadecimal string of 959 * ASN.1 data or not. 960 * @example 961 * ASN1HEX.isASN1HEX('0203012345') → true // PROPER ASN.1 INTEGER 962 * ASN1HEX.isASN1HEX('0203012345ff') → false // TOO LONG VALUE 963 * ASN1HEX.isASN1HEX('02030123') → false // TOO SHORT VALUE 964 * ASN1HEX.isASN1HEX('fa3bcd') → false // WRONG FOR ASN.1 965 */ 966 ASN1HEX.isASN1HEX = function(hex) { 967 var _ASN1HEX = ASN1HEX; 968 if (hex.length % 2 == 1) return false; 969 970 var intL = _ASN1HEX.getVblen(hex, 0); 971 var hT = hex.substr(0, 2); 972 var hL = _ASN1HEX.getL(hex, 0); 973 var hVLength = hex.length - hT.length - hL.length; 974 if (hVLength == intL * 2) return true; 975 976 return false; 977 }; 978 979 /** 980 * strict ASN.1 DER hexadecimal string checker 981 * @name checkStrictDER 982 * @memberOf ASN1HEX 983 * @function 984 * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not 985 * @return unspecified 986 * @since jsrsasign 8.0.19 asn1hex 1.2.1 987 * @throws Error when malformed ASN.1 DER hexadecimal string 988 * @description 989 * This method checks wheather the argument 'hex' is a hexadecimal string of 990 * ASN.1 data or not. If the argument is not DER string, this 991 * raise an exception. 992 * @example 993 * ASN1HEX.checkStrictDER('0203012345') → NO EXCEPTION FOR PROPER ASN.1 INTEGER 994 * ASN1HEX.checkStrictDER('0203012345ff') → RAISE EXCEPTION FOR TOO LONG VALUE 995 * ASN1HEX.checkStrictDER('02030123') → false RAISE EXCEPITON FOR TOO SHORT VALUE 996 * ASN1HEX.checkStrictDER('fa3bcd') → false RAISE EXCEPTION FOR WRONG ASN.1 997 */ 998 ASN1HEX.checkStrictDER = function(h, idx, maxHexLen, maxByteLen, maxLbyteLen) { 999 var _ASN1HEX = ASN1HEX; 1000 1001 if (maxHexLen === undefined) { 1002 // 1. hex string check 1003 if (typeof h != "string") throw new Error("not hex string"); 1004 h = h.toLowerCase(); 1005 if (! KJUR.lang.String.isHex(h)) throw new Error("not hex string"); 1006 1007 // 2. set max if needed 1008 // max length of hexadecimal string 1009 maxHexLen = h.length; 1010 // max length of octets 1011 maxByteLen = h.length / 2; 1012 // max length of L octets of TLV 1013 if (maxByteLen < 0x80) { 1014 maxLbyteLen = 1; 1015 } else { 1016 maxLbyteLen = Math.ceil(maxByteLen.toString(16)) + 1; 1017 } 1018 } 1019 //console.log(maxHexLen + ":" + maxByteLen + ":" + maxLbyteLen); 1020 1021 // 3. check if L(length) string not exceeds maxLbyteLen 1022 var hL = _ASN1HEX.getL(h, idx); 1023 if (hL.length > maxLbyteLen * 2) 1024 throw new Error("L of TLV too long: idx=" + idx); 1025 1026 // 4. check if V(value) octet length (i.e. L(length) value) 1027 // not exceeds maxByteLen 1028 var vblen = _ASN1HEX.getVblen(h, idx); 1029 if (vblen > maxByteLen) 1030 throw new Error("value of L too long than hex: idx=" + idx); 1031 1032 // 5. check V string length and L's value are the same 1033 var hTLV = _ASN1HEX.getTLV(h, idx); 1034 var hVLength = 1035 hTLV.length - 2 - _ASN1HEX.getL(h, idx).length; 1036 if (hVLength !== (vblen * 2)) 1037 throw new Error("V string length and L's value not the same:" + 1038 hVLength + "/" + (vblen * 2)); 1039 1040 // 6. check appending garbled string 1041 if (idx === 0) { 1042 if (h.length != hTLV.length) 1043 throw new Error("total length and TLV length unmatch:" + 1044 h.length + "!=" + hTLV.length); 1045 } 1046 1047 // 7. check if there isn't prepending zeros in DER INTEGER value 1048 var hT = h.substr(idx, 2); 1049 if (hT === '02') { 1050 var vidx = _ASN1HEX.getVidx(h, idx); 1051 // check if DER INTEGER VALUE have least leading zeros 1052 // for two's complement 1053 // GOOD - 3fabde... 008fad... 1054 // BAD - 000012... 007fad... 1055 if (h.substr(vidx, 2) == "00" && h.charCodeAt(vidx + 2) < 56) // '8'=56 1056 throw new Error("not least zeros for DER INTEGER"); 1057 } 1058 1059 // 8. check if all of elements in a structured item are conformed to 1060 // strict DER encoding rules. 1061 if (parseInt(hT, 16) & 32) { // structured tag? 1062 var intL = _ASN1HEX.getVblen(h, idx); 1063 var sum = 0; 1064 var aIdx = _ASN1HEX.getChildIdx(h, idx); 1065 for (var i = 0; i < aIdx.length; i++) { 1066 var tlv = _ASN1HEX.getTLV(h, aIdx[i]); 1067 sum += tlv.length; 1068 _ASN1HEX.checkStrictDER(h, aIdx[i], 1069 maxHexLen, maxByteLen, maxLbyteLen); 1070 } 1071 if ((intL * 2) != sum) 1072 throw new Error("sum of children's TLV length and L unmatch: " + 1073 (intL * 2) + "!=" + sum); 1074 } 1075 }; 1076 1077 /** 1078 * get hexacedimal string from PEM format data<br/> 1079 * @name oidname 1080 * @memberOf ASN1HEX 1081 * @function 1082 * @param {String} oidDotOrHex number dot notation(i.e. 1.2.3) or hexadecimal string for OID 1083 * @return {String} name for OID 1084 * @since jsrsasign 7.2.0 asn1hex 1.1.11 1085 * @description 1086 * This static method gets a OID name for 1087 * a specified string of number dot notation (i.e. 1.2.3) or 1088 * hexadecimal string. 1089 * @example 1090 * ASN1HEX.oidname("2.5.29.37") → extKeyUsage 1091 * ASN1HEX.oidname("551d25") → extKeyUsage 1092 * ASN1HEX.oidname("0.1.2.3") → 0.1.2.3 // unknown 1093 */ 1094 ASN1HEX.oidname = function(oidDotOrHex) { 1095 var _KJUR_asn1 = KJUR.asn1; 1096 if (KJUR.lang.String.isHex(oidDotOrHex)) 1097 oidDotOrHex = _KJUR_asn1.ASN1Util.oidHexToInt(oidDotOrHex); 1098 var name = _KJUR_asn1.x509.OID.oid2name(oidDotOrHex); 1099 if (name === "") name = oidDotOrHex; 1100 return name; 1101 }; 1102 1103