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