UNPKG

19.1 kBJavaScriptView Raw
1'use strict';
2
3var chai = require('chai');
4var should = chai.should();
5var expect = chai.expect;
6
7var bitcore = require('..');
8var Address = bitcore.Address;
9var BN = bitcore.crypto.BN;
10var Point = bitcore.crypto.Point;
11var PrivateKey = bitcore.PrivateKey;
12var Networks = bitcore.Networks;
13var Base58Check = bitcore.encoding.Base58Check;
14
15var validbase58 = require('./data/bitcoind/base58_keys_valid.json');
16var invalidbase58 = require('./data/bitcoind/base58_keys_invalid.json');
17
18describe('PrivateKey', function() {
19 var hex = '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a';
20 var hex2 = '8080808080808080808080808080808080808080808080808080808080808080';
21 var buf = Buffer.from(hex, 'hex');
22 var wifTestnet = 'cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG';
23 var wifTestnetUncompressed = '92jJzK4tbURm1C7udQXxeCBvXHoHJstDXRxAMouPG1k1XUaXdsu';
24 var wifLivenet = 'L2Gkw3kKJ6N24QcDuH4XDqt9cTqsKTVNDGz1CRZhk9cq4auDUbJy';
25 var wifLivenetUncompressed = '5JxgQaFM1FMd38cd14e3mbdxsdSa9iM2BV6DHBYsvGzxkTNQ7Un';
26 var wifNamecoin = '74pxNKNpByQ2kMow4d9kF6Z77BYeKztQNLq3dSyU4ES1K5KLNiz';
27
28 it('should create a new random private key', function() {
29 var a = new PrivateKey();
30 should.exist(a);
31 should.exist(a.bn);
32 var b = PrivateKey();
33 should.exist(b);
34 should.exist(b.bn);
35 });
36
37 it('should create a privatekey from hexa string', function() {
38 var a = new PrivateKey(hex2);
39 should.exist(a);
40 should.exist(a.bn);
41 });
42
43 it('should create a new random testnet private key with only one argument', function() {
44 var a = new PrivateKey(Networks.testnet);
45 should.exist(a);
46 should.exist(a.bn);
47 });
48
49 it('should create a private key from a custom network WIF string', function() {
50 var nmc = {
51 name: 'namecoin',
52 alias: 'namecoin',
53 pubkeyhash: 0x34,
54 privatekey: 0xB4,
55 // these below aren't the real NMC version numbers
56 scripthash: 0x08,
57 xpubkey: 0x0278b20e,
58 xprivkey: 0x0278ade4,
59 networkMagic: 0xf9beb4fe,
60 port: 20001,
61 dnsSeeds: [
62 'localhost',
63 'mynet.localhost'
64 ]
65 };
66 Networks.add(nmc);
67 var nmcNet = Networks.get('namecoin');
68 var a = new PrivateKey(wifNamecoin, nmcNet);
69 should.exist(a);
70 should.exist(a.bn);
71 Networks.remove(nmcNet);
72 });
73
74 it('should create a new random testnet private key with empty data', function() {
75 var a = new PrivateKey(null, Networks.testnet);
76 should.exist(a);
77 should.exist(a.bn);
78 });
79
80 it('should create a private key from WIF string', function() {
81 var a = new PrivateKey('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
82 should.exist(a);
83 should.exist(a.bn);
84 });
85
86 it('should create a private key from WIF buffer', function() {
87 var a = new PrivateKey(Base58Check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m'));
88 should.exist(a);
89 should.exist(a.bn);
90 });
91
92 describe('bitcoind compliance', function() {
93 validbase58.map(function(d){
94 if (d[2].isPrivkey) {
95 it('should instantiate WIF private key ' + d[0] + ' with correct properties', function() {
96 var network = Networks.livenet;
97 if (d[2].isTestnet) {
98 network = Networks.testnet;
99 }
100 var key = new PrivateKey(d[0]);
101 key.compressed.should.equal(d[2].isCompressed);
102 key.network.should.equal(network);
103 });
104 }
105 });
106 invalidbase58.map(function(d){
107 it('should describe input ' + d[0].slice(0,10) + '... as invalid', function() {
108 expect(function() {
109 return new PrivateKey(d[0]);
110 }).to.throw(Error);
111 });
112 });
113 });
114
115 describe('instantiation', function() {
116 it('should not be able to instantiate private key greater than N', function() {
117 expect(function() {
118 return new PrivateKey(Point.getN());
119 }).to.throw('Number must be less than N');
120 });
121
122 it('should not be able to instantiate private key because of network mismatch', function() {
123 expect(function() {
124 return new PrivateKey('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m', 'testnet');
125 }).to.throw('Private key network mismatch');
126 });
127
128 it('should not be able to instantiate private key WIF is too long', function() {
129 expect(function() {
130 var buf = Base58Check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
131 var buf2 = Buffer.concat([buf, Buffer.from([0x01])]);
132 return new PrivateKey(buf2);
133 }).to.throw('Length of buffer must be 33 (uncompressed) or 34 (compressed');
134 });
135
136 it('should not be able to instantiate private key WIF because of unknown network byte', function() {
137 expect(function() {
138 var buf = Base58Check.decode('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
139 var buf2 = Buffer.concat([ Buffer.from('ff', 'hex'), buf.slice(1, 33)]);
140 return new PrivateKey(buf2);
141 }).to.throw('Invalid network');
142 });
143
144 it('should not be able to instantiate private key WIF because of network mismatch', function() {
145 expect(function(){
146 var a = new PrivateKey(wifNamecoin, 'testnet');
147 }).to.throw('Invalid network');
148 });
149
150 it('can be instantiated from a hex string', function() {
151 var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
152 var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
153 var privkey = new PrivateKey(privhex);
154 privkey.publicKey.toString().should.equal(pubhex);
155 });
156
157 it('should not be able to instantiate because of unrecognized data', function() {
158 expect(function() {
159 return new PrivateKey(new Error());
160 }).to.throw('First argument is an unrecognized data type.');
161 });
162
163 it('should not be able to instantiate with unknown network', function() {
164 expect(function() {
165 return new PrivateKey(new BN(2), 'unknown');
166 }).to.throw('Must specify the network ("livenet" or "testnet")');
167 });
168
169 it('should not create a zero private key', function() {
170 expect(function() {
171 var bn = new BN(0);
172 return new PrivateKey(bn);
173 }).to.throw(TypeError);
174 });
175
176 it('should create a livenet private key', function() {
177 var privkey = new PrivateKey(BN.fromBuffer(buf), 'livenet');
178 privkey.toWIF().should.equal(wifLivenet);
179 });
180
181 it('should create a default network private key', function() {
182 // keep the original
183 var network = Networks.defaultNetwork;
184 Networks.defaultNetwork = Networks.livenet;
185 var a = new PrivateKey(BN.fromBuffer(buf));
186 a.network.should.equal(Networks.livenet);
187 // change the default
188 Networks.defaultNetwork = Networks.testnet;
189 var b = new PrivateKey(BN.fromBuffer(buf));
190 b.network.should.equal(Networks.testnet);
191 // restore the default
192 Networks.defaultNetwork = network;
193 });
194
195 it('returns the same instance if a PrivateKey is provided (immutable)', function() {
196 var privkey = new PrivateKey();
197 new PrivateKey(privkey).should.equal(privkey);
198 });
199
200 });
201
202 describe('#json/object', function() {
203
204 it('should input/output json', function() {
205 var json = JSON.stringify({
206 bn: '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a',
207 compressed: false,
208 network: 'livenet'
209 });
210 var key = PrivateKey.fromObject(JSON.parse(json));
211 JSON.stringify(key).should.equal(json);
212 });
213
214 it('input json should correctly initialize network field', function() {
215 ['livenet', 'testnet', 'mainnet'].forEach(function (net) {
216 var pk = PrivateKey.fromObject({
217 bn: '96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a',
218 compressed: false,
219 network: net
220 });
221 pk.network.should.be.deep.equal(Networks.get(net));
222 });
223 });
224
225 it('fails on invalid argument', function() {
226 expect(function() {
227 return PrivateKey.fromJSON('¹');
228 }).to.throw();
229 });
230
231 it('also accepts an object as argument', function() {
232 expect(function() {
233 return PrivateKey.fromObject(new PrivateKey().toObject());
234 }).to.not.throw();
235 });
236 });
237
238 it('coverage: public key cache', function() {
239 expect(function() {
240 var privateKey = new PrivateKey();
241 /* jshint unused: false */
242 var publicKey = privateKey.publicKey;
243 return privateKey.publicKey;
244 }).to.not.throw();
245 });
246
247 describe('#toString', function() {
248
249 it('should output this address correctly', function() {
250 var privkey = PrivateKey.fromWIF(wifLivenetUncompressed);
251 privkey.toWIF().should.equal(wifLivenetUncompressed);
252 });
253
254 });
255
256 describe('#toAddress', function() {
257 it('should output this known livenet address correctly', function() {
258 var privkey = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
259 var address = privkey.toAddress();
260 address.toString().should.equal('1A6ut1tWnUq1SEQLMr4ttDh24wcbJ5o9TT');
261 });
262
263 it('should output this known testnet address correctly', function() {
264 var privkey = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
265 var address = privkey.toAddress();
266 address.toString().should.equal('mtX8nPZZdJ8d3QNLRJ1oJTiEi26Sj6LQXS');
267 });
268
269 it('creates network specific address', function() {
270 var pk = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
271 pk.toAddress(Networks.livenet).network.name.should.equal(Networks.livenet.name);
272 pk.toAddress(Networks.testnet).network.name.should.equal(Networks.testnet.name);
273 });
274
275 it('should output this known livenet witness address correctly', function() {
276 var privkey = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
277 var address = privkey.toAddress(null, Address.PayToWitnessPublicKeyHash);
278 address.toString().should.equal('bc1qv0t45lutg37ghyg7lg22vgducs3d9hvuarwr89');
279 });
280
281 it('should output this known testnet witness address correctly', function() {
282 var privkey = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
283 var address = privkey.toAddress(null, Address.PayToWitnessPublicKeyHash);
284 address.toString().should.equal('tb1q363x8lv54fdsywyc9494upd6sp4rg6glhsyzk0');
285 });
286
287 it('creates network specific witness address', function() {
288 var pk = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
289 pk.toAddress(Networks.livenet, Address.PayToWitnessPublicKeyHash).network.name.should.equal(Networks.livenet.name);
290 pk.toAddress(Networks.testnet, Address.PayToWitnessPublicKeyHash).network.name.should.equal(Networks.testnet.name);
291 });
292
293 it('should output this known livenet wrapped witness address correctly', function() {
294 var privkey = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
295 var address = privkey.toAddress(null, Address.PayToScriptHash);
296 address.toString().should.equal('39wREM7dxb7KNMNR1py1W8nUheUtkPPA5r');
297 });
298
299 it('should output this known testnet wrapped witness address correctly', function() {
300 var privkey = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
301 var address = privkey.toAddress(null, Address.PayToScriptHash);
302 address.toString().should.equal('2NDgQSsQGdLDGoYvh4NTmesQ2wWgx6RGu3m');
303 });
304
305 it('creates network specific wrapped witness address', function() {
306 var pk = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
307 pk.toAddress(Networks.livenet, Address.PayToScriptHash).network.name.should.equal(Networks.livenet.name);
308 pk.toAddress(Networks.testnet, Address.PayToScriptHash).network.name.should.equal(Networks.testnet.name);
309 });
310
311 });
312
313 describe('#inspect', function() {
314 it('should output known livenet address for console', function() {
315 var privkey = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
316 privkey.inspect().should.equal(
317 '<PrivateKey: b9de6e778fe92aa7edb69395556f843f1dce0448350112e14906efc2a80fa61a, network: livenet>'
318 );
319 });
320
321 it('should output known testnet address for console', function() {
322 var privkey = PrivateKey.fromWIF('cR4qogdN9UxLZJXCNFNwDRRZNeLRWuds9TTSuLNweFVjiaE4gPaq');
323 privkey.inspect().should.equal(
324 '<PrivateKey: 67fd2209ce4a95f6f1d421ab3fbea47ada13df11b73b30c4d9a9f78cc80651ac, network: testnet>'
325 );
326 });
327
328 it('outputs "uncompressed" for uncompressed imported WIFs', function() {
329 var privkey = PrivateKey.fromWIF(wifLivenetUncompressed);
330 privkey.inspect().should.equal('<PrivateKey: 96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a, network: livenet, uncompressed>');
331 });
332 });
333
334 describe('#getValidationError', function(){
335 it('should get an error because private key greater than N', function() {
336 var n = Point.getN();
337 var a = PrivateKey.getValidationError(n);
338 a.message.should.equal('Number must be less than N');
339 });
340
341 it('should validate as false because private key greater than N', function() {
342 var n = Point.getN();
343 var a = PrivateKey.isValid(n);
344 a.should.equal(false);
345 });
346
347 it('should recognize that undefined is an invalid private key', function() {
348 PrivateKey.isValid().should.equal(false);
349 });
350
351 it('should validate as true', function() {
352 var a = PrivateKey.isValid('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m');
353 a.should.equal(true);
354 });
355
356 });
357
358 describe('buffer serialization', function() {
359 it('returns an expected value when creating a PrivateKey from a buffer', function() {
360 var privkey = new PrivateKey(BN.fromBuffer(buf), 'livenet');
361 privkey.toString().should.equal(buf.toString('hex'));
362 });
363
364 it('roundtrips correctly when using toBuffer/fromBuffer', function() {
365 var privkey = new PrivateKey(BN.fromBuffer(buf));
366 var toBuffer = new PrivateKey(privkey.toBuffer());
367 var fromBuffer = PrivateKey.fromBuffer(toBuffer.toBuffer());
368 fromBuffer.toString().should.equal(privkey.toString());
369 });
370
371 it('will output a 31 byte buffer', function() {
372 var bn = BN.fromBuffer(Buffer.from('9b5a0e8fee1835e21170ce1431f9b6f19b487e67748ed70d8a4462bc031915', 'hex'));
373 var privkey = new PrivateKey(bn);
374 var buffer = privkey.toBufferNoPadding();
375 buffer.length.should.equal(31);
376 });
377
378 // TODO: enable for v1.0.0 when toBuffer is changed to always be 32 bytes long
379 // it('will output a 32 byte buffer', function() {
380 // var bn = BN.fromBuffer(new Buffer('9b5a0e8fee1835e21170ce1431f9b6f19b487e67748ed70d8a4462bc031915', 'hex'));
381 // var privkey = new PrivateKey(bn);
382 // var buffer = privkey.toBuffer();
383 // buffer.length.should.equal(32);
384 // });
385
386 // TODO: enable for v1.0.0 when toBuffer is changed to always be 32 bytes long
387 // it('should return buffer with length equal 32', function() {
388 // var bn = BN.fromBuffer(buf.slice(0, 31));
389 // var privkey = new PrivateKey(bn, 'livenet');
390 // var expected = Buffer.concat([ new Buffer([0]), buf.slice(0, 31) ]);
391 // privkey.toBuffer().toString('hex').should.equal(expected.toString('hex'));
392 // });
393 });
394
395 describe('#toBigNumber', function() {
396 it('should output known BN', function() {
397 var a = BN.fromBuffer(buf);
398 var privkey = new PrivateKey(a, 'livenet');
399 var b = privkey.toBigNumber();
400 b.toString('hex').should.equal(a.toString('hex'));
401 });
402 });
403
404 describe('#fromRandom', function() {
405
406 it('should set bn gt 0 and lt n, and should be compressed', function() {
407 var privkey = PrivateKey.fromRandom();
408 privkey.bn.gt(new BN(0)).should.equal(true);
409 privkey.bn.lt(Point.getN()).should.equal(true);
410 privkey.compressed.should.equal(true);
411 });
412
413 });
414
415 describe('#fromWIF', function() {
416
417 it('should parse this compressed testnet address correctly', function() {
418 var privkey = PrivateKey.fromWIF(wifLivenet);
419 privkey.toWIF().should.equal(wifLivenet);
420 });
421
422 });
423
424 describe('#toWIF', function() {
425
426 it('should parse this compressed testnet address correctly', function() {
427 var privkey = PrivateKey.fromWIF(wifTestnet);
428 privkey.toWIF().should.equal(wifTestnet);
429 });
430
431 });
432
433 describe('#fromString', function() {
434
435 it('should parse this uncompressed testnet address correctly', function() {
436 var privkey = PrivateKey.fromString(wifTestnetUncompressed);
437 privkey.toWIF().should.equal(wifTestnetUncompressed);
438 });
439
440 });
441
442 describe('#toString', function() {
443
444 it('should parse this uncompressed livenet address correctly', function() {
445 var privkey = PrivateKey.fromString(wifLivenetUncompressed);
446 privkey.toString().should.equal("96c132224121b509b7d0a16245e957d9192609c5637c6228311287b1be21627a");
447 });
448
449 });
450
451 describe('#toPublicKey', function() {
452
453 it('should convert this known PrivateKey to known PublicKey', function() {
454 var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
455 var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
456 var privkey = new PrivateKey(new BN(Buffer.from(privhex, 'hex')));
457 var pubkey = privkey.toPublicKey();
458 pubkey.toString().should.equal(pubhex);
459 });
460
461 it('should have a "publicKey" property', function() {
462 var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff';
463 var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc';
464 var privkey = new PrivateKey(new BN(Buffer.from(privhex, 'hex')));
465 privkey.publicKey.toString().should.equal(pubhex);
466 });
467
468 it('should convert this known PrivateKey to known PublicKey and preserve compressed=true', function() {
469 var privwif = 'L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m';
470 var privkey = new PrivateKey(privwif, 'livenet');
471 var pubkey = privkey.toPublicKey();
472 pubkey.compressed.should.equal(true);
473 });
474
475 it('should convert this known PrivateKey to known PublicKey and preserve compressed=false', function() {
476 var privwif = '92jJzK4tbURm1C7udQXxeCBvXHoHJstDXRxAMouPG1k1XUaXdsu';
477 var privkey = new PrivateKey(privwif, 'testnet');
478 var pubkey = privkey.toPublicKey();
479 pubkey.compressed.should.equal(false);
480 });
481
482 });
483
484 it('creates an address as expected from WIF, livenet', function() {
485 var privkey = new PrivateKey('5J2NYGstJg7aJQEqNwYp4enG5BSfFdKXVTtBLvHicnRGD5kjxi6');
486 privkey.publicKey.toAddress().toString().should.equal('135bwugFCmhmNU3SeCsJeTqvo5ViymgwZ9');
487 });
488
489 it('creates an address as expected from WIF, testnet', function() {
490 var privkey = new PrivateKey('92VYMmwFLXRwXn5688edGxYYgMFsc3fUXYhGp17WocQhU6zG1kd');
491 privkey.publicKey.toAddress().toString().should.equal('moiAvLUw16qgrwhFGo1eDnXHC2wPMYiv7Y');
492 });
493
494});