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