1 /*! asn1hex-1.1.6.js (c) 2012-2016 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * asn1hex.js - Hexadecimal represented ASN.1 string library 5 * 6 * Copyright (c) 2010-2016 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 asn1hex-1.1.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version asn1hex 1.1.6 (2015-Jun-11) 20 * @license <a href="http://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.getHexOfTLV_AtObj} - get ASN.1 TLV at specified position</li> 49 * <li>{@link ASN1HEX.getHexOfV_AtObj} - get ASN.1 V at specified position</li> 50 * <li>{@link ASN1HEX.getHexOfL_AtObj} - get hexadecimal ASN.1 L at specified position</li> 51 * <li>{@link ASN1HEX.getIntOfL_AtObj} - get integer ASN.1 L at specified position</li> 52 * <li>{@link ASN1HEX.getStartPosOfV_AtObj} - get ASN.1 V position from its ASN.1 TLV position</li> 53 * </ul> 54 * </li> 55 * <li><b>ACCESS FOR CHILD ITEM</b> 56 * <ul> 57 * <li>{@link ASN1HEX.getNthChildIndex_AtObj} - get nth child index at specified position</li> 58 * <li>{@link ASN1HEX.getPosArrayOfChildren_AtObj} - get indexes of children</li> 59 * <li>{@link ASN1HEX.getPosOfNextSibling_AtObj} - get position of next sibling</li> 60 * </ul> 61 * </li> 62 * <li><b>ACCESS NESTED ASN.1 STRUCTURE</b> 63 * <ul> 64 * <li>{@link ASN1HEX.getDecendantHexTLVByNthList} - get ASN.1 TLV at specified list index</li> 65 * <li>{@link ASN1HEX.getDecendantHexVByNthList} - get ASN.1 V at specified list index</li> 66 * <li>{@link ASN1HEX.getDecendantIndexByNthList} - get index at specified list index</li> 67 * </ul> 68 * </li> 69 * <li><b>UTILITIES</b> 70 * <ul> 71 * <li>{@link ASN1HEX.dump} - dump ASN.1 structure</li> 72 * <li>{@link ASN1HEX.isASN1HEX} - check whether ASN.1 hexadecimal string or not</li> 73 * <li>{@link ASN1HEX.hextooidstr} - convert hexadecimal string of OID to dotted integer list</li> 74 * </ul> 75 * </li> 76 * </ul> 77 */ 78 var ASN1HEX = new function() { 79 /** 80 * get byte length for ASN.1 L(length) bytes 81 * @name getByteLengthOfL_AtObj 82 * @memberOf ASN1HEX 83 * @function 84 * @param {String} s hexadecimal string of ASN.1 DER encoded data 85 * @param {Number} pos string index 86 * @return byte length for ASN.1 L(length) bytes 87 */ 88 this.getByteLengthOfL_AtObj = function(s, pos) { 89 if (s.substring(pos + 2, pos + 3) != '8') return 1; 90 var i = parseInt(s.substring(pos + 3, pos + 4)); 91 if (i == 0) return -1; // length octet '80' indefinite length 92 if (0 < i && i < 10) return i + 1; // including '8?' octet; 93 return -2; // malformed format 94 }; 95 96 /** 97 * get hexadecimal string for ASN.1 L(length) bytes 98 * @name getHexOfL_AtObj 99 * @memberOf ASN1HEX 100 * @function 101 * @param {String} s hexadecimal string of ASN.1 DER encoded data 102 * @param {Number} pos string index 103 * @return {String} hexadecimal string for ASN.1 L(length) bytes 104 */ 105 this.getHexOfL_AtObj = function(s, pos) { 106 var len = this.getByteLengthOfL_AtObj(s, pos); 107 if (len < 1) return ''; 108 return s.substring(pos + 2, pos + 2 + len * 2); 109 }; 110 111 // getting ASN.1 length value at the position 'idx' of 112 // hexa decimal string 's'. 113 // 114 // f('3082025b02...', 0) ... 82025b ... ??? 115 // f('020100', 0) ... 01 ... 1 116 // f('0203001...', 0) ... 03 ... 3 117 // f('02818003...', 0) ... 8180 ... 128 118 /** 119 * get integer value of ASN.1 length for ASN.1 data 120 * @name getIntOfL_AtObj 121 * @memberOf ASN1HEX 122 * @function 123 * @param {String} s hexadecimal string of ASN.1 DER encoded data 124 * @param {Number} pos string index 125 * @return ASN.1 L(length) integer value 126 */ 127 this.getIntOfL_AtObj = function(s, pos) { 128 var hLength = this.getHexOfL_AtObj(s, pos); 129 if (hLength == '') return -1; 130 var bi; 131 if (parseInt(hLength.substring(0, 1)) < 8) { 132 bi = new BigInteger(hLength, 16); 133 } else { 134 bi = new BigInteger(hLength.substring(2), 16); 135 } 136 return bi.intValue(); 137 }; 138 139 /** 140 * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'. 141 * @name getStartPosOfV_AtObj 142 * @memberOf ASN1HEX 143 * @function 144 * @param {String} s hexadecimal string of ASN.1 DER encoded data 145 * @param {Number} pos string index 146 */ 147 this.getStartPosOfV_AtObj = function(s, pos) { 148 var l_len = this.getByteLengthOfL_AtObj(s, pos); 149 if (l_len < 0) return l_len; 150 return pos + (l_len + 1) * 2; 151 }; 152 153 /** 154 * get hexadecimal string of ASN.1 V(value) 155 * @name getHexOfV_AtObj 156 * @memberOf ASN1HEX 157 * @function 158 * @param {String} s hexadecimal string of ASN.1 DER encoded data 159 * @param {Number} pos string index 160 * @return {String} hexadecimal string of ASN.1 value. 161 */ 162 this.getHexOfV_AtObj = function(s, pos) { 163 var pos1 = this.getStartPosOfV_AtObj(s, pos); 164 var len = this.getIntOfL_AtObj(s, pos); 165 return s.substring(pos1, pos1 + len * 2); 166 }; 167 168 /** 169 * get hexadecimal string of ASN.1 TLV at 170 * @name getHexOfTLV_AtObj 171 * @memberOf ASN1HEX 172 * @function 173 * @param {String} s hexadecimal string of ASN.1 DER encoded data 174 * @param {Number} pos string index 175 * @return {String} hexadecimal string of ASN.1 TLV. 176 * @since 1.1 177 */ 178 this.getHexOfTLV_AtObj = function(s, pos) { 179 var hT = s.substr(pos, 2); 180 var hL = this.getHexOfL_AtObj(s, pos); 181 var hV = this.getHexOfV_AtObj(s, pos); 182 return hT + hL + hV; 183 }; 184 185 /** 186 * get next sibling starting index for ASN.1 object string 187 * @name getPosOfNextSibling_AtObj 188 * @memberOf ASN1HEX 189 * @function 190 * @param {String} s hexadecimal string of ASN.1 DER encoded data 191 * @param {Number} pos string index 192 * @return next sibling starting index for ASN.1 object string 193 */ 194 this.getPosOfNextSibling_AtObj = function(s, pos) { 195 var pos1 = this.getStartPosOfV_AtObj(s, pos); 196 var len = this.getIntOfL_AtObj(s, pos); 197 return pos1 + len * 2; 198 }; 199 200 /** 201 * get array of indexes of child ASN.1 objects 202 * @name getPosArrayOfChildren_AtObj 203 * @memberOf ASN1HEX 204 * @function 205 * @param {String} s hexadecimal string of ASN.1 DER encoded data 206 * @param {Number} start string index of ASN.1 object 207 * @return {Array of Number} array of indexes for childen of ASN.1 objects 208 */ 209 this.getPosArrayOfChildren_AtObj = function(h, pos) { 210 var a = new Array(); 211 var p0 = this.getStartPosOfV_AtObj(h, pos); 212 a.push(p0); 213 214 var len = this.getIntOfL_AtObj(h, pos); 215 var p = p0; 216 var k = 0; 217 while (1) { 218 var pNext = this.getPosOfNextSibling_AtObj(h, p); 219 if (pNext == null || (pNext - p0 >= (len * 2))) break; 220 if (k >= 200) break; 221 222 a.push(pNext); 223 p = pNext; 224 225 k++; 226 } 227 228 return a; 229 }; 230 231 /** 232 * get string index of nth child object of ASN.1 object refered by h, idx 233 * @name getNthChildIndex_AtObj 234 * @memberOf ASN1HEX 235 * @function 236 * @param {String} h hexadecimal string of ASN.1 DER encoded data 237 * @param {Number} idx start string index of ASN.1 object 238 * @param {Number} nth for child 239 * @return {Number} string index of nth child. 240 * @since 1.1 241 */ 242 this.getNthChildIndex_AtObj = function(h, idx, nth) { 243 var a = this.getPosArrayOfChildren_AtObj(h, idx); 244 return a[nth]; 245 }; 246 247 // ========== decendant methods ============================== 248 /** 249 * get string index of nth child object of ASN.1 object refered by h, idx 250 * @name getDecendantIndexByNthList 251 * @memberOf ASN1HEX 252 * @function 253 * @param {String} h hexadecimal string of ASN.1 DER encoded data 254 * @param {Number} currentIndex start string index of ASN.1 object 255 * @param {Array of Number} nthList array list of nth 256 * @return {Number} string index refered by nthList 257 * @since 1.1 258 * @example 259 * The "nthList" is a index list of structured ASN.1 object 260 * reference. Here is a sample structure and "nthList"s which 261 * refers each objects. 262 * 263 * SQUENCE - 264 * SEQUENCE - [0] 265 * IA5STRING 000 - [0, 0] 266 * UTF8STRING 001 - [0, 1] 267 * SET - [1] 268 * IA5STRING 010 - [1, 0] 269 * UTF8STRING 011 - [1, 1] 270 */ 271 this.getDecendantIndexByNthList = function(h, currentIndex, nthList) { 272 if (nthList.length == 0) { 273 return currentIndex; 274 } 275 var firstNth = nthList.shift(); 276 var a = this.getPosArrayOfChildren_AtObj(h, currentIndex); 277 return this.getDecendantIndexByNthList(h, a[firstNth], nthList); 278 }; 279 280 /** 281 * get hexadecimal string of ASN.1 TLV refered by current index and nth index list. 282 * @name getDecendantHexTLVByNthList 283 * @memberOf ASN1HEX 284 * @function 285 * @param {String} h hexadecimal string of ASN.1 DER encoded data 286 * @param {Number} currentIndex start string index of ASN.1 object 287 * @param {Array of Number} nthList array list of nth 288 * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList 289 * @since 1.1 290 */ 291 this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) { 292 var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList); 293 return this.getHexOfTLV_AtObj(h, idx); 294 }; 295 296 /** 297 * get hexadecimal string of ASN.1 V refered by current index and nth index list. 298 * @name getDecendantHexVByNthList 299 * @memberOf ASN1HEX 300 * @function 301 * @param {String} h hexadecimal string of ASN.1 DER encoded data 302 * @param {Number} currentIndex start string index of ASN.1 object 303 * @param {Array of Number} nthList array list of nth 304 * @return {Number} hexadecimal string of ASN.1 V refered by nthList 305 * @since 1.1 306 */ 307 this.getDecendantHexVByNthList = function(h, currentIndex, nthList) { 308 var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList); 309 return this.getHexOfV_AtObj(h, idx); 310 }; 311 }; 312 313 /* 314 * @since asn1hex 1.1.4 315 */ 316 ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) { 317 var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList); 318 if (idx === undefined) { 319 throw "can't find nthList object"; 320 } 321 if (checkingTag !== undefined) { 322 if (h.substr(idx, 2) != checkingTag) { 323 throw "checking tag doesn't match: " + 324 h.substr(idx,2) + "!=" + checkingTag; 325 } 326 } 327 return this.getHexOfV_AtObj(h, idx); 328 }; 329 330 /** 331 * get OID string from hexadecimal encoded value 332 * @name hextooidstr 333 * @memberOf ASN1HEX 334 * @function 335 * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value 336 * @return {String} OID string (ex. '1.2.3.4.567') 337 * @since asn1hex 1.1.5 338 */ 339 ASN1HEX.hextooidstr = function(hex) { 340 var zeroPadding = function(s, len) { 341 if (s.length >= len) return s; 342 return new Array(len - s.length + 1).join('0') + s; 343 }; 344 345 var a = []; 346 347 // a[0], a[1] 348 var hex0 = hex.substr(0, 2); 349 var i0 = parseInt(hex0, 16); 350 a[0] = new String(Math.floor(i0 / 40)); 351 a[1] = new String(i0 % 40); 352 353 // a[2]..a[n] 354 var hex1 = hex.substr(2); 355 var b = []; 356 for (var i = 0; i < hex1.length / 2; i++) { 357 b.push(parseInt(hex1.substr(i * 2, 2), 16)); 358 } 359 var c = []; 360 var cbin = ""; 361 for (var i = 0; i < b.length; i++) { 362 if (b[i] & 0x80) { 363 cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7); 364 } else { 365 cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7); 366 c.push(new String(parseInt(cbin, 2))); 367 cbin = ""; 368 } 369 } 370 371 var s = a.join("."); 372 if (c.length > 0) s = s + "." + c.join("."); 373 return s; 374 }; 375 376 /** 377 * get string of simple ASN.1 dump from hexadecimal ASN.1 data 378 * @name dump 379 * @memberOf ASN1HEX 380 * @function 381 * @param {String} hex hexadecmal string of ASN.1 data 382 * @param {Array} associative array of flags for dump (OPTION) 383 * @param {Number} idx string index for starting dump (OPTION) 384 * @param {String} indent string (OPTION) 385 * @return {String} string of simple ASN.1 dump 386 * @since jsrsasign 4.8.3 asn1hex 1.1.6 387 * @description 388 * This method will get an ASN.1 dump from 389 * hexadecmal string of ASN.1 DER encoded data. 390 * Here are features: 391 * <ul> 392 * <li>ommit long hexadecimal string</li> 393 * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li> 394 * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li> 395 * <li>automatic decode for implicit primitive context specific tag 396 * (good for X.509v3 extension value) 397 * <ul> 398 * <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li> 399 * <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag 400 * value will be encoded as utf8 string</li> 401 * <li>otherwise it shows as hexadecimal string</li> 402 * </ul> 403 * </li> 404 * </ul> 405 * @example 406 * // ASN.1 INTEGER 407 * ASN1HEX.dump('0203012345') 408 * ↓ 409 * INTEGER 012345 410 * 411 * // ASN.1 Object Identifier 412 * ASN1HEX.dump('06052b0e03021a') 413 * ↓ 414 * ObjectIdentifier sha1 (1 3 14 3 2 26) 415 * 416 * // ASN.1 SEQUENCE 417 * ASN1HEX.dump('3006020101020102') 418 * ↓ 419 * SEQUENCE 420 * INTEGER 01 421 * INTEGER 02 422 * 423 * // ASN.1 DUMP FOR X.509 CERTIFICATE 424 * ASN1HEX.dump(X509.pemToHex(certPEM)) 425 * ↓ 426 * SEQUENCE 427 * SEQUENCE 428 * [0] 429 * INTEGER 02 430 * INTEGER 0c009310d206dbe337553580118ddc87 431 * SEQUENCE 432 * ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11) 433 * NULL 434 * SEQUENCE 435 * SET 436 * SEQUENCE 437 * ObjectIdentifier countryName (2 5 4 6) 438 * PrintableString 'US' 439 * : 440 */ 441 ASN1HEX.dump = function(hex, flags, idx, indent) { 442 var _skipLongHex = function(hex, limitNumOctet) { 443 if (hex.length <= limitNumOctet * 2) { 444 return hex; 445 } else { 446 var s = hex.substr(0, limitNumOctet) + 447 "..(total " + hex.length / 2 + "bytes).." + 448 hex.substr(hex.length - limitNumOctet, limitNumOctet); 449 return s; 450 }; 451 }; 452 453 if (flags === undefined) flags = { "ommit_long_octet": 32 }; 454 if (idx === undefined) idx = 0; 455 if (indent === undefined) indent = ""; 456 var skipLongHex = flags.ommit_long_octet; 457 458 if (hex.substr(idx, 2) == "01") { 459 var v = ASN1HEX.getHexOfV_AtObj(hex, idx); 460 if (v == "00") { 461 return indent + "BOOLEAN FALSE\n"; 462 } else { 463 return indent + "BOOLEAN TRUE\n"; 464 } 465 } 466 if (hex.substr(idx, 2) == "02") { 467 var v = ASN1HEX.getHexOfV_AtObj(hex, idx); 468 return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n"; 469 } 470 if (hex.substr(idx, 2) == "03") { 471 var v = ASN1HEX.getHexOfV_AtObj(hex, idx); 472 return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n"; 473 } 474 if (hex.substr(idx, 2) == "04") { 475 var v = ASN1HEX.getHexOfV_AtObj(hex, idx); 476 if (ASN1HEX.isASN1HEX(v)) { 477 var s = indent + "OCTETSTRING, encapsulates\n"; 478 s = s + ASN1HEX.dump(v, flags, 0, indent + " "); 479 return s; 480 } else { 481 return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n"; 482 } 483 } 484 if (hex.substr(idx, 2) == "05") { 485 return indent + "NULL\n"; 486 } 487 if (hex.substr(idx, 2) == "06") { 488 var hV = ASN1HEX.getHexOfV_AtObj(hex, idx); 489 var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV); 490 var oidName = KJUR.asn1.x509.OID.oid2name(oidDot); 491 var oidSpc = oidDot.replace(/\./g, ' '); 492 if (oidName != '') { 493 return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n"; 494 } else { 495 return indent + "ObjectIdentifier (" + oidSpc + ")\n"; 496 } 497 } 498 if (hex.substr(idx, 2) == "0c") { 499 return indent + "UTF8String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n"; 500 } 501 if (hex.substr(idx, 2) == "13") { 502 return indent + "PrintableString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n"; 503 } 504 if (hex.substr(idx, 2) == "14") { 505 return indent + "TeletexString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n"; 506 } 507 if (hex.substr(idx, 2) == "16") { 508 return indent + "IA5String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n"; 509 } 510 if (hex.substr(idx, 2) == "17") { 511 return indent + "UTCTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n"; 512 } 513 if (hex.substr(idx, 2) == "18") { 514 return indent + "GeneralizedTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n"; 515 } 516 if (hex.substr(idx, 2) == "30") { 517 if (hex.substr(idx, 4) == "3000") { 518 return indent + "SEQUENCE {}\n"; 519 } 520 521 var s = indent + "SEQUENCE\n"; 522 var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx); 523 524 var flagsTemp = flags; 525 526 if ((aIdx.length == 2 || aIdx.length == 3) && 527 hex.substr(aIdx[0], 2) == "06" && 528 hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension 529 var oidHex = ASN1HEX.getHexOfV_AtObj(hex, aIdx[0]); 530 var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(oidHex); 531 var oidName = KJUR.asn1.x509.OID.oid2name(oidDot); 532 533 var flagsClone = JSON.parse(JSON.stringify(flags)); 534 flagsClone.x509ExtName = oidName; 535 flagsTemp = flagsClone; 536 } 537 538 for (var i = 0; i < aIdx.length; i++) { 539 s = s + ASN1HEX.dump(hex, flagsTemp, aIdx[i], indent + " "); 540 } 541 return s; 542 } 543 if (hex.substr(idx, 2) == "31") { 544 var s = indent + "SET\n"; 545 var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx); 546 for (var i = 0; i < aIdx.length; i++) { 547 s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + " "); 548 } 549 return s; 550 } 551 var tag = parseInt(hex.substr(idx, 2), 16); 552 if ((tag & 128) != 0) { // context specific 553 var tagNumber = tag & 31; 554 if ((tag & 32) != 0) { // structured tag 555 var s = indent + "[" + tagNumber + "]\n"; 556 var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx); 557 for (var i = 0; i < aIdx.length; i++) { 558 s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + " "); 559 } 560 return s; 561 } else { // primitive tag 562 var v = ASN1HEX.getHexOfV_AtObj(hex, idx); 563 if (v.substr(0, 8) == "68747470") { // http 564 v = hextoutf8(v); 565 } 566 if (flags.x509ExtName === "subjectAltName" && 567 tagNumber == 2) { 568 v = hextoutf8(v); 569 } 570 571 var s = indent + "[" + tagNumber + "] " + v + "\n"; 572 return s; 573 } 574 } 575 return indent + "UNKNOWN(" + hex.substr(idx, 2) + ") " + ASN1HEX.getHexOfV_AtObj(hex, idx) + "\n"; 576 }; 577 578 /** 579 * check wheather the string is ASN.1 hexadecimal string or not 580 * @name isASN1HEX 581 * @memberOf ASN1HEX 582 * @function 583 * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not 584 * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false 585 * @since jsrsasign 4.8.3 asn1hex 1.1.6 586 * @description 587 * This method checks wheather the argument 'hex' is a hexadecimal string of 588 * ASN.1 data or not. 589 * @example 590 * ASN1HEX.isASN1HEX('0203012345') → true // PROPER ASN.1 INTEGER 591 * ASN1HEX.isASN1HEX('0203012345ff') → false // TOO LONG VALUE 592 * ASN1HEX.isASN1HEX('02030123') → false // TOO SHORT VALUE 593 * ASN1HEX.isASN1HEX('fa3bcd') → false // WRONG FOR ASN.1 594 */ 595 ASN1HEX.isASN1HEX = function(hex) { 596 if (hex.length % 2 == 1) return false; 597 598 var intL = ASN1HEX.getIntOfL_AtObj(hex, 0); 599 var tV = hex.substr(0, 2); 600 var lV = ASN1HEX.getHexOfL_AtObj(hex, 0); 601 var hVLength = hex.length - tV.length - lV.length; 602 if (hVLength == intL * 2) return true; 603 604 return false; 605 }; 606