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