1 /*! asn1hex-1.1.4.js (c) 2012-2013 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * asn1hex.js - Hexadecimal represented ASN.1 string library 5 * 6 * Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * http://kjur.github.com/jsrsasign/license/ 10 * 11 * The above copyright and license notice shall be 12 * included in all copies or substantial portions of the Software. 13 */ 14 15 /** 16 * @fileOverview 17 * @name asn1hex-1.1.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version asn1hex 1.1.4 (2013-Oct-02) 20 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a> 21 */ 22 23 /* 24 * MEMO: 25 * f('3082025b02...', 2) ... 82025b ... 3bytes 26 * f('020100', 2) ... 01 ... 1byte 27 * f('0203001...', 2) ... 03 ... 1byte 28 * f('02818003...', 2) ... 8180 ... 2bytes 29 * f('3080....0000', 2) ... 80 ... -1 30 * 31 * Requirements: 32 * - ASN.1 type octet length MUST be 1. 33 * (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...) 34 */ 35 36 /** 37 * ASN.1 DER encoded hexadecimal string utility class 38 * @name ASN1HEX 39 * @class ASN.1 DER encoded hexadecimal string utility class 40 * @since jsrsasign 1.1 41 */ 42 var ASN1HEX = new function() { 43 /** 44 * get byte length for ASN.1 L(length) bytes 45 * @name getByteLengthOfL_AtObj 46 * @memberOf ASN1HEX 47 * @function 48 * @param {String} s hexadecimal string of ASN.1 DER encoded data 49 * @param {Number} pos string index 50 * @return byte length for ASN.1 L(length) bytes 51 */ 52 this.getByteLengthOfL_AtObj = function(s, pos) { 53 if (s.substring(pos + 2, pos + 3) != '8') return 1; 54 var i = parseInt(s.substring(pos + 3, pos + 4)); 55 if (i == 0) return -1; // length octet '80' indefinite length 56 if (0 < i && i < 10) return i + 1; // including '8?' octet; 57 return -2; // malformed format 58 }; 59 60 /** 61 * get hexadecimal string for ASN.1 L(length) bytes 62 * @name getHexOfL_AtObj 63 * @memberOf ASN1HEX 64 * @function 65 * @param {String} s hexadecimal string of ASN.1 DER encoded data 66 * @param {Number} pos string index 67 * @return {String} hexadecimal string for ASN.1 L(length) bytes 68 */ 69 this.getHexOfL_AtObj = function(s, pos) { 70 var len = this.getByteLengthOfL_AtObj(s, pos); 71 if (len < 1) return ''; 72 return s.substring(pos + 2, pos + 2 + len * 2); 73 }; 74 75 // getting ASN.1 length value at the position 'idx' of 76 // hexa decimal string 's'. 77 // 78 // f('3082025b02...', 0) ... 82025b ... ??? 79 // f('020100', 0) ... 01 ... 1 80 // f('0203001...', 0) ... 03 ... 3 81 // f('02818003...', 0) ... 8180 ... 128 82 /** 83 * get integer value of ASN.1 length for ASN.1 data 84 * @name getIntOfL_AtObj 85 * @memberOf ASN1HEX 86 * @function 87 * @param {String} s hexadecimal string of ASN.1 DER encoded data 88 * @param {Number} pos string index 89 * @return ASN.1 L(length) integer value 90 */ 91 this.getIntOfL_AtObj = function(s, pos) { 92 var hLength = this.getHexOfL_AtObj(s, pos); 93 if (hLength == '') return -1; 94 var bi; 95 if (parseInt(hLength.substring(0, 1)) < 8) { 96 bi = new BigInteger(hLength, 16); 97 } else { 98 bi = new BigInteger(hLength.substring(2), 16); 99 } 100 return bi.intValue(); 101 }; 102 103 /** 104 * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'. 105 * @name getStartPosOfV_AtObj 106 * @memberOf ASN1HEX 107 * @function 108 * @param {String} s hexadecimal string of ASN.1 DER encoded data 109 * @param {Number} pos string index 110 */ 111 this.getStartPosOfV_AtObj = function(s, pos) { 112 var l_len = this.getByteLengthOfL_AtObj(s, pos); 113 if (l_len < 0) return l_len; 114 return pos + (l_len + 1) * 2; 115 }; 116 117 /** 118 * get hexadecimal string of ASN.1 V(value) 119 * @name getHexOfV_AtObj 120 * @memberOf ASN1HEX 121 * @function 122 * @param {String} s hexadecimal string of ASN.1 DER encoded data 123 * @param {Number} pos string index 124 * @return {String} hexadecimal string of ASN.1 value. 125 */ 126 this.getHexOfV_AtObj = function(s, pos) { 127 var pos1 = this.getStartPosOfV_AtObj(s, pos); 128 var len = this.getIntOfL_AtObj(s, pos); 129 return s.substring(pos1, pos1 + len * 2); 130 }; 131 132 /** 133 * get hexadecimal string of ASN.1 TLV at 134 * @name getHexOfTLV_AtObj 135 * @memberOf ASN1HEX 136 * @function 137 * @param {String} s hexadecimal string of ASN.1 DER encoded data 138 * @param {Number} pos string index 139 * @return {String} hexadecimal string of ASN.1 TLV. 140 * @since 1.1 141 */ 142 this.getHexOfTLV_AtObj = function(s, pos) { 143 var hT = s.substr(pos, 2); 144 var hL = this.getHexOfL_AtObj(s, pos); 145 var hV = this.getHexOfV_AtObj(s, pos); 146 return hT + hL + hV; 147 }; 148 149 /** 150 * get next sibling starting index for ASN.1 object string 151 * @name getPosOfNextSibling_AtObj 152 * @memberOf ASN1HEX 153 * @function 154 * @param {String} s hexadecimal string of ASN.1 DER encoded data 155 * @param {Number} pos string index 156 * @return next sibling starting index for ASN.1 object string 157 */ 158 this.getPosOfNextSibling_AtObj = function(s, pos) { 159 var pos1 = this.getStartPosOfV_AtObj(s, pos); 160 var len = this.getIntOfL_AtObj(s, pos); 161 return pos1 + len * 2; 162 }; 163 164 /** 165 * get array of indexes of child ASN.1 objects 166 * @name getPosArrayOfChildren_AtObj 167 * @memberOf ASN1HEX 168 * @function 169 * @param {String} s hexadecimal string of ASN.1 DER encoded data 170 * @param {Number} start string index of ASN.1 object 171 * @return {Array of Number} array of indexes for childen of ASN.1 objects 172 */ 173 this.getPosArrayOfChildren_AtObj = function(h, pos) { 174 var a = new Array(); 175 var p0 = this.getStartPosOfV_AtObj(h, pos); 176 a.push(p0); 177 178 var len = this.getIntOfL_AtObj(h, pos); 179 var p = p0; 180 var k = 0; 181 while (1) { 182 var pNext = this.getPosOfNextSibling_AtObj(h, p); 183 if (pNext == null || (pNext - p0 >= (len * 2))) break; 184 if (k >= 200) break; 185 186 a.push(pNext); 187 p = pNext; 188 189 k++; 190 } 191 192 return a; 193 }; 194 195 /** 196 * get string index of nth child object of ASN.1 object refered by h, idx 197 * @name getNthChildIndex_AtObj 198 * @memberOf ASN1HEX 199 * @function 200 * @param {String} h hexadecimal string of ASN.1 DER encoded data 201 * @param {Number} idx start string index of ASN.1 object 202 * @param {Number} nth for child 203 * @return {Number} string index of nth child. 204 * @since 1.1 205 */ 206 this.getNthChildIndex_AtObj = function(h, idx, nth) { 207 var a = this.getPosArrayOfChildren_AtObj(h, idx); 208 return a[nth]; 209 }; 210 211 // ========== decendant methods ============================== 212 /** 213 * get string index of nth child object of ASN.1 object refered by h, idx 214 * @name getDecendantIndexByNthList 215 * @memberOf ASN1HEX 216 * @function 217 * @param {String} h hexadecimal string of ASN.1 DER encoded data 218 * @param {Number} currentIndex start string index of ASN.1 object 219 * @param {Array of Number} nthList array list of nth 220 * @return {Number} string index refered by nthList 221 * @since 1.1 222 * @example 223 * The "nthList" is a index list of structured ASN.1 object 224 * reference. Here is a sample structure and "nthList"s which 225 * refers each objects. 226 * 227 * SQUENCE - [0] 228 * SEQUENCE - [0, 0] 229 * IA5STRING 000 - [0, 0, 0] 230 * UTF8STRING 001 - [0, 0, 1] 231 * SET - [0, 1] 232 * IA5STRING 010 - [0, 1, 0] 233 * UTF8STRING 011 - [0, 1, 1] 234 */ 235 this.getDecendantIndexByNthList = function(h, currentIndex, nthList) { 236 if (nthList.length == 0) { 237 return currentIndex; 238 } 239 var firstNth = nthList.shift(); 240 var a = this.getPosArrayOfChildren_AtObj(h, currentIndex); 241 return this.getDecendantIndexByNthList(h, a[firstNth], nthList); 242 }; 243 244 /** 245 * get hexadecimal string of ASN.1 TLV refered by current index and nth index list. 246 * @name getDecendantHexTLVByNthList 247 * @memberOf ASN1HEX 248 * @function 249 * @param {String} h hexadecimal string of ASN.1 DER encoded data 250 * @param {Number} currentIndex start string index of ASN.1 object 251 * @param {Array of Number} nthList array list of nth 252 * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList 253 * @since 1.1 254 */ 255 this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) { 256 var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList); 257 return this.getHexOfTLV_AtObj(h, idx); 258 }; 259 260 /** 261 * get hexadecimal string of ASN.1 V refered by current index and nth index list. 262 * @name getDecendantHexVByNthList 263 * @memberOf ASN1HEX 264 * @function 265 * @param {String} h hexadecimal string of ASN.1 DER encoded data 266 * @param {Number} currentIndex start string index of ASN.1 object 267 * @param {Array of Number} nthList array list of nth 268 * @return {Number} hexadecimal string of ASN.1 V refered by nthList 269 * @since 1.1 270 */ 271 this.getDecendantHexVByNthList = function(h, currentIndex, nthList) { 272 var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList); 273 return this.getHexOfV_AtObj(h, idx); 274 }; 275 }; 276 277 /* 278 * @since asn1hex 1.1.4 279 */ 280 ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) { 281 var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList); 282 if (idx === undefined) { 283 throw "can't find nthList object"; 284 } 285 if (checkingTag !== undefined) { 286 if (h.substr(idx, 2) != checkingTag) { 287 throw "checking tag doesn't match: " + h.substr(idx,2) + "!=" + checkingTag; 288 } 289 } 290 return this.getHexOfV_AtObj(h, idx); 291 }; 292 293