Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ultraviolet
GitHub Repository: ultraviolet/bitaddress.org
Path: blob/master/src/ninja.unittests.js
248 views
1
(function (ninja) {
2
var ut = ninja.unitTests = {
3
runSynchronousTests: function (showOutput) {
4
if (showOutput) {
5
document.getElementById("busyblock").className = "busy";
6
var div = document.createElement("div");
7
div.setAttribute("class", "unittests");
8
div.setAttribute("id", "unittests");
9
}
10
var userKeyPool = Bitcoin.KeyPool.getArray(); // get the user key pool before test keys get added to it
11
var testResults = "";
12
var passCount = 0;
13
var testCount = 0;
14
for (var test in ut.synchronousTests) {
15
var exceptionMsg = "";
16
var resultBool = false;
17
try {
18
resultBool = ut.synchronousTests[test]();
19
} catch (ex) {
20
exceptionMsg = ex.toString();
21
resultBool = false;
22
}
23
if (resultBool == true) {
24
var passFailStr = "pass";
25
passCount++;
26
}
27
else {
28
var passFailStr = "<b>FAIL " + exceptionMsg + "</b>";
29
}
30
testCount++;
31
testResults += test + ": " + passFailStr + "<br/>";
32
}
33
testResults += passCount + " of " + testCount + " synchronous tests passed";
34
if (passCount < testCount) {
35
testResults += "<br/><b>" + (testCount - passCount) + " unit test(s) failed</b>";
36
}
37
if (showOutput) {
38
div.innerHTML = "<h3>Unit Tests</h3><div id=\"unittestresults\">" + testResults + "<br/><br/></div>";
39
document.body.appendChild(div);
40
document.getElementById("busyblock").className = "";
41
}
42
Bitcoin.KeyPool.setArray(userKeyPool); // set the key pool so users don't see the test keys
43
return { passCount: passCount, testCount: testCount };
44
},
45
46
runAsynchronousTests: function (showOutput) {
47
if (showOutput) {
48
var div = document.createElement("div");
49
div.setAttribute("class", "unittests");
50
div.setAttribute("id", "asyncunittests");
51
div.innerHTML = "<h3>Async Unit Tests</h3><div id=\"asyncunittestresults\"></div><br/><br/><br/><br/>";
52
document.body.appendChild(div);
53
}
54
55
var userKeyPool = Bitcoin.KeyPool.getArray();
56
// run the asynchronous tests one after another so we don't crash the browser
57
ninja.foreachSerialized(ninja.unitTests.asynchronousTests, function (name, cb) {
58
//Bitcoin.KeyPool.reset();
59
document.getElementById("busyblock").className = "busy";
60
ninja.unitTests.asynchronousTests[name](cb);
61
}, function () {
62
if (showOutput) {
63
document.getElementById("asyncunittestresults").innerHTML += "running of asynchronous unit tests complete!<br/>";
64
}
65
console.log("running of asynchronous unit tests complete!");
66
Bitcoin.KeyPool.setArray(userKeyPool);
67
document.getElementById("busyblock").className = "";
68
});
69
},
70
71
synchronousTests: {
72
//ninja.publicKey tests
73
testIsPublicKeyHexFormat: function () {
74
var key = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
75
var bool = ninja.publicKey.isPublicKeyHexFormat(key);
76
if (bool != true) {
77
return false;
78
}
79
return true;
80
},
81
testGetHexFromByteArray: function () {
82
var bytes = [4, 120, 152, 47, 64, 250, 12, 11, 122, 85, 113, 117, 131, 175, 201, 154, 78, 223, 211, 1, 162, 114, 157, 197, 155, 11, 142, 185, 225, 134, 146, 188, 181, 33, 240, 84, 250, 217, 130, 175, 76, 193, 147, 58, 253, 31, 27, 86, 62, 167, 121, 166, 170, 108, 206, 54, 163, 11, 148, 125, 214, 83, 230, 62, 68];
83
var key = ninja.publicKey.getHexFromByteArray(bytes);
84
if (key != "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44") {
85
return false;
86
}
87
return true;
88
},
89
testHexToBytes: function () {
90
var key = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
91
var bytes = Crypto.util.hexToBytes(key);
92
if (bytes.toString() != "4,120,152,47,64,250,12,11,122,85,113,117,131,175,201,154,78,223,211,1,162,114,157,197,155,11,142,185,225,134,146,188,181,33,240,84,250,217,130,175,76,193,147,58,253,31,27,86,62,167,121,166,170,108,206,54,163,11,148,125,214,83,230,62,68") {
93
return false;
94
}
95
return true;
96
},
97
testGetBitcoinAddressFromByteArray: function () {
98
var bytes = [4, 120, 152, 47, 64, 250, 12, 11, 122, 85, 113, 117, 131, 175, 201, 154, 78, 223, 211, 1, 162, 114, 157, 197, 155, 11, 142, 185, 225, 134, 146, 188, 181, 33, 240, 84, 250, 217, 130, 175, 76, 193, 147, 58, 253, 31, 27, 86, 62, 167, 121, 166, 170, 108, 206, 54, 163, 11, 148, 125, 214, 83, 230, 62, 68];
99
var address = ninja.publicKey.getBitcoinAddressFromByteArray(bytes);
100
if (address != "1Cnz9ULjzBPYhDw1J8bpczDWCEXnC9HuU1") {
101
return false;
102
}
103
return true;
104
},
105
testGetByteArrayFromAdding: function () {
106
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
107
var key2 = "0419153E53FECAD7FF07FEC26F7DDEB1EDD66957711AA4554B8475F10AFBBCD81C0159DC0099AD54F733812892EB9A11A8C816A201B3BAF0D97117EBA2033C9AB2";
108
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
109
if (bytes.toString() != "4,151,19,227,152,54,37,184,255,4,83,115,216,102,189,76,82,170,57,4,196,253,2,41,74,6,226,33,167,199,250,74,235,223,128,233,99,150,147,92,57,39,208,84,196,71,68,248,166,106,138,95,172,253,224,70,187,65,62,92,81,38,253,79,0") {
110
return false;
111
}
112
return true;
113
},
114
testGetByteArrayFromAddingCompressed: function () {
115
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
116
var key2 = "0219153E53FECAD7FF07FEC26F7DDEB1EDD66957711AA4554B8475F10AFBBCD81C";
117
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
118
var hex = ninja.publicKey.getHexFromByteArray(bytes);
119
if (hex != "029713E3983625B8FF045373D866BD4C52AA3904C4FD02294A06E221A7C7FA4AEB") {
120
return false;
121
}
122
return true;
123
},
124
testGetByteArrayFromAddingUncompressedAndCompressed: function () {
125
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
126
var key2 = "0219153E53FECAD7FF07FEC26F7DDEB1EDD66957711AA4554B8475F10AFBBCD81C";
127
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
128
if (bytes.toString() != "4,151,19,227,152,54,37,184,255,4,83,115,216,102,189,76,82,170,57,4,196,253,2,41,74,6,226,33,167,199,250,74,235,223,128,233,99,150,147,92,57,39,208,84,196,71,68,248,166,106,138,95,172,253,224,70,187,65,62,92,81,38,253,79,0") {
129
return false;
130
}
131
return true;
132
},
133
testGetByteArrayFromAddingShouldReturnNullWhenSameKey1: function () {
134
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
135
var key2 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
136
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
137
if (bytes != null) {
138
return false;
139
}
140
return true;
141
},
142
testGetByteArrayFromAddingShouldReturnNullWhenSameKey2: function () {
143
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
144
var key2 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
145
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
146
if (bytes != null) {
147
return false;
148
}
149
return true;
150
},
151
testGetByteArrayFromMultiplying: function () {
152
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
153
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
154
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
155
if (bytes.toString() != "4,102,230,163,180,107,9,21,17,48,35,245,227,110,199,119,144,57,41,112,64,245,182,40,224,41,230,41,5,26,206,138,57,115,35,54,105,7,180,5,106,217,57,229,127,174,145,215,79,121,163,191,211,143,215,50,48,156,211,178,72,226,68,150,52") {
156
return false;
157
}
158
return true;
159
},
160
testGetByteArrayFromMultiplyingCompressedOutputsUncompressed: function () {
161
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
162
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
163
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
164
if (bytes.toString() != "4,102,230,163,180,107,9,21,17,48,35,245,227,110,199,119,144,57,41,112,64,245,182,40,224,41,230,41,5,26,206,138,57,115,35,54,105,7,180,5,106,217,57,229,127,174,145,215,79,121,163,191,211,143,215,50,48,156,211,178,72,226,68,150,52") {
165
return false;
166
}
167
return true;
168
},
169
testGetByteArrayFromMultiplyingCompressedOutputsCompressed: function () {
170
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
171
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
172
var ecKey = new Bitcoin.ECKey(key2);
173
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, ecKey);
174
if (bytes.toString() != "2,102,230,163,180,107,9,21,17,48,35,245,227,110,199,119,144,57,41,112,64,245,182,40,224,41,230,41,5,26,206,138,57") {
175
return false;
176
}
177
return true;
178
},
179
testGetByteArrayFromMultiplyingShouldReturnNullWhenSameKey1: function () {
180
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
181
var key2 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
182
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
183
if (bytes != null) {
184
return false;
185
}
186
return true;
187
},
188
testGetByteArrayFromMultiplyingShouldReturnNullWhenSameKey2: function () {
189
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
190
var key2 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
191
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
192
if (bytes != null) {
193
return false;
194
}
195
return true;
196
},
197
// confirms multiplication is working and BigInteger was created correctly (Pub Key B vs Priv Key A)
198
testGetPubHexFromMultiplyingPrivAPubB: function () {
199
var keyPub = "04F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F98938020F36EBBDE6F1BEAF98E5BD0E425747E68B0F2FB7A2A59EDE93F43C0D78156FF";
200
var keyPriv = "B1202A137E917536B3B4C5010C3FF5DDD4784917B3EEF21D3A3BF21B2E03310C";
201
var bytes = ninja.publicKey.getByteArrayFromMultiplying(keyPub, new Bitcoin.ECKey(keyPriv));
202
var pubHex = ninja.publicKey.getHexFromByteArray(bytes);
203
if (pubHex != "04C6732006AF4AE571C7758DF7A7FB9E3689DFCF8B53D8724D3A15517D8AB1B4DBBE0CB8BB1C4525F8A3001771FC7E801D3C5986A555E2E9441F1AD6D181356076") {
204
return false;
205
}
206
return true;
207
},
208
// confirms multiplication is working and BigInteger was created correctly (Pub Key A vs Priv Key B)
209
testGetPubHexFromMultiplyingPrivBPubA: function () {
210
var keyPub = "0429BF26C0AF7D31D608474CEBD49DA6E7C541B8FAD95404B897643476CE621CFD05E24F7AE8DE8033AADE5857DB837E0B704A31FDDFE574F6ECA879643A0D3709";
211
var keyPriv = "7DE52819F1553C2BFEDE6A2628B6FDDF03C2A07EB21CF77ACA6C2C3D252E1FD9";
212
var bytes = ninja.publicKey.getByteArrayFromMultiplying(keyPub, new Bitcoin.ECKey(keyPriv));
213
var pubHex = ninja.publicKey.getHexFromByteArray(bytes);
214
if (pubHex != "04C6732006AF4AE571C7758DF7A7FB9E3689DFCF8B53D8724D3A15517D8AB1B4DBBE0CB8BB1C4525F8A3001771FC7E801D3C5986A555E2E9441F1AD6D181356076") {
215
return false;
216
}
217
return true;
218
},
219
220
// Private Key tests
221
testBadKeyIsNotWif: function () {
222
return !(Bitcoin.ECKey.isWalletImportFormat("bad key"));
223
},
224
testBadKeyIsNotWifCompressed: function () {
225
return !(Bitcoin.ECKey.isCompressedWalletImportFormat("bad key"));
226
},
227
testBadKeyIsNotHex: function () {
228
return !(Bitcoin.ECKey.isHexFormat("bad key"));
229
},
230
testBadKeyIsNotBase64: function () {
231
return !(Bitcoin.ECKey.isBase64Format("bad key"));
232
},
233
testBadKeyIsNotMini: function () {
234
return !(Bitcoin.ECKey.isMiniFormat("bad key"));
235
},
236
testBadKeyReturnsNullPrivFromECKey: function () {
237
var key = "bad key";
238
var ecKey = new Bitcoin.ECKey(key);
239
if (ecKey.priv != null) {
240
return false;
241
}
242
return true;
243
},
244
testGetBitcoinPrivateKeyByteArray: function () {
245
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
246
var bytes = [41, 38, 101, 195, 135, 36, 24, 173, 241, 218, 127, 250, 58, 100, 111, 47, 6, 2, 36, 109, 166, 9, 138, 145, 210, 41, 195, 33, 80, 242, 113, 139];
247
var btcKey = new Bitcoin.ECKey(key);
248
if (btcKey.getBitcoinPrivateKeyByteArray().toString() != bytes.toString()) {
249
return false;
250
}
251
return true;
252
},
253
testECKeyDecodeWalletImportFormat: function () {
254
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
255
var bytes1 = [41, 38, 101, 195, 135, 36, 24, 173, 241, 218, 127, 250, 58, 100, 111, 47, 6, 2, 36, 109, 166, 9, 138, 145, 210, 41, 195, 33, 80, 242, 113, 139];
256
var bytes2 = Bitcoin.ECKey.decodeWalletImportFormat(key);
257
if (bytes1.toString() != bytes2.toString()) {
258
return false;
259
}
260
return true;
261
},
262
testECKeyDecodeCompressedWalletImportFormat: function () {
263
var key = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
264
var bytes1 = [41, 38, 101, 195, 135, 36, 24, 173, 241, 218, 127, 250, 58, 100, 111, 47, 6, 2, 36, 109, 166, 9, 138, 145, 210, 41, 195, 33, 80, 242, 113, 139];
265
var bytes2 = Bitcoin.ECKey.decodeCompressedWalletImportFormat(key);
266
if (bytes1.toString() != bytes2.toString()) {
267
return false;
268
}
269
return true;
270
},
271
testWifToPubKeyHex: function () {
272
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
273
var btcKey = new Bitcoin.ECKey(key);
274
if (btcKey.getPubKeyHex() != "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44"
275
|| btcKey.getPubPoint().compressed != false) {
276
return false;
277
}
278
return true;
279
},
280
testWifToPubKeyHexCompressed: function () {
281
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
282
var btcKey = new Bitcoin.ECKey(key);
283
btcKey.setCompressed(true);
284
if (btcKey.getPubKeyHex() != "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5"
285
|| btcKey.getPubPoint().compressed != true) {
286
return false;
287
}
288
return true;
289
},
290
testBase64ToECKey: function () {
291
var key = "KSZlw4ckGK3x2n/6OmRvLwYCJG2mCYqR0inDIVDycYs=";
292
var btcKey = new Bitcoin.ECKey(key);
293
if (btcKey.getBitcoinBase64Format() != "KSZlw4ckGK3x2n/6OmRvLwYCJG2mCYqR0inDIVDycYs=") {
294
return false;
295
}
296
return true;
297
},
298
testHexToECKey: function () {
299
var key = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B";
300
var btcKey = new Bitcoin.ECKey(key);
301
if (btcKey.getBitcoinHexFormat() != "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B") {
302
return false;
303
}
304
return true;
305
},
306
testCompressedWifToECKey: function () {
307
var key = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
308
var btcKey = new Bitcoin.ECKey(key);
309
if (btcKey.getBitcoinWalletImportFormat() != "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S"
310
|| btcKey.getPubPoint().compressed != true
311
|| btcKey.compressed != true) {
312
return false;
313
}
314
return true;
315
},
316
testWifToECKey: function () {
317
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
318
var btcKey = new Bitcoin.ECKey(key);
319
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb"
320
|| btcKey.compressed == true) {
321
return false;
322
}
323
return true;
324
},
325
testBrainToECKey: function () {
326
var key = "bitaddress.org unit test";
327
var bytes = Crypto.SHA256(key, { asBytes: true });
328
var btcKey = new Bitcoin.ECKey(bytes);
329
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb") {
330
return false;
331
}
332
return true;
333
},
334
testMini30CharsToECKey: function () {
335
var key = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
336
var btcKey = new Bitcoin.ECKey(key);
337
if (btcKey.getBitcoinWalletImportFormat() != "5JrBLQseeZdYw4jWEAHmNxGMr5fxh9NJU3fUwnv4khfKcg2rJVh") {
338
return false;
339
}
340
return true;
341
},
342
testGetECKeyFromAdding: function () {
343
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
344
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
345
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
346
if (ecKey.getBitcoinWalletImportFormat() != "5KAJTSqSjpsZ11KyEE3qu5PrJVjR4ZCbNxK3Nb1F637oe41m1c2") {
347
return false;
348
}
349
return true;
350
},
351
testGetECKeyFromAddingCompressed: function () {
352
var key1 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
353
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
354
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
355
if (ecKey.getBitcoinWalletImportFormat() != "L3A43j2pc2J8F2SjBNbYprPrcDpDCh8Aju8dUH65BEM2r7RFSLv4") {
356
return false;
357
}
358
return true;
359
},
360
testGetECKeyFromAddingUncompressedAndCompressed: function () {
361
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
362
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
363
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
364
if (ecKey.getBitcoinWalletImportFormat() != "5KAJTSqSjpsZ11KyEE3qu5PrJVjR4ZCbNxK3Nb1F637oe41m1c2") {
365
return false;
366
}
367
return true;
368
},
369
testGetECKeyFromAddingShouldReturnNullWhenSameKey1: function () {
370
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
371
var key2 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
372
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
373
if (ecKey != null) {
374
return false;
375
}
376
return true;
377
},
378
testGetECKeyFromAddingShouldReturnNullWhenSameKey2: function () {
379
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
380
var key2 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
381
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
382
if (ecKey != null) {
383
return false;
384
}
385
return true;
386
},
387
testGetECKeyFromMultiplying: function () {
388
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
389
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
390
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
391
if (ecKey.getBitcoinWalletImportFormat() != "5KetpZ5mCGagCeJnMmvo18n4iVrtPSqrpnW5RP92Gv2BQy7GPCk") {
392
return false;
393
}
394
return true;
395
},
396
testGetECKeyFromMultiplyingCompressed: function () {
397
var key1 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
398
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
399
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
400
if (ecKey.getBitcoinWalletImportFormat() != "L5LFitc24jme2PfVChJS3bKuQAPBp54euuqLWciQdF2CxnaU3M8t") {
401
return false;
402
}
403
return true;
404
},
405
testGetECKeyFromMultiplyingUncompressedAndCompressed: function () {
406
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
407
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
408
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
409
if (ecKey.getBitcoinWalletImportFormat() != "5KetpZ5mCGagCeJnMmvo18n4iVrtPSqrpnW5RP92Gv2BQy7GPCk") {
410
return false;
411
}
412
return true;
413
},
414
testGetECKeyFromMultiplyingShouldReturnNullWhenSameKey1: function () {
415
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
416
var key2 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
417
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
418
if (ecKey != null) {
419
return false;
420
}
421
return true;
422
},
423
testGetECKeyFromMultiplyingShouldReturnNullWhenSameKey2: function () {
424
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
425
var key2 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
426
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
427
if (ecKey != null) {
428
return false;
429
}
430
return true;
431
},
432
testGetECKeyFromBase6Key: function () {
433
var baseKey = "100531114202410255230521444145414341221420541210522412225005202300434134213212540304311321323051431";
434
var hexKey = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B";
435
var ecKey = new Bitcoin.ECKey(baseKey);
436
if (ecKey.getBitcoinHexFormat() != hexKey) {
437
return false;
438
}
439
return true;
440
},
441
442
// EllipticCurve tests
443
testDecodePointEqualsDecodeFrom: function () {
444
var key = "04F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F98938020F36EBBDE6F1BEAF98E5BD0E425747E68B0F2FB7A2A59EDE93F43C0D78156FF";
445
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
446
var ecPoint1 = EllipticCurve.PointFp.decodeFrom(ecparams.getCurve(), Crypto.util.hexToBytes(key));
447
var ecPoint2 = ecparams.getCurve().decodePointHex(key);
448
if (!ecPoint1.equals(ecPoint2)) {
449
return false;
450
}
451
return true;
452
},
453
testDecodePointHexForCompressedPublicKey: function () {
454
var key = "03F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F989380";
455
var pubHexUncompressed = ninja.publicKey.getDecompressedPubKeyHex(key);
456
if (pubHexUncompressed != "04F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F98938020F36EBBDE6F1BEAF98E5BD0E425747E68B0F2FB7A2A59EDE93F43C0D78156FF") {
457
return false;
458
}
459
return true;
460
},
461
// old bugs
462
testBugWithLeadingZeroBytePublicKey: function () {
463
var key = "5Je7CkWTzgdo1RpwjYhwnVKxQXt8EPRq17WZFtWcq5umQdsDtTP";
464
var btcKey = new Bitcoin.ECKey(key);
465
if (btcKey.getBitcoinAddress() != "1M6dsMZUjFxjdwsyVk8nJytWcfr9tfUa9E") {
466
return false;
467
}
468
return true;
469
},
470
testBugWithLeadingZeroBytePrivateKey: function () {
471
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da";
472
var btcKey = new Bitcoin.ECKey(key);
473
if (btcKey.getBitcoinAddress() != "1NAjZjF81YGfiJ3rTKc7jf1nmZ26KN7Gkn") {
474
return false;
475
}
476
return true;
477
},
478
479
// test split wallet
480
testSplitAndCombinePrivateKey2of2: function () {
481
// lowercase hex key
482
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da"; //5HpJ4bpHFEMWYwCidjtZHwM2rsMh4PRfmZKV8Y21i7msiUkQKUW
483
var numshares = 2;
484
var threshold = 2;
485
secrets.setRNG();
486
secrets.init(7);
487
488
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
489
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
490
var btcKey = new Bitcoin.ECKey(combined);
491
492
if (btcKey.getBitcoinHexFormat() != key.toUpperCase()) {
493
return false;
494
}
495
return true;
496
},
497
// Example use case #1:
498
// Division of 3 shares:
499
// 1 share in a safety deposit box ("Box")
500
// 1 share at Home
501
// 1 share at Work
502
// Threshold of 2 can be redeemed in these permutations
503
// Home + Box
504
// Work + Box
505
// Home + Work
506
testSplitAndCombinePrivateKey2of3: function () {
507
// lowercase hex key
508
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da"; //5HpJ4bpHFEMWYwCidjtZHwM2rsMh4PRfmZKV8Y21i7msiUkQKUW
509
var numshares = 3;
510
var threshold = 2;
511
secrets.setRNG();
512
secrets.init(7);
513
514
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
515
shares.shift();
516
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
517
var btcKey = new Bitcoin.ECKey(combined);
518
519
if (btcKey.getBitcoinHexFormat() != key.toUpperCase()) {
520
return false;
521
}
522
return true;
523
},
524
testSplitAndCombinePrivateKey2of4: function () {
525
// uppercase hex key
526
var key = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B"; //5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb
527
var numshares = 4;
528
var threshold = 2;
529
secrets.setRNG();
530
secrets.init(7);
531
532
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
533
shares.shift();
534
shares.shift();
535
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
536
var btcKey = new Bitcoin.ECKey(combined);
537
538
if (btcKey.getBitcoinHexFormat() != key) {
539
return false;
540
}
541
return true;
542
},
543
// Example use case #2:
544
// Division of 13 shares:
545
// 4 shares in a safety deposit box ("Box")
546
// 3 shares with good friend Angie
547
// 3 shares with good friend Fred
548
// 3 shares with Self at home or office
549
// Threshold of 7 can be redeemed in these permutations
550
// Self + Box (no trust to spend your coins but your friends are backing up your shares)
551
// Angie + Box (Angie will send btc to executor of your will)
552
// Fred + Box (if Angie hasn't already then Fred will send btc to executor of your will)
553
// Angie + Fred + Self (bank fire/theft then you with both your friends can spend the coins)
554
testSplitAndCombinePrivateKey7of13: function () {
555
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da";
556
var numshares = 12;
557
var threshold = 7;
558
secrets.setRNG();
559
secrets.init(7);
560
561
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
562
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
563
var btcKey = new Bitcoin.ECKey(combined);
564
565
if (btcKey.getBitcoinHexFormat() != key.toUpperCase()) {
566
return false;
567
}
568
return true;
569
},
570
testCombinePrivateKeyFromXofYShares: function () {
571
var key = "5K9nHKqbwc1xXpa6wV5p3AaCnubvxQDBukKaFkq7ThAkxgMTMEh";
572
// these are 4 of 6 shares
573
var shares = ["3XxjMASmrkk6eXMM9kAJA7qiqViNVBfiwA1GQDLvg4PVScL", "3Y2DkcPuNX8VKZwpnDdxw55wJtcnCvv2nALqe8nBLViHvck",
574
"3Y6qv7kyGwgRBKVHVbUNtzmLYAZWQtTPztPwR8wc7uf4MXR", "3YD4TowZn6jw5ss8U89vrcPHonFW4vSs9VKq8MupV5kevG4"]
575
secrets.setRNG();
576
secrets.init(7);
577
578
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
579
var btcKey = new Bitcoin.ECKey(combined);
580
if (btcKey.getBitcoinWalletImportFormat() != key) {
581
return false;
582
}
583
return true;
584
},
585
586
//Bitcoin.KeyPool tests
587
testKeyPoolStoresCompressedAndUncompressedKey: function () {
588
var keyUncompressed = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
589
var keyCompressed = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
590
Bitcoin.KeyPool.reset();
591
592
var btcKeyUncompressed = new Bitcoin.ECKey(keyUncompressed);
593
var btcKeyCompressed = new Bitcoin.ECKey(keyCompressed);
594
var pool = Bitcoin.KeyPool.getArray();
595
596
if (pool.length != 2
597
|| pool[0].getBitcoinWalletImportFormat() != keyUncompressed
598
|| pool[1].getBitcoinWalletImportFormat() != keyCompressed
599
) {
600
return false;
601
}
602
return true;
603
},
604
testKeyPoolPreventDuplicatesWhenAdding: function () {
605
var keyUncompressed = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
606
var keyCompressed = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
607
var keyHex = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B";
608
609
Bitcoin.KeyPool.reset();
610
var btcKeyUncompressed = new Bitcoin.ECKey(keyUncompressed);
611
var btcKeyCompressed = new Bitcoin.ECKey(keyCompressed);
612
var btcKeyCompressed2 = new Bitcoin.ECKey(keyCompressed);
613
var btcKeyUncompressed2 = new Bitcoin.ECKey(keyUncompressed);
614
var btcKeyHex = new Bitcoin.ECKey(keyHex);
615
var pool = Bitcoin.KeyPool.getArray();
616
617
if (pool.length != 2
618
|| pool[0].getBitcoinWalletImportFormat() != keyUncompressed
619
|| pool[1].getBitcoinWalletImportFormat() != keyCompressed
620
) {
621
return false;
622
}
623
return true;
624
},
625
626
//BigInteger tests
627
testBigIntegerShouldWorkWithoutNew: function () {
628
var bi = BigInteger('12345')
629
if (bi.toString(10) != '12345') {
630
return false;
631
}
632
return true;
633
},
634
testBigIntegerShouldWorkWithStringInput: function () {
635
if (new BigInteger('12345').toString(16) != '3039') return false;
636
if (new BigInteger('29048849665247').toString(16) != '1a6b765d8cdf') return false;
637
if (new BigInteger('-29048849665247').toString(16) != '-1a6b765d8cdf') return false;
638
if (new BigInteger('1A6B765D8CDF', 16).toString(16) != '1a6b765d8cdf') return false;
639
if (new BigInteger('FF', 16).toString() != '255') return false;
640
if (new BigInteger('1A6B765D8CDF', 16).toString() != '29048849665247') return false;
641
if (new BigInteger('a89c e5af8724 c0a23e0e 0ff77500', 16).toString(16) != 'a89ce5af8724c0a23e0e0ff77500') return false;
642
if (new BigInteger('123456789abcdef123456789abcdef123456789abcdef', 16).toString(16) != '123456789abcdef123456789abcdef123456789abcdef') return false;
643
if (new BigInteger('10654321').toString() != '10654321') return false;
644
if (new BigInteger('10000000000000000').toString(10) != '10000000000000000') return false;
645
646
return true;
647
},
648
testBigIntegerShouldImportExportTwosComplementBigEndian: function () {
649
if (new BigInteger([1, 2, 3], 256).toString(16) != '10203') return false;
650
if (new BigInteger([1, 2, 3, 4], 256).toString(16) != '1020304') return false;
651
if (new BigInteger([1, 2, 3, 4, 5], 256).toString(16) != '102030405') return false;
652
if (new BigInteger([1, 2, 3, 4, 5, 6, 7, 8], 256).toString(16) != '102030405060708') return false;
653
if (new BigInteger([1, 2, 3, 4], 256).toByteArray().join(',') != '1,2,3,4') return false;
654
if (new BigInteger([1, 2, 3, 4, 5, 6, 7, 8], 256).toByteArray().join(',') != '1,2,3,4,5,6,7,8') return false;
655
656
return true;
657
},
658
testBigIntegerShouldReturnProperBitLength: function () {
659
if (new BigInteger('0').bitLength() != 0) return false;
660
if (new BigInteger('1', 16).bitLength() != 1) return false;
661
if (new BigInteger('2', 16).bitLength() != 2) return false;
662
if (new BigInteger('3', 16).bitLength() != 2) return false;
663
if (new BigInteger('4', 16).bitLength() != 3) return false;
664
if (new BigInteger('8', 16).bitLength() != 4) return false;
665
if (new BigInteger('10', 16).bitLength() != 5) return false;
666
if (new BigInteger('100', 16).bitLength() != 9) return false;
667
if (new BigInteger('123456', 16).bitLength() != 21) return false;
668
if (new BigInteger('123456789', 16).bitLength() != 33) return false;
669
if (new BigInteger('8023456789', 16).bitLength() != 40) return false;
670
671
return true;
672
},
673
testBigIntegerShouldAddNumbers: function () {
674
// test 1
675
if (new BigInteger('14').add(new BigInteger('26')).toString(16) != '28') return false;
676
677
// test 2
678
var k = new BigInteger('1234', 16);
679
var r = k;
680
for (var i = 0; i < 257; i++) r = r.add(k);
681
if (r.toString(16) != '125868') return false;
682
683
// test 3
684
var k = new BigInteger('abcdefabcdefabcdef', 16);
685
var r = new BigInteger('deadbeef', 16);
686
for (var i = 0; i < 257; i++) {
687
r = r.add(k);
688
}
689
if (r.toString(16) != 'ac79bd9b79be7a277bde') return false;
690
691
return true;
692
},
693
testBigIntegerShouldSubtractNumbers: function () {
694
// test 1
695
if (new BigInteger('14').subtract(new BigInteger('26')).toString(16) != '-c') return false;
696
// test 2
697
if (new BigInteger('26').subtract(new BigInteger('14')).toString(16) != 'c') return false;
698
// test 3
699
if (new BigInteger('26').subtract(new BigInteger('26')).toString(16) != '0') return false;
700
// test 4
701
if (new BigInteger('-26').subtract(new BigInteger('26')).toString(16) != '-34') return false;
702
// test 5
703
var a = new BigInteger('31ff3c61db2db84b9823d320907a573f6ad37c437abe458b1802cda041d6384a7d8daef41395491e2', 16);
704
var b = new BigInteger('6f0e4d9f1d6071c183677f601af9305721c91d31b0bbbae8fb790000', 16);
705
var r = new BigInteger('31ff3c61db2db84b9823d3208989726578fd75276287cd9516533a9acfb9a6776281f34583ddb91e2', 16);
706
if (a.subtract(b).compareTo(r) != 0) return false;
707
// test 6
708
var r = b.subtract(new BigInteger('14'));
709
if (b.clone().subtract(new BigInteger('14')).compareTo(r) != 0) return false;
710
// test 7
711
var r = new BigInteger('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b', 16);
712
if (r.subtract(new BigInteger('-1')).toString(16) != '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681c') return false;
713
// test 8
714
// Carry and copy
715
var a = new BigInteger('12345', 16);
716
var b = new BigInteger('1000000000000', 16);
717
if (a.subtract(b).toString(16) != '-fffffffedcbb') return false;
718
// test 9
719
var a = new BigInteger('12345', 16);
720
var b = new BigInteger('1000000000000', 16);
721
if (b.subtract(a).toString(16) != 'fffffffedcbb') return false;
722
723
return true;
724
},
725
testBigIntegerShouldMultiplyNumbers: function () {
726
if (new BigInteger('1001', 16).multiply(new BigInteger('1234', 16)).toString(16) != '1235234') return false;
727
if (new BigInteger('-1001', 16).multiply(new BigInteger('1234', 16)).toString(16) != '-1235234') return false;
728
if (new BigInteger('-1001', 16).multiply(new BigInteger('-1234', 16)).toString(16) != '1235234') return false;
729
730
// test 4
731
var n = new BigInteger('1001', 16);
732
var r = n;
733
for (var i = 0; i < 4; i++) {
734
r = r.multiply(n);
735
}
736
if (r.toString(16) != '100500a00a005001') return false;
737
738
var n = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
739
if (n.multiply(n).toString(16) != '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9978a8bd8acaa40') return false;
740
if (n.multiply(n).multiply(n).toString(16) != '1b888e01a06e974017a28a5b4da436169761c9730b7aeedf75fc60f687b46e0cf2cb11667f795d5569482640fe5f628939467a01a612b023500d0161e9730279a7561043af6197798e41b7432458463e64fa81158907322dc330562697d0d600') return false;
741
742
if (new BigInteger('-100000000000').multiply(new BigInteger('3').divide(new BigInteger('4'))).toString(16) != '0') return false;
743
744
return true;
745
},
746
testBigIntegerShouldDivideNumbers: function () {
747
if (new BigInteger('10').divide(new BigInteger('256')).toString(16) != '0') return false;
748
if (new BigInteger('69527932928').divide(new BigInteger('16974594')).toString(16) != 'fff') return false;
749
if (new BigInteger('-69527932928').divide(new BigInteger('16974594')).toString(16) != '-fff') return false;
750
751
var b = new BigInteger('39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9978a8bd8acaa40', 16);
752
var n = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
753
if (b.divide(n).toString(16) != n.toString(16)) return false;
754
755
if (new BigInteger('1').divide(new BigInteger('-5')).toString(10) != '0') return false;
756
757
// // Regression after moving to word div
758
var p = new BigInteger('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16);
759
var a = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
760
var as = a.square();
761
if (as.divide(p).toString(16) != '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729e58090b9') return false;
762
763
var p = new BigInteger('ffffffff00000001000000000000000000000000ffffffffffffffffffffffff', 16);
764
var a = new BigInteger('fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16);
765
if (a.divide(p).toString(16) != 'ffffffff00000002000000000000000000000001000000000000000000000001') return false;
766
767
return true;
768
},
769
testBigIntegerShouldModNumbers: function () {
770
if (new BigInteger('10').mod(new BigInteger('256')).toString(16) != 'a') return false;
771
if (new BigInteger('69527932928').mod(new BigInteger('16974594')).toString(16) != '102f302') return false;
772
if (new BigInteger('-69527932928').mod(new BigInteger('16974594')).toString(16) != '1000') return false;
773
if (new BigInteger('10', 16).mod(new BigInteger('256')).toString(16) != '10') return false;
774
if (new BigInteger('100', 16).mod(new BigInteger('256')).toString(16) != '0') return false;
775
if (new BigInteger('1001', 16).mod(new BigInteger('256')).toString(16) != '1') return false;
776
if (new BigInteger('100000000001', 16).mod(new BigInteger('256')).toString(16) != '1') return false;
777
if (new BigInteger('100000000001', 16).mod(new BigInteger('257')).toString(16) != new BigInteger('100000000001', 16).mod(new BigInteger('257')).toString(16)) return false;
778
if (new BigInteger('123456789012', 16).mod(new BigInteger('3')).toString(16) != new BigInteger('123456789012', 16).mod(new BigInteger('3')).toString(16)) return false;
779
780
var p = new BigInteger('ffffffff00000001000000000000000000000000ffffffffffffffffffffffff', 16);
781
var a = new BigInteger('fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16);
782
if (a.mod(p).toString(16) != '0') return false;
783
784
return true;
785
},
786
testBigIntegerShouldShiftLeftNumbers: function () {
787
if (new BigInteger('69527932928').shiftLeft(13).toString(16) != '2060602000000') return false;
788
if (new BigInteger('69527932928').shiftLeft(45).toString(16) != '206060200000000000000') return false;
789
790
return true;
791
},
792
testBigIntegerShouldShiftRightNumbers: function () {
793
if (new BigInteger('69527932928').shiftRight(13).toString(16) != '818180') return false;
794
if (new BigInteger('69527932928').shiftRight(17).toString(16) != '81818') return false;
795
if (new BigInteger('69527932928').shiftRight(256).toString(16) != '0') return false;
796
797
return true;
798
},
799
testBigIntegerShouldModInverseNumbers: function () {
800
var p = new BigInteger('257');
801
var a = new BigInteger('3');
802
var b = a.modInverse(p);
803
if (a.multiply(b).mod(p).toString(16) != '1') return false;
804
805
var p192 = new BigInteger('fffffffffffffffffffffffffffffffeffffffffffffffff', 16);
806
var a = new BigInteger('deadbeef', 16);
807
var b = a.modInverse(p192);
808
if (a.multiply(b).mod(p192).toString(16) != '1') return false;
809
810
return true;
811
},
812
testBigIntegerShouldThrowOnModInverseOfZero: function () {
813
var p = new BigInteger('257');
814
var a = new BigInteger('0');
815
//division by zero
816
try {
817
a.modInverse(p);
818
}
819
catch (e) {
820
return true;
821
}
822
return false;
823
},
824
testBigIntegerShouldAlwaysReturnPositiveNumber: function () {
825
var z = new BigInteger('cc61934972bba029382f0bef146b228ca15d54f7e38b6cd5f6b382398b7a97a8', 16);
826
var p = new BigInteger('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16);
827
var zInv = z.modInverse(p);
828
if (zInv.signum() !== 1) return false; //zInv should be positive
829
830
return true;
831
},
832
testECKeyDoesntHangWithSpecificKey: function () {
833
var key = "848b39bbe4c9ddf978d3d8f786315bdc3ba71237d5f780399e0026e1269313ef";
834
var btcKey = new Bitcoin.ECKey(key);
835
if (btcKey.getPubKeyHex() != "0478BC8F7CB4485E7A0314A698AA1600639FF2922D09C26DED5F730CAC4784477D2B325922459F017AC1E8775436D11D7F84BD84E11CB64FC9BE110931D0C990CE"
836
) {
837
return false;
838
}
839
return true;
840
},
841
842
// test checksum exceptions
843
testUncompressedWifShouldFailChecksum: function () {
844
// original key: 5KjQAHniFiy18SU7eenyJ9EPYUkjrbiBPfDqw987QjT5vehVQZV K->k
845
var key = "5kjQAHniFiy18SU7eenyJ9EPYUkjrbiBPfDqw987QjT5vehVQZV";
846
var btcKey = new Bitcoin.ECKey(key);
847
if (btcKey.error.toString().indexOf("failed") == -1) { //Checksum validation failed!
848
return false;
849
}
850
return true;
851
852
},
853
testCompressedWifShouldFailChecksum: function () {
854
// original key: L5g9E16m5zEBZqQgMBouUfL6VwW49vCks1hgyxrPHkN8jNNdWTTk g->G
855
var key = "L5G9E16m5zEBZqQgMBouUfL6VwW49vCks1hgyxrPHkN8jNNdWTTk";
856
var btcKey = new Bitcoin.ECKey(key);
857
if (btcKey.error.toString().indexOf("failed") == -1) { //Checksum validation failed!
858
return false;
859
}
860
return true;
861
862
},
863
// test range of valid private key values for the secp256k1 curve, when specified in hex is
864
// [0x1, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140]
865
testBigIntegerZeroShouldSetError: function () {
866
var key = "0000000000000000000000000000000000000000000000000000000000000000";
867
var btcKey = new Bitcoin.ECKey(key);
868
if (btcKey.error == null) {
869
return false;
870
}
871
return true;
872
873
},
874
testBigIntegerOutOfCurveRangeShouldSetError1: function () {
875
var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";
876
var btcKey = new Bitcoin.ECKey(key);
877
if (btcKey.error == null) {
878
return false;
879
}
880
return true;
881
},
882
testBigIntegerOutOfCurveRangeShouldSetError2: function () {
883
var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364142";
884
var btcKey = new Bitcoin.ECKey(key);
885
if (btcKey.error == null) {
886
return false;
887
}
888
return true;
889
},
890
testBigIntegerOutOfCurveRangeShouldSetError3: function () {
891
var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
892
var btcKey = new Bitcoin.ECKey(key);
893
if (btcKey.error == null) {
894
return false;
895
}
896
return true;
897
}
898
},
899
900
asynchronousTests: {
901
//https://en.bitcoin.it/wiki/BIP_0038
902
testBip38: function (done) {
903
var tests = [
904
//No compression, no EC multiply
905
["6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg", "TestingOneTwoThree", "5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR"],
906
["6PRNFFkZc2NZ6dJqFfhRoFNMR9Lnyj7dYGrzdgXXVMXcxoKTePPX1dWByq", "Satoshi", "5HtasZ6ofTHP6HCwTqTkLDuLQisYPah7aUnSKfC7h4hMUVw2gi5"],
907
//Compression, no EC multiply
908
["6PYNKZ1EAgYgmQfmNVamxyXVWHzK5s6DGhwP4J5o44cvXdoY7sRzhtpUeo", "TestingOneTwoThree", "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP"],
909
["6PYLtMnXvfG3oJde97zRyLYFZCYizPU5T3LwgdYJz1fRhh16bU7u6PPmY7", "Satoshi", "KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7"],
910
//EC multiply, no compression, no lot/sequence numbers
911
["6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX", "TestingOneTwoThree", "5K4caxezwjGCGfnoPTZ8tMcJBLB7Jvyjv4xxeacadhq8nLisLR2"],
912
["6PfLGnQs6VZnrNpmVKfjotbnQuaJK4KZoPFrAjx1JMJUa1Ft8gnf5WxfKd", "Satoshi", "5KJ51SgxWaAYR13zd9ReMhJpwrcX47xTJh2D3fGPG9CM8vkv5sH"],
913
//EC multiply, no compression, lot/sequence numbers
914
["6PgNBNNzDkKdhkT6uJntUXwwzQV8Rr2tZcbkDcuC9DZRsS6AtHts4Ypo1j", "MOLON LABE", "5JLdxTtcTHcfYcmJsNVy1v2PMDx432JPoYcBTVVRHpPaxUrdtf8"],
915
["6PgGWtx25kUg8QWvwuJAgorN6k9FbE25rv5dMRwu5SKMnfpfVe5mar2ngH", Crypto.charenc.UTF8.bytesToString([206, 156, 206, 159, 206, 155, 206, 169, 206, 157, 32, 206, 155, 206, 145, 206, 146, 206, 149])/*UTF-8 characters, encoded in source so they don't get corrupted*/, "5KMKKuUmAkiNbA3DazMQiLfDq47qs8MAEThm4yL8R2PhV1ov33D"]];
916
917
var waitTimeMs = 60000;
918
919
// running each test uses a lot of memory, which isn't freed
920
// immediately, so give the VM a little time to reclaim memory
921
function waitThenCall(callback) {
922
return function () { setTimeout(callback, waitTimeMs); }
923
}
924
925
function log(str) {
926
if (document.getElementById("asyncunittestresults")) document.getElementById("asyncunittestresults").innerHTML += str + "<br/>";
927
console.log(str);
928
}
929
930
var decryptBip38Test = function (test, i, onComplete) {
931
ninja.privateKey.BIP38EncryptedKeyToByteArrayAsync(test[0], test[1], function (privBytes) {
932
if (privBytes.constructor == Error) {
933
log("fail decryptBip38Test #" + i + ", error: " + privBytes.message);
934
} else {
935
var btcKey = new Bitcoin.ECKey(privBytes);
936
var wif = !test[2].substr(0, 1).match(/[LK]/) ? btcKey.setCompressed(false).getBitcoinWalletImportFormat() : btcKey.setCompressed(true).getBitcoinWalletImportFormat();
937
if (wif != test[2]) {
938
log("fail decryptBip38Test #" + i);
939
} else {
940
log("pass decryptBip38Test #" + i);
941
}
942
}
943
onComplete();
944
});
945
};
946
947
var encryptBip38Test = function (test, compressed, i, onComplete) {
948
ninja.privateKey.BIP38PrivateKeyToEncryptedKeyAsync(test[2], test[1], compressed, function (encryptedKey) {
949
if (encryptedKey === test[0]) {
950
log("pass encryptBip38Test #" + i);
951
} else {
952
log("fail encryptBip38Test #" + i);
953
log("expected " + test[0] + "<br/>received " + encryptedKey);
954
}
955
onComplete();
956
});
957
};
958
959
// test randomly generated encryption-decryption cycle
960
var cycleBip38Test = function (i, compress, onComplete) {
961
// create new private key
962
var privKey = (new Bitcoin.ECKey(false)).getBitcoinWalletImportFormat();
963
964
// encrypt private key
965
ninja.privateKey.BIP38PrivateKeyToEncryptedKeyAsync(privKey, 'testing', compress, function (encryptedKey) {
966
// decrypt encryptedKey
967
ninja.privateKey.BIP38EncryptedKeyToByteArrayAsync(encryptedKey, 'testing', function (decryptedBytes) {
968
var decryptedKey = (new Bitcoin.ECKey(decryptedBytes)).getBitcoinWalletImportFormat();
969
970
if (decryptedKey === privKey) {
971
log("pass cycleBip38Test #" + i);
972
}
973
else {
974
log("fail cycleBip38Test #" + i + " " + privKey);
975
log("encrypted key: " + encryptedKey + "<br/>decrypted key: " + decryptedKey);
976
}
977
onComplete();
978
});
979
});
980
};
981
982
// intermediate test - create some encrypted keys from an intermediate
983
// then decrypt them to check that the private keys are recoverable
984
var intermediateBip38Test = function (i, onComplete) {
985
var pass = Math.random().toString(36).substr(2);
986
ninja.privateKey.BIP38GenerateIntermediatePointAsync(pass, null, null, function (intermediatePoint) {
987
ninja.privateKey.BIP38GenerateECAddressAsync(intermediatePoint, false, function (address, encryptedKey) {
988
ninja.privateKey.BIP38EncryptedKeyToByteArrayAsync(encryptedKey, pass, function (privBytes) {
989
if (privBytes.constructor == Error) {
990
log("fail intermediateBip38Test #" + i + ", error: " + privBytes.message);
991
} else {
992
var btcKey = new Bitcoin.ECKey(privBytes);
993
var btcAddress = btcKey.getBitcoinAddress();
994
if (address !== btcKey.getBitcoinAddress()) {
995
log("fail intermediateBip38Test #" + i);
996
} else {
997
log("pass intermediateBip38Test #" + i);
998
}
999
}
1000
onComplete();
1001
});
1002
});
1003
});
1004
}
1005
1006
var testArray = [
1007
function (cb) {
1008
log("running " + tests.length + " tests named decryptBip38Test");
1009
ninja.forSerialized(0, tests.length, function (i, callback) {
1010
console.log("running decryptBip38Test #" + i + " " + tests[i]);
1011
decryptBip38Test(tests[i], i, waitThenCall(callback));
1012
}, waitThenCall(cb));
1013
}
1014
,
1015
function (cb) {
1016
log("running 4 tests named encryptBip38Test");
1017
ninja.forSerialized(0, 4, function (i, callback) {
1018
console.log("running encryptBip38Test #" + i + " " + tests[i]);
1019
// only first 4 test vectors are not EC-multiply,
1020
// compression param false for i = 1,2 and true for i = 3,4
1021
encryptBip38Test(tests[i], i >= 2, i, waitThenCall(callback));
1022
}, waitThenCall(cb));
1023
}
1024
,
1025
function (cb) {
1026
log("running 2 tests named cycleBip38Test");
1027
ninja.forSerialized(0, 2, function (i, callback) {
1028
console.log("running cycleBip38Test #" + i);
1029
cycleBip38Test(i, i % 2 ? true : false, waitThenCall(callback));
1030
}, waitThenCall(cb));
1031
}
1032
,
1033
function (cb) {
1034
log("running 5 tests named intermediateBip38Test");
1035
ninja.forSerialized(0, 5, function (i, callback) {
1036
console.log("running intermediateBip38Test #" + i);
1037
intermediateBip38Test(i, waitThenCall(callback));
1038
}, cb);
1039
}
1040
];
1041
1042
ninja.runSerialized(testArray, done);
1043
}
1044
}
1045
};
1046
})(ninja);
1047