UNPKG

14.6 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const crypto = require("./crypto");
4const testecc_1 = require("./testecc");
5const bs58check = require('bs58check');
6const typeforce = require('typeforce');
7const wif = require('wif');
8function BIP32Factory(ecc) {
9 testecc_1.testEcc(ecc);
10 const UINT256_TYPE = typeforce.BufferN(32);
11 const NETWORK_TYPE = typeforce.compile({
12 wif: typeforce.UInt8,
13 bip32: {
14 public: typeforce.UInt32,
15 private: typeforce.UInt32,
16 },
17 });
18 const BITCOIN = {
19 messagePrefix: '\x18Bitcoin Signed Message:\n',
20 bech32: 'bc',
21 bip32: {
22 public: 0x0488b21e,
23 private: 0x0488ade4,
24 },
25 pubKeyHash: 0x00,
26 scriptHash: 0x05,
27 wif: 0x80,
28 };
29 const HIGHEST_BIT = 0x80000000;
30 const UINT31_MAX = Math.pow(2, 31) - 1;
31 function BIP32Path(value) {
32 return (typeforce.String(value) && value.match(/^(m\/)?(\d+'?\/)*\d+'?$/) !== null);
33 }
34 function UInt31(value) {
35 return typeforce.UInt32(value) && value <= UINT31_MAX;
36 }
37 function toXOnly(pubKey) {
38 return pubKey.length === 32 ? pubKey : pubKey.slice(1, 33);
39 }
40 class Bip32Signer {
41 constructor(__D, __Q) {
42 this.__D = __D;
43 this.__Q = __Q;
44 this.lowR = false;
45 }
46 get publicKey() {
47 if (this.__Q === undefined)
48 this.__Q = Buffer.from(ecc.pointFromScalar(this.__D, true));
49 return this.__Q;
50 }
51 get privateKey() {
52 return this.__D;
53 }
54 sign(hash, lowR) {
55 if (!this.privateKey)
56 throw new Error('Missing private key');
57 if (lowR === undefined)
58 lowR = this.lowR;
59 if (lowR === false) {
60 return Buffer.from(ecc.sign(hash, this.privateKey));
61 }
62 else {
63 let sig = Buffer.from(ecc.sign(hash, this.privateKey));
64 const extraData = Buffer.alloc(32, 0);
65 let counter = 0;
66 // if first try is lowR, skip the loop
67 // for second try and on, add extra entropy counting up
68 while (sig[0] > 0x7f) {
69 counter++;
70 extraData.writeUIntLE(counter, 0, 6);
71 sig = Buffer.from(ecc.sign(hash, this.privateKey, extraData));
72 }
73 return sig;
74 }
75 }
76 signSchnorr(hash) {
77 if (!this.privateKey)
78 throw new Error('Missing private key');
79 if (!ecc.signSchnorr)
80 throw new Error('signSchnorr not supported by ecc library');
81 return Buffer.from(ecc.signSchnorr(hash, this.privateKey));
82 }
83 verify(hash, signature) {
84 return ecc.verify(hash, this.publicKey, signature);
85 }
86 verifySchnorr(hash, signature) {
87 if (!ecc.verifySchnorr)
88 throw new Error('verifySchnorr not supported by ecc library');
89 return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature);
90 }
91 }
92 class BIP32 extends Bip32Signer {
93 constructor(__D, __Q, chainCode, network, __DEPTH = 0, __INDEX = 0, __PARENT_FINGERPRINT = 0x00000000) {
94 super(__D, __Q);
95 this.chainCode = chainCode;
96 this.network = network;
97 this.__DEPTH = __DEPTH;
98 this.__INDEX = __INDEX;
99 this.__PARENT_FINGERPRINT = __PARENT_FINGERPRINT;
100 typeforce(NETWORK_TYPE, network);
101 }
102 get depth() {
103 return this.__DEPTH;
104 }
105 get index() {
106 return this.__INDEX;
107 }
108 get parentFingerprint() {
109 return this.__PARENT_FINGERPRINT;
110 }
111 get identifier() {
112 return crypto.hash160(this.publicKey);
113 }
114 get fingerprint() {
115 return this.identifier.slice(0, 4);
116 }
117 get compressed() {
118 return true;
119 }
120 // Private === not neutered
121 // Public === neutered
122 isNeutered() {
123 return this.__D === undefined;
124 }
125 neutered() {
126 return fromPublicKeyLocal(this.publicKey, this.chainCode, this.network, this.depth, this.index, this.parentFingerprint);
127 }
128 toBase58() {
129 const network = this.network;
130 const version = !this.isNeutered()
131 ? network.bip32.private
132 : network.bip32.public;
133 const buffer = Buffer.allocUnsafe(78);
134 // 4 bytes: version bytes
135 buffer.writeUInt32BE(version, 0);
136 // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ....
137 buffer.writeUInt8(this.depth, 4);
138 // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
139 buffer.writeUInt32BE(this.parentFingerprint, 5);
140 // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
141 // This is encoded in big endian. (0x00000000 if master key)
142 buffer.writeUInt32BE(this.index, 9);
143 // 32 bytes: the chain code
144 this.chainCode.copy(buffer, 13);
145 // 33 bytes: the public key or private key data
146 if (!this.isNeutered()) {
147 // 0x00 + k for private keys
148 buffer.writeUInt8(0, 45);
149 this.privateKey.copy(buffer, 46);
150 // 33 bytes: the public key
151 }
152 else {
153 // X9.62 encoding for public keys
154 this.publicKey.copy(buffer, 45);
155 }
156 return bs58check.encode(buffer);
157 }
158 toWIF() {
159 if (!this.privateKey)
160 throw new TypeError('Missing private key');
161 return wif.encode(this.network.wif, this.privateKey, true);
162 }
163 // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions
164 derive(index) {
165 typeforce(typeforce.UInt32, index);
166 const isHardened = index >= HIGHEST_BIT;
167 const data = Buffer.allocUnsafe(37);
168 // Hardened child
169 if (isHardened) {
170 if (this.isNeutered())
171 throw new TypeError('Missing private key for hardened child key');
172 // data = 0x00 || ser256(kpar) || ser32(index)
173 data[0] = 0x00;
174 this.privateKey.copy(data, 1);
175 data.writeUInt32BE(index, 33);
176 // Normal child
177 }
178 else {
179 // data = serP(point(kpar)) || ser32(index)
180 // = serP(Kpar) || ser32(index)
181 this.publicKey.copy(data, 0);
182 data.writeUInt32BE(index, 33);
183 }
184 const I = crypto.hmacSHA512(this.chainCode, data);
185 const IL = I.slice(0, 32);
186 const IR = I.slice(32);
187 // if parse256(IL) >= n, proceed with the next value for i
188 if (!ecc.isPrivate(IL))
189 return this.derive(index + 1);
190 // Private parent key -> private child key
191 let hd;
192 if (!this.isNeutered()) {
193 // ki = parse256(IL) + kpar (mod n)
194 const ki = Buffer.from(ecc.privateAdd(this.privateKey, IL));
195 // In case ki == 0, proceed with the next value for i
196 if (ki == null)
197 return this.derive(index + 1);
198 hd = fromPrivateKeyLocal(ki, IR, this.network, this.depth + 1, index, this.fingerprint.readUInt32BE(0));
199 // Public parent key -> public child key
200 }
201 else {
202 // Ki = point(parse256(IL)) + Kpar
203 // = G*IL + Kpar
204 const Ki = Buffer.from(ecc.pointAddScalar(this.publicKey, IL, true));
205 // In case Ki is the point at infinity, proceed with the next value for i
206 if (Ki === null)
207 return this.derive(index + 1);
208 hd = fromPublicKeyLocal(Ki, IR, this.network, this.depth + 1, index, this.fingerprint.readUInt32BE(0));
209 }
210 return hd;
211 }
212 deriveHardened(index) {
213 typeforce(UInt31, index);
214 // Only derives hardened private keys by default
215 return this.derive(index + HIGHEST_BIT);
216 }
217 derivePath(path) {
218 typeforce(BIP32Path, path);
219 let splitPath = path.split('/');
220 if (splitPath[0] === 'm') {
221 if (this.parentFingerprint)
222 throw new TypeError('Expected master, got child');
223 splitPath = splitPath.slice(1);
224 }
225 return splitPath.reduce((prevHd, indexStr) => {
226 let index;
227 if (indexStr.slice(-1) === `'`) {
228 index = parseInt(indexStr.slice(0, -1), 10);
229 return prevHd.deriveHardened(index);
230 }
231 else {
232 index = parseInt(indexStr, 10);
233 return prevHd.derive(index);
234 }
235 }, this);
236 }
237 tweak(t) {
238 if (this.privateKey)
239 return this.tweakFromPrivateKey(t);
240 return this.tweakFromPublicKey(t);
241 }
242 tweakFromPublicKey(t) {
243 const xOnlyPubKey = toXOnly(this.publicKey);
244 const tweakedPublicKey = ecc.xOnlyPointAddTweak(xOnlyPubKey, t);
245 if (!tweakedPublicKey || tweakedPublicKey.xOnlyPubkey === null)
246 throw new Error('Cannot tweak public key!');
247 const parityByte = Buffer.from([
248 tweakedPublicKey.parity === 0 ? 0x02 : 0x03,
249 ]);
250 const tweakedPublicKeyCompresed = Buffer.concat([
251 parityByte,
252 tweakedPublicKey.xOnlyPubkey,
253 ]);
254 return new Bip32Signer(undefined, tweakedPublicKeyCompresed);
255 }
256 tweakFromPrivateKey(t) {
257 const hasOddY = this.publicKey[0] === 3 ||
258 (this.publicKey[0] === 4 && (this.publicKey[64] & 1) === 1);
259 const privateKey = hasOddY
260 ? ecc.privateNegate(this.privateKey)
261 : this.privateKey;
262 const tweakedPrivateKey = ecc.privateAdd(privateKey, t);
263 if (!tweakedPrivateKey)
264 throw new Error('Invalid tweaked private key!');
265 return new Bip32Signer(Buffer.from(tweakedPrivateKey), undefined);
266 }
267 }
268 function fromBase58(inString, network) {
269 const buffer = bs58check.decode(inString);
270 if (buffer.length !== 78)
271 throw new TypeError('Invalid buffer length');
272 network = network || BITCOIN;
273 // 4 bytes: version bytes
274 const version = buffer.readUInt32BE(0);
275 if (version !== network.bip32.private && version !== network.bip32.public)
276 throw new TypeError('Invalid network version');
277 // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
278 const depth = buffer[4];
279 // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
280 const parentFingerprint = buffer.readUInt32BE(5);
281 if (depth === 0) {
282 if (parentFingerprint !== 0x00000000)
283 throw new TypeError('Invalid parent fingerprint');
284 }
285 // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
286 // This is encoded in MSB order. (0x00000000 if master key)
287 const index = buffer.readUInt32BE(9);
288 if (depth === 0 && index !== 0)
289 throw new TypeError('Invalid index');
290 // 32 bytes: the chain code
291 const chainCode = buffer.slice(13, 45);
292 let hd;
293 // 33 bytes: private key data (0x00 + k)
294 if (version === network.bip32.private) {
295 if (buffer.readUInt8(45) !== 0x00)
296 throw new TypeError('Invalid private key');
297 const k = buffer.slice(46, 78);
298 hd = fromPrivateKeyLocal(k, chainCode, network, depth, index, parentFingerprint);
299 // 33 bytes: public key data (0x02 + X or 0x03 + X)
300 }
301 else {
302 const X = buffer.slice(45, 78);
303 hd = fromPublicKeyLocal(X, chainCode, network, depth, index, parentFingerprint);
304 }
305 return hd;
306 }
307 function fromPrivateKey(privateKey, chainCode, network) {
308 return fromPrivateKeyLocal(privateKey, chainCode, network);
309 }
310 function fromPrivateKeyLocal(privateKey, chainCode, network, depth, index, parentFingerprint) {
311 typeforce({
312 privateKey: UINT256_TYPE,
313 chainCode: UINT256_TYPE,
314 }, { privateKey, chainCode });
315 network = network || BITCOIN;
316 if (!ecc.isPrivate(privateKey))
317 throw new TypeError('Private key not in range [1, n)');
318 return new BIP32(privateKey, undefined, chainCode, network, depth, index, parentFingerprint);
319 }
320 function fromPublicKey(publicKey, chainCode, network) {
321 return fromPublicKeyLocal(publicKey, chainCode, network);
322 }
323 function fromPublicKeyLocal(publicKey, chainCode, network, depth, index, parentFingerprint) {
324 typeforce({
325 publicKey: typeforce.BufferN(33),
326 chainCode: UINT256_TYPE,
327 }, { publicKey, chainCode });
328 network = network || BITCOIN;
329 // verify the X coordinate is a point on the curve
330 if (!ecc.isPoint(publicKey))
331 throw new TypeError('Point is not on the curve');
332 return new BIP32(undefined, publicKey, chainCode, network, depth, index, parentFingerprint);
333 }
334 function fromSeed(seed, network) {
335 typeforce(typeforce.Buffer, seed);
336 if (seed.length < 16)
337 throw new TypeError('Seed should be at least 128 bits');
338 if (seed.length > 64)
339 throw new TypeError('Seed should be at most 512 bits');
340 network = network || BITCOIN;
341 const I = crypto.hmacSHA512(Buffer.from('Bitcoin seed', 'utf8'), seed);
342 const IL = I.slice(0, 32);
343 const IR = I.slice(32);
344 return fromPrivateKey(IL, IR, network);
345 }
346 return {
347 fromSeed,
348 fromBase58,
349 fromPublicKey,
350 fromPrivateKey,
351 };
352}
353exports.BIP32Factory = BIP32Factory;