1 /* asn1hex-1.2.9.js (c) 2012-2021 Kenji Urushima | kjur.github.com/jsrsasign/license
  2  */
  3 /*
  4  * asn1hex.js - Hexadecimal represented ASN.1 string library
  5  *
  6  * Copyright (c) 2010-2021 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 10.1.13 asn1hex 1.2.9 (2021-Mar-07)
 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 integer value from ASN.1 V(value) of Integer or BitString<br/>
595  * @name getInt
596  * @memberOf ASN1HEX
597  * @function
598  * @param {String} h hexadecimal string
599  * @param {Number} idx string index in h to get ASN.1 DER Integer or BitString
600  * @param {Object} errorReturn (OPTION) error return value (DEFAULT: -1)
601  * @return {Number} ASN.1 DER Integer or BitString value
602  * @since jsrsasign 10.1.0 asn1hex 1.2.7
603  * @see bitstrtoint
604  *
605  * @example
606  * ASN1HEX.getInt("xxxx020103xxxxxx", 4) &rarr 3 // DER Integer
607  * ASN1HEX.getInt("xxxx03020780xxxxxx", 4) &rarr 1 // DER BitStringx
608  * ASN1HEX.getInt("xxxx030203c8xxxxxx", 4) &rarr 25 // DER BitStringx
609  */
610 ASN1HEX.getInt = function(h, idx, errorReturn) {
611     if (errorReturn == undefined) errorReturn = -1;
612     try {
613 	var hTag = h.substr(idx, 2);
614 	if (hTag != "02" && hTag != "03") return errorReturn;
615 	var hV = ASN1HEX.getV(h, idx);
616 	if (hTag == "02") {
617 	    return parseInt(hV, 16);
618 	} else {
619 	    return bitstrtoint(hV);
620 	}
621     } catch(ex) {
622 	return errorReturn;
623     }
624 };
625 
626 /**
627  * get object identifier string from ASN.1 V(value)<br/>
628  * @name getOID
629  * @memberOf ASN1HEX
630  * @function
631  * @param {String} h hexadecimal string
632  * @param {Number} idx string index in h to get ASN.1 DER ObjectIdentifier
633  * @param {Object} errorReturn (OPTION) error return value (DEFAULT: null)
634  * @return {String} object identifier string (ex. "1.2.3.4")
635  * @since jsrsasign 10.1.0 asn1hex 1.2.7
636  *
637  * @example
638  * ASN1HEX.getInt("xxxx06032a0304xxxxxx", 4) &rarr "1.2.3.4"
639  */
640 ASN1HEX.getOID = function(h, idx, errorReturn) {
641     if (errorReturn == undefined) errorReturn = null;
642     try {
643 	if (h.substr(idx, 2) != "06") return errorReturn;
644 	var hOID = ASN1HEX.getV(h, idx);
645 	return hextooid(hOID);
646     } catch(ex) {
647 	return errorReturn;
648     }
649 };
650 
651 /**
652  * get object identifier name from ASN.1 V(value)<br/>
653  * @name getOIDName
654  * @memberOf ASN1HEX
655  * @function
656  * @param {String} h hexadecimal string
657  * @param {Number} idx string index in h to get ASN.1 DER ObjectIdentifier
658  * @param {Object} errorReturn (OPTION) error return value (DEFAULT: null)
659  * @return {String} object identifier name (ex. "sha256") oir OID string
660  * @since jsrsasign 10.1.0 asn1hex 1.2.7
661  *
662  * @description
663  * This static method returns object identifier name such as "sha256"
664  * if registered. If not registered, it returns OID string. 
665  * (ex. "1.2.3.4")
666  *
667  * @example
668  * ASN1HEX.getOIDName("xxxx0609608648016503040201xxxxxx", 4) &rarr "sha256"
669  * ASN1HEX.getOIDName("xxxx06032a0304xxxxxx", 4) &rarr "1.2.3.4"
670  */
671 ASN1HEX.getOIDName = function(h, idx, errorReturn) {
672     if (errorReturn == undefined) errorReturn = null;
673     try {
674 	var oid = ASN1HEX.getOID(h, idx, errorReturn);
675 	if (oid == errorReturn) return errorReturn;
676 	var name = KJUR.asn1.x509.OID.oid2name(oid);
677 	if (name == '') return oid;
678 	return name;
679     } catch(ex) {
680 	return errorReturn;
681     }
682 };
683 
684 /**
685  * get raw string from ASN.1 V(value)<br/>
686  * @name getString
687  * @memberOf ASN1HEX
688  * @function
689  * @param {String} h hexadecimal string
690  * @param {Number} idx string index in h to get any ASN.1 DER String
691  * @param {Object} errorReturn (OPTION) error return value (DEFAULT: null)
692  * @return {String} raw string
693  * @since jsrsasign 10.1.3 asn1hex 1.2.8
694  *
695  * @description
696  * This static method returns a raw string from
697  * any ASN.1 DER primitives.
698  *
699  * @example
700  * ASN1HEX.getString("xxxx1303616161xxxxxx", 4) &rarr "aaa"
701  * ASN1HEX.getString("xxxx0c03616161xxxxxx", 4) &rarr "aaa"
702  */
703 ASN1HEX.getString = function(h, idx, errorReturn) {
704     if (errorReturn == undefined) errorReturn = null;
705     try {
706 	var hV = ASN1HEX.getV(h, idx);
707 	return hextorstr(hV);
708     } catch(ex) {
709 	return errorReturn;
710     }
711 };
712 
713 /**
714  * get OID string from hexadecimal encoded value<br/>
715  * @name hextooidstr
716  * @memberOf ASN1HEX
717  * @function
718  * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value
719  * @return {String} OID string (ex. '1.2.3.4.567')
720  * @since asn1hex 1.1.5
721  * @see {@link KJUR.asn1.ASN1Util.oidIntToHex}
722  * @description
723  * This static method converts from ASN.1 DER encoded 
724  * hexadecimal object identifier value to dot concatinated OID value.
725  * {@link KJUR.asn1.ASN1Util.oidIntToHex} is a reverse function of this.
726  * @example
727  * ASN1HEX.hextooidstr("550406") → "2.5.4.6"
728  */
729 ASN1HEX.hextooidstr = function(hex) {
730     var zeroPadding = function(s, len) {
731         if (s.length >= len) return s;
732         return new Array(len - s.length + 1).join('0') + s;
733     };
734 
735     var a = [];
736 
737     // a[0], a[1]
738     var hex0 = hex.substr(0, 2);
739     var i0 = parseInt(hex0, 16);
740     a[0] = new String(Math.floor(i0 / 40));
741     a[1] = new String(i0 % 40);
742 
743     // a[2]..a[n]
744    var hex1 = hex.substr(2);
745     var b = [];
746     for (var i = 0; i < hex1.length / 2; i++) {
747     b.push(parseInt(hex1.substr(i * 2, 2), 16));
748     }
749     var c = [];
750     var cbin = "";
751     for (var i = 0; i < b.length; i++) {
752         if (b[i] & 0x80) {
753             cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
754         } else {
755             cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
756             c.push(new String(parseInt(cbin, 2)));
757             cbin = "";
758         }
759     }
760 
761     var s = a.join(".");
762     if (c.length > 0) s = s + "." + c.join(".");
763     return s;
764 };
765 
766 /**
767  * get string of simple ASN.1 dump from hexadecimal ASN.1 data<br/>
768  * @name dump
769  * @memberOf ASN1HEX
770  * @function
771  * @param {Object} hexOrObj hexadecmal string of ASN.1 data or ASN1Object object
772  * @param {Array} flags associative array of flags for dump (OPTION)
773  * @param {Number} idx string index for starting dump (OPTION)
774  * @param {String} indent indent string (OPTION)
775  * @return {String} string of simple ASN.1 dump
776  * @since jsrsasign 4.8.3 asn1hex 1.1.6
777  * @description
778  * This method will get an ASN.1 dump from
779  * hexadecmal string of ASN.1 DER encoded data.
780  * Here are features:
781  * <ul>
782  * <li>ommit long hexadecimal string</li>
783  * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li>
784  * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li>
785  * <li>automatic decode for implicit primitive context specific tag 
786  * (good for X.509v3 extension value)
787  *   <ul>
788  *   <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li>
789  *   <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag
790  *   value will be encoded as utf8 string</li>
791  *   <li>otherwise it shows as hexadecimal string</li>
792  *   </ul>
793  * </li>
794  * </ul>
795  * NOTE1: Argument {@link KJUR.asn1.ASN1Object} object is supported since
796  * jsrsasign 6.2.4 asn1hex 1.0.8
797  * @example
798  * // 1) ASN.1 INTEGER
799  * ASN1HEX.dump('0203012345')
800  * ↓
801  * INTEGER 012345
802  *
803  * // 2) ASN.1 Object Identifier
804  * ASN1HEX.dump('06052b0e03021a')
805  * ↓
806  * ObjectIdentifier sha1 (1 3 14 3 2 26)
807  *
808  * // 3) ASN.1 SEQUENCE
809  * ASN1HEX.dump('3006020101020102')
810  * ↓
811  * SEQUENCE
812  *   INTEGER 01
813  *   INTEGER 02
814  *
815  * // 4) ASN.1 SEQUENCE since jsrsasign 6.2.4
816  * o = KJUR.asn1.ASN1Util.newObject({seq: [{int: 1}, {int: 2}]});
817  * ASN1HEX.dump(o)
818  * ↓
819  * SEQUENCE
820  *   INTEGER 01
821  *   INTEGER 02
822  * // 5) ASN.1 DUMP FOR X.509 CERTIFICATE
823  * ASN1HEX.dump(pemtohex(certPEM))
824  * ↓
825  * SEQUENCE
826  *   SEQUENCE
827  *     [0]
828  *       INTEGER 02
829  *     INTEGER 0c009310d206dbe337553580118ddc87
830  *     SEQUENCE
831  *       ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11)
832  *       NULL
833  *     SEQUENCE
834  *       SET
835  *         SEQUENCE
836  *           ObjectIdentifier countryName (2 5 4 6)
837  *           PrintableString 'US'
838  *             :
839  */
840 ASN1HEX.dump = function(hexOrObj, flags, idx, indent) {
841     var _ASN1HEX = ASN1HEX;
842     var _getV = _ASN1HEX.getV;
843     var _dump = _ASN1HEX.dump;
844     var _getChildIdx = _ASN1HEX.getChildIdx;
845 
846     var hex = hexOrObj;
847     if (hexOrObj instanceof KJUR.asn1.ASN1Object)
848 	hex = hexOrObj.getEncodedHex();
849 
850     var _skipLongHex = function(hex, limitNumOctet) {
851 	if (hex.length <= limitNumOctet * 2) {
852 	    return hex;
853 	} else {
854 	    var s = hex.substr(0, limitNumOctet) + 
855 		    "..(total " + hex.length / 2 + "bytes).." +
856 		    hex.substr(hex.length - limitNumOctet, limitNumOctet);
857 	    return s;
858 	};
859     };
860 
861     if (flags === undefined) flags = { "ommit_long_octet": 32 };
862     if (idx === undefined) idx = 0;
863     if (indent === undefined) indent = "";
864     var skipLongHex = flags.ommit_long_octet;
865 
866     var tag = hex.substr(idx, 2);
867 
868     if (tag == "01") {
869 	var v = _getV(hex, idx);
870 	if (v == "00") {
871 	    return indent + "BOOLEAN FALSE\n";
872 	} else {
873 	    return indent + "BOOLEAN TRUE\n";
874 	}
875     }
876     if (tag == "02") {
877 	var v = _getV(hex, idx);
878         return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n";
879     }
880     if (tag == "03") {
881 	var v = _getV(hex, idx);
882 	if (_ASN1HEX.isASN1HEX(v.substr(2))) {
883   	    var s = indent + "BITSTRING, encapsulates\n";
884             s = s + _dump(v.substr(2), flags, 0, indent + "  ");
885             return s;
886 	} else {
887             return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n";
888 	}
889     }
890     if (tag == "04") {
891 	var v = _getV(hex, idx);
892 	if (_ASN1HEX.isASN1HEX(v)) {
893 	    var s = indent + "OCTETSTRING, encapsulates\n";
894 	    s = s + _dump(v, flags, 0, indent + "  ");
895 	    return s;
896 	} else {
897 	    return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n";
898 	}
899     }
900     if (tag == "05") {
901 	return indent + "NULL\n";
902     }
903     if (tag == "06") {
904 	var hV = _getV(hex, idx);
905         var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV);
906         var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
907 	var oidSpc = oidDot.replace(/\./g, ' ');
908         if (oidName != '') {
909   	    return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n";
910 	} else {
911   	    return indent + "ObjectIdentifier (" + oidSpc + ")\n";
912 	}
913     }
914     if (tag == "0a") {
915 	return indent + "ENUMERATED " + parseInt(_getV(hex, idx)) + "\n";
916     }
917     if (tag == "0c") {
918 	return indent + "UTF8String '" + hextoutf8(_getV(hex, idx)) + "'\n";
919     }
920     if (tag == "13") {
921 	return indent + "PrintableString '" + hextoutf8(_getV(hex, idx)) + "'\n";
922     }
923     if (tag == "14") {
924 	return indent + "TeletexString '" + hextoutf8(_getV(hex, idx)) + "'\n";
925     }
926     if (tag == "16") {
927 	return indent + "IA5String '" + hextoutf8(_getV(hex, idx)) + "'\n";
928     }
929     if (tag == "17") {
930 	return indent + "UTCTime " + hextoutf8(_getV(hex, idx)) + "\n";
931     }
932     if (tag == "18") {
933 	return indent + "GeneralizedTime " + hextoutf8(_getV(hex, idx)) + "\n";
934     }
935     if (tag == "1a") {
936 	return indent + "VisualString '" + hextoutf8(_getV(hex, idx)) + "'\n";
937     }
938     if (tag == "1e") {
939 	return indent + "BMPString '" + ucs2hextoutf8(_getV(hex, idx)) + "'\n";
940     }
941     if (tag == "30") {
942 	if (hex.substr(idx, 4) == "3000") {
943 	    return indent + "SEQUENCE {}\n";
944 	}
945 
946 	var s = indent + "SEQUENCE\n";
947 	var aIdx = _getChildIdx(hex, idx);
948 
949 	var flagsTemp = flags;
950 	
951 	if ((aIdx.length == 2 || aIdx.length == 3) &&
952 	    hex.substr(aIdx[0], 2) == "06" &&
953 	    hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension
954 	    var oidName = _ASN1HEX.oidname(_getV(hex, aIdx[0]));
955 	    var flagsClone = JSON.parse(JSON.stringify(flags));
956 	    flagsClone.x509ExtName = oidName;
957 	    flagsTemp = flagsClone;
958 	}
959 	
960 	for (var i = 0; i < aIdx.length; i++) {
961 	    s = s + _dump(hex, flagsTemp, aIdx[i], indent + "  ");
962 	}
963 	return s;
964     }
965     if (tag == "31") {
966 	var s = indent + "SET\n";
967 	var aIdx = _getChildIdx(hex, idx);
968 	for (var i = 0; i < aIdx.length; i++) {
969 	    s = s + _dump(hex, flags, aIdx[i], indent + "  ");
970 	}
971 	return s;
972     }
973     var tag = parseInt(tag, 16);
974     if ((tag & 128) != 0) { // context specific 
975 	var tagNumber = tag & 31;
976 	if ((tag & 32) != 0) { // structured tag
977 	    var s = indent + "[" + tagNumber + "]\n";
978 	    var aIdx = _getChildIdx(hex, idx);
979 	    for (var i = 0; i < aIdx.length; i++) {
980 		s = s + _dump(hex, flags, aIdx[i], indent + "  ");
981 	    }
982 	    return s;
983 	} else { // primitive tag
984 	    var v = _getV(hex, idx);
985 	    if (ASN1HEX.isASN1HEX(v)) {
986 		var s = indent + "[" + tagNumber + "]\n";
987 		s = s + _dump(v, flags, 0, indent + "  ");
988 		return s;
989 	    } else if (v.substr(0, 8) == "68747470") { // http
990 		v = hextoutf8(v);
991 	    } else if (flags.x509ExtName === "subjectAltName" &&
992 		       tagNumber == 2) {
993 		v = hextoutf8(v);
994 	    }
995 	    // else if (ASN1HEX.isASN1HEX(v))
996 
997 	    var s = indent + "[" + tagNumber + "] " + v + "\n";
998 	    return s;
999 	}
1000     }
1001     return indent + "UNKNOWN(" + tag + ") " + 
1002 	   _getV(hex, idx) + "\n";
1003 };
1004 
1005 /**
1006  * check if a hexadecimal tag is a specified ASN.1 context specific tag
1007  * @name isContextTag
1008  * @memberOf ASN1HEX
1009  * @function
1010  * @param {hTag} hex string of a hexadecimal ASN.1 tag consists by two characters (e.x. "a0")
1011  * @param {sTag} context specific tag in string represention (OPTION) (e.x. "[0]")
1012  * @return {Boolean} true if hTag is a ASN.1 context specific tag specified by sTag value.
1013  * @since jsrsasign 8.0.21 asn1hex 1.2.2
1014  * @description
1015  * This method checks if a hexadecimal tag is a specified ASN.1 context specific tag.
1016  * Structured and non-structured type of tag have the same string representation
1017  * of context specific tag. For example tag "a0" and "80" have the same string
1018  * representation "[0]".
1019  * The sTag has a range from from "[0]" to "[31]".
1020  * @example
1021  * ASN1HEX.isContextTag('a0', '[0]') → true // structured
1022  * ASN1HEX.isContextTag('a1', '[1]') → true // structured
1023  * ASN1HEX.isContextTag('a2', '[2]') → true // structured
1024  * ASN1HEX.isContextTag('80', '[0]') → true // non structured
1025  * ASN1HEX.isContextTag('81', '[1]') → true // non structured
1026  * ASN1HEX.isContextTag('82', '[2]') → true // non structured
1027  * ASN1HEX.isContextTag('a0', '[3]') → false
1028  * ASN1HEX.isContextTag('80', '[15]') → false
1029  *
1030  * ASN.1 tag bits
1031  * 12345679
1032  * ++        tag class(universal:00, context specific:10)
1033  *   +       structured:1, primitive:0
1034  *    +++++  tag number (0 - 31)
1035  */
1036 ASN1HEX.isContextTag = function(hTag, sTag) {
1037     hTag = hTag.toLowerCase();
1038     var ihtag, istag;
1039 
1040     try {
1041 	ihtag = parseInt(hTag, 16);
1042     } catch (ex) {
1043 	return -1;
1044     }
1045 	
1046     if (sTag === undefined) {
1047 	if ((ihtag & 192) == 128) {
1048 	    return true;
1049 	} else {
1050 	    return false;
1051 	}
1052     }
1053 
1054     try {
1055 	var result = sTag.match(/^\[[0-9]+\]$/);
1056 	if (result == null) return false;
1057 	istag = parseInt(sTag.substr(1,sTag.length - 1), 10);
1058 	if (istag > 31) return false;
1059 	if (((ihtag & 192) == 128) &&   // ihtag & b11000000 == b10000000
1060 	    ((ihtag & 31) == istag)) {  // ihtag & b00011111 == istag (0-31)
1061 	    return true;
1062 	}
1063 	return false;
1064     } catch (ex) {
1065 	return false;
1066     }
1067 };
1068 
1069 /**
1070  * simple ASN.1 DER hexadecimal string checker
1071  * @name isASN1HEX
1072  * @memberOf ASN1HEX
1073  * @function
1074  * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not
1075  * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false
1076  * @since jsrsasign 4.8.3 asn1hex 1.1.6
1077  * @description
1078  * This method checks wheather the argument 'hex' is a hexadecimal string of
1079  * ASN.1 data or not.
1080  * @example
1081  * ASN1HEX.isASN1HEX('0203012345') → true // PROPER ASN.1 INTEGER
1082  * ASN1HEX.isASN1HEX('0203012345ff') → false // TOO LONG VALUE
1083  * ASN1HEX.isASN1HEX('02030123') → false // TOO SHORT VALUE
1084  * ASN1HEX.isASN1HEX('fa3bcd') → false // WRONG FOR ASN.1
1085  */
1086 ASN1HEX.isASN1HEX = function(hex) {
1087     var _ASN1HEX = ASN1HEX;
1088     if (hex.length % 2 == 1) return false;
1089 
1090     var intL = _ASN1HEX.getVblen(hex, 0);
1091     var hT = hex.substr(0, 2);
1092     var hL = _ASN1HEX.getL(hex, 0);
1093     var hVLength = hex.length - hT.length - hL.length;
1094     if (hVLength == intL * 2) return true;
1095 
1096     return false;
1097 };
1098 
1099 /**
1100  * strict ASN.1 DER hexadecimal string checker
1101  * @name checkStrictDER
1102  * @memberOf ASN1HEX
1103  * @function
1104  * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not
1105  * @return unspecified
1106  * @since jsrsasign 8.0.19 asn1hex 1.2.1
1107  * @throws Error when malformed ASN.1 DER hexadecimal string
1108  * @description
1109  * This method checks wheather the argument 'hex' is a hexadecimal string of
1110  * ASN.1 data or not. If the argument is not DER string, this 
1111  * raise an exception.
1112  * @example
1113  * ASN1HEX.checkStrictDER('0203012345') → NO EXCEPTION FOR PROPER ASN.1 INTEGER
1114  * ASN1HEX.checkStrictDER('0203012345ff') → RAISE EXCEPTION FOR TOO LONG VALUE
1115  * ASN1HEX.checkStrictDER('02030123') → false RAISE EXCEPITON FOR TOO SHORT VALUE
1116  * ASN1HEX.checkStrictDER('fa3bcd') → false RAISE EXCEPTION FOR WRONG ASN.1
1117  */
1118 ASN1HEX.checkStrictDER = function(h, idx, maxHexLen, maxByteLen, maxLbyteLen) {
1119     var _ASN1HEX = ASN1HEX;
1120 
1121     if (maxHexLen === undefined) {
1122 	// 1. hex string check
1123 	if (typeof h != "string") throw new Error("not hex string");
1124 	h = h.toLowerCase();
1125 	if (! KJUR.lang.String.isHex(h)) throw new Error("not hex string");
1126 
1127 	// 2. set max if needed
1128 	// max length of hexadecimal string
1129 	maxHexLen = h.length;
1130 	// max length of octets
1131 	maxByteLen = h.length / 2;
1132 	// max length of L octets of TLV
1133 	if (maxByteLen < 0x80) {
1134 	    maxLbyteLen = 1;
1135 	} else {
1136 	    maxLbyteLen = Math.ceil(maxByteLen.toString(16)) + 1;
1137 	}
1138     }
1139     //console.log(maxHexLen + ":" + maxByteLen + ":" + maxLbyteLen);
1140 
1141     // 3. check if L(length) string not exceeds maxLbyteLen
1142     var hL = _ASN1HEX.getL(h, idx);
1143     if (hL.length > maxLbyteLen * 2)
1144 	throw new Error("L of TLV too long: idx=" + idx);
1145 
1146     // 4. check if V(value) octet length (i.e. L(length) value) 
1147     //    not exceeds maxByteLen
1148     var vblen = _ASN1HEX.getVblen(h, idx);
1149     if (vblen > maxByteLen) 
1150 	throw new Error("value of L too long than hex: idx=" + idx);
1151 
1152     // 5. check V string length and L's value are the same
1153     var hTLV = _ASN1HEX.getTLV(h, idx);
1154     var hVLength = 
1155 	hTLV.length - 2 - _ASN1HEX.getL(h, idx).length;
1156     if (hVLength !== (vblen * 2))
1157 	throw new Error("V string length and L's value not the same:" +
1158 		        hVLength + "/" + (vblen * 2));
1159 
1160     // 6. check appending garbled string
1161     if (idx === 0) {
1162 	if (h.length != hTLV.length)
1163 	    throw new Error("total length and TLV length unmatch:" +
1164 			    h.length + "!=" + hTLV.length);
1165     }
1166 
1167     // 7. check if there isn't prepending zeros in DER INTEGER value
1168     var hT = h.substr(idx, 2);
1169     if (hT === '02') {
1170 	var vidx = _ASN1HEX.getVidx(h, idx);
1171 	// check if DER INTEGER VALUE have least leading zeros 
1172 	// for two's complement
1173 	// GOOD - 3fabde... 008fad...
1174 	// BAD  - 000012... 007fad...
1175 	if (h.substr(vidx, 2) == "00" && h.charCodeAt(vidx + 2) < 56) // '8'=56
1176 	    throw new Error("not least zeros for DER INTEGER");
1177     }
1178 
1179     // 8. check if all of elements in a structured item are conformed to
1180     //    strict DER encoding rules.
1181     if (parseInt(hT, 16) & 32) { // structured tag?
1182 	var intL = _ASN1HEX.getVblen(h, idx);
1183 	var sum = 0;
1184 	var aIdx = _ASN1HEX.getChildIdx(h, idx);
1185 	for (var i = 0; i < aIdx.length; i++) {
1186 	    var tlv = _ASN1HEX.getTLV(h, aIdx[i]);
1187 	    sum += tlv.length;
1188 	    _ASN1HEX.checkStrictDER(h, aIdx[i], 
1189 				   maxHexLen, maxByteLen, maxLbyteLen);
1190 	}
1191 	if ((intL * 2) != sum)
1192 	    throw new Error("sum of children's TLV length and L unmatch: " +
1193 			    (intL * 2) + "!=" + sum);
1194     }
1195 };
1196 
1197 /**
1198  * get hexacedimal string from PEM format data<br/>
1199  * @name oidname
1200  * @memberOf ASN1HEX
1201  * @function
1202  * @param {String} oidDotOrHex number dot notation(i.e. 1.2.3) or hexadecimal string for OID
1203  * @return {String} name for OID
1204  * @since jsrsasign 7.2.0 asn1hex 1.1.11
1205  * @description
1206  * This static method gets a OID name for
1207  * a specified string of number dot notation (i.e. 1.2.3) or
1208  * hexadecimal string.
1209  * @example
1210  * ASN1HEX.oidname("2.5.29.37") → extKeyUsage
1211  * ASN1HEX.oidname("551d25") → extKeyUsage
1212  * ASN1HEX.oidname("0.1.2.3") → 0.1.2.3 // unknown
1213  */
1214 ASN1HEX.oidname = function(oidDotOrHex) {
1215     var _KJUR_asn1 = KJUR.asn1;
1216     if (KJUR.lang.String.isHex(oidDotOrHex))
1217 	oidDotOrHex = _KJUR_asn1.ASN1Util.oidHexToInt(oidDotOrHex);
1218     var name = _KJUR_asn1.x509.OID.oid2name(oidDotOrHex);
1219     if (name === "") name = oidDotOrHex;
1220     return name;
1221 };
1222 
1223