blob: 04d9acf8e4a365c0ea7003ae9a1f6fa07d91fa3d [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
Jeff Thompson2b14c7e2013-07-29 15:09:56 -07006/**
7 * @constructor
8 */
Wentao Shang882e34e2013-01-05 02:49:51 -08009var MerklePath = function MerkelPath() {
10 this.index = null; // int
11 this.digestList = []; // array of hex string
12};
13
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070014/**
15 * @constructor
16 */
Wentao Shang882e34e2013-01-05 02:49:51 -080017var Witness = function Witness() {
18 this.oid = null; // string
19 this.path = new MerklePath(); // MerklePath
20};
21
Wentao Shange0d7f052013-01-05 16:37:02 -080022function parseOID(bytes, start, end) {
23 var s, n = 0, bits = 0;
24 for (var i = start; i < end; ++i) {
25 var v = bytes[i];
26 n = (n << 7) | (v & 0x7F);
27 bits += 7;
28 if (!(v & 0x80)) { // finished
29 if (s == undefined)
30 s = parseInt(n / 40) + "." + (n % 40);
31 else
32 s += "." + ((bits >= 31) ? "bigint" : n);
33 n = bits = 0;
34 }
35 s += String.fromCharCode();
36 }
37 return s;
38}
39
40function parseInteger(bytes, start, end) {
41 var n = 0;
42 for (var i = start; i < end; ++i)
43 n = (n << 8) | bytes[i];
44 return n;
45}
46
Wentao Shang882e34e2013-01-05 02:49:51 -080047Witness.prototype.decode = function(/* Uint8Array */ witness) {
Wentao Shange0d7f052013-01-05 16:37:02 -080048 /* The asn1.js decoder has some bug and
49 * cannot decode certain kind of witness.
50 * So we use an alternative (and dirty) hack
51 * to read witness from byte streams
52 * ------Wentao
53 */
54 /*
Wentao Shang882e34e2013-01-05 02:49:51 -080055 var wit = DataUtils.toHex(witness).toLowerCase();
Wentao Shange0d7f052013-01-05 16:37:02 -080056 try {
57 var der = Hex.decode(wit);
58 var asn1 = ASN1.decode(der);
59 }
60 catch (e) {
61 console.log(e);
62 console.log(wit);
63 }
Wentao Shang882e34e2013-01-05 02:49:51 -080064 //console.log(asn1.toPrettyString());
65
66 this.oid = asn1.sub[0].sub[0].content(); // OID
Wentao Shange0d7f052013-01-05 16:37:02 -080067 //console.log(this.oid);
Wentao Shang882e34e2013-01-05 02:49:51 -080068 this.path.index = asn1.sub[1].sub[0].sub[0].content(); // index
Wentao Shange0d7f052013-01-05 16:37:02 -080069 //console.log(this.path.index);
Wentao Shang882e34e2013-01-05 02:49:51 -080070 for (i = 0; i < asn1.sub[1].sub[0].sub[1].sub.length; i++) {
71 pos = asn1.sub[1].sub[0].sub[1].sub[i].stream.pos;
72 str = wit.substring(2 * pos + 4, 2 * pos + 68);
73 this.path.digestList.push(str); // digest hex string
Wentao Shange0d7f052013-01-05 16:37:02 -080074 //console.log(str);
75 }
76 */
77
78 // FIXME: Need to be fixed to support arbitrary ASN1 encoding,
79 // But do we really nned that???? -------Wentao
80
81 // The structure of Witness is fixed as follows:
82 // SEQUENCE (2 elem)
83 // SEQUENCE (1 elem)
84 // OBJECT IDENTIFIER 1.2.840.113550.11.1.2.2
85 // OCTET STRING (1 elem)
86 // SEQUENCE (2 elem)
87 // INTEGER index
88 // SEQUENCE (n elem)
89 // OCTET STRING(32 byte) 345FB4B5E9A1D2FF450ECA87EB87601683027A1A...
90 // OCTET STRING(32 byte) DBCEE5B7A6C2B851B029324197DDBD9A655723DC...
91 // OCTET STRING(32 byte) 4C79B2D256E4CD657A27F01DCB51AC3C56A24E71...
92 // OCTET STRING(32 byte) 7F7FB169604A87EAC94378F0BDB4FC5D5899AB88...
93 // ......
94 // Hence we can follow this structure to extract witness fields at fixed level
95 // Tag numbers for ASN1:
96 // SEQUENCE 0x10
97 // OCT STRING 0x04
98 // INTEGER 0x02
99 // OBJECT IDENTIFIER 0x06
100 var i = 0;
101 var step = 0; // count of sequence tag
102 while (i < witness.length) {
103 var len = 0;
104
105 if (witness[i] == 0x30) {
106 // Sequence (constructed)
107 // There is no primitive sequence in Witness
108 if ((witness[i + 1] & 0x80) != 0) {
109 len = witness[i+1] & 0x7F;
110 }
111 step++;
112 } else if (witness[i] == 0x06) {
113 // Decode OID
114 len = witness[i+1]; // XXX: OID will not be longer than 127 bytes
115 this.oid = parseOID(witness, i + 2, i + 2 + len);
116 //console.log(this.oid);
117 } else if (witness[i] == 0x02) {
118 // Decode node index
119 len = witness[i+1]; // XXX: index will not be longer than 127 bytes
120 this.path.index = parseInteger(witness, i + 2, i + 2 + len);
121 //console.log(this.path.index);
122 } else if (witness[i] == 0x04) {
123 if ((witness[i + 1] & 0x80) != 0) {
124 len = witness[i+1] & 0x7F;
Wentao Shange0d7f052013-01-05 16:37:02 -0800125 }
126 if (step == 4) {
127 // Start to decode digest hex string
Wentao Shangedd4dea2013-01-19 16:55:11 -0800128 len = witness[i+1]; // XXX: digest hex should always be 32 bytes
Jeff Thompson48ff28a2013-02-18 22:53:29 -0800129 var str = DataUtils.toHex(witness.subarray(i + 2, i + 2 + len));
Wentao Shange0d7f052013-01-05 16:37:02 -0800130 this.path.digestList.push(str); // digest hex string
131 //console.log(str);
132 }
133 }
134 i = i + 2 + len;
Wentao Shang882e34e2013-01-05 02:49:51 -0800135 }
136};