blob: 1a8c5e04251d58d158522332de996007fb984569 [file] [log] [blame]
Wentao Shang882e34e2013-01-05 02:49:51 -08001/**
2 * @author: Wentao Shang
3 * See COPYING for copyright and distribution information.
4 */
5
6var MerklePath = function MerkelPath() {
7 this.index = null; // int
8 this.digestList = []; // array of hex string
9};
10
11var Witness = function Witness() {
12 this.oid = null; // string
13 this.path = new MerklePath(); // MerklePath
14};
15
Wentao Shange0d7f052013-01-05 16:37:02 -080016function parseOID(bytes, start, end) {
17 var s, n = 0, bits = 0;
18 for (var i = start; i < end; ++i) {
19 var v = bytes[i];
20 n = (n << 7) | (v & 0x7F);
21 bits += 7;
22 if (!(v & 0x80)) { // finished
23 if (s == undefined)
24 s = parseInt(n / 40) + "." + (n % 40);
25 else
26 s += "." + ((bits >= 31) ? "bigint" : n);
27 n = bits = 0;
28 }
29 s += String.fromCharCode();
30 }
31 return s;
32}
33
34function parseInteger(bytes, start, end) {
35 var n = 0;
36 for (var i = start; i < end; ++i)
37 n = (n << 8) | bytes[i];
38 return n;
39}
40
Wentao Shang882e34e2013-01-05 02:49:51 -080041Witness.prototype.decode = function(/* Uint8Array */ witness) {
Wentao Shange0d7f052013-01-05 16:37:02 -080042 /* The asn1.js decoder has some bug and
43 * cannot decode certain kind of witness.
44 * So we use an alternative (and dirty) hack
45 * to read witness from byte streams
46 * ------Wentao
47 */
48 /*
Wentao Shang882e34e2013-01-05 02:49:51 -080049 var wit = DataUtils.toHex(witness).toLowerCase();
Wentao Shange0d7f052013-01-05 16:37:02 -080050 try {
51 var der = Hex.decode(wit);
52 var asn1 = ASN1.decode(der);
53 }
54 catch (e) {
55 console.log(e);
56 console.log(wit);
57 }
Wentao Shang882e34e2013-01-05 02:49:51 -080058 //console.log(asn1.toPrettyString());
59
60 this.oid = asn1.sub[0].sub[0].content(); // OID
Wentao Shange0d7f052013-01-05 16:37:02 -080061 //console.log(this.oid);
Wentao Shang882e34e2013-01-05 02:49:51 -080062 this.path.index = asn1.sub[1].sub[0].sub[0].content(); // index
Wentao Shange0d7f052013-01-05 16:37:02 -080063 //console.log(this.path.index);
Wentao Shang882e34e2013-01-05 02:49:51 -080064 for (i = 0; i < asn1.sub[1].sub[0].sub[1].sub.length; i++) {
65 pos = asn1.sub[1].sub[0].sub[1].sub[i].stream.pos;
66 str = wit.substring(2 * pos + 4, 2 * pos + 68);
67 this.path.digestList.push(str); // digest hex string
Wentao Shange0d7f052013-01-05 16:37:02 -080068 //console.log(str);
69 }
70 */
71
72 // FIXME: Need to be fixed to support arbitrary ASN1 encoding,
73 // But do we really nned that???? -------Wentao
74
75 // The structure of Witness is fixed as follows:
76 // SEQUENCE (2 elem)
77 // SEQUENCE (1 elem)
78 // OBJECT IDENTIFIER 1.2.840.113550.11.1.2.2
79 // OCTET STRING (1 elem)
80 // SEQUENCE (2 elem)
81 // INTEGER index
82 // SEQUENCE (n elem)
83 // OCTET STRING(32 byte) 345FB4B5E9A1D2FF450ECA87EB87601683027A1A...
84 // OCTET STRING(32 byte) DBCEE5B7A6C2B851B029324197DDBD9A655723DC...
85 // OCTET STRING(32 byte) 4C79B2D256E4CD657A27F01DCB51AC3C56A24E71...
86 // OCTET STRING(32 byte) 7F7FB169604A87EAC94378F0BDB4FC5D5899AB88...
87 // ......
88 // Hence we can follow this structure to extract witness fields at fixed level
89 // Tag numbers for ASN1:
90 // SEQUENCE 0x10
91 // OCT STRING 0x04
92 // INTEGER 0x02
93 // OBJECT IDENTIFIER 0x06
94 var i = 0;
95 var step = 0; // count of sequence tag
96 while (i < witness.length) {
97 var len = 0;
98
99 if (witness[i] == 0x30) {
100 // Sequence (constructed)
101 // There is no primitive sequence in Witness
102 if ((witness[i + 1] & 0x80) != 0) {
103 len = witness[i+1] & 0x7F;
104 }
105 step++;
106 } else if (witness[i] == 0x06) {
107 // Decode OID
108 len = witness[i+1]; // XXX: OID will not be longer than 127 bytes
109 this.oid = parseOID(witness, i + 2, i + 2 + len);
110 //console.log(this.oid);
111 } else if (witness[i] == 0x02) {
112 // Decode node index
113 len = witness[i+1]; // XXX: index will not be longer than 127 bytes
114 this.path.index = parseInteger(witness, i + 2, i + 2 + len);
115 //console.log(this.path.index);
116 } else if (witness[i] == 0x04) {
117 if ((witness[i + 1] & 0x80) != 0) {
118 len = witness[i+1] & 0x7F;
119 } else {
120 len = witness[i+1];
121 }
122 if (step == 4) {
123 // Start to decode digest hex string
124 str = DataUtils.toHex(witness.subarray(i + 2, i + 2 + len));
125 this.path.digestList.push(str); // digest hex string
126 //console.log(str);
127 }
128 }
129 i = i + 2 + len;
Wentao Shang882e34e2013-01-05 02:49:51 -0800130 }
131};