You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.1 KiB
100 lines
3.1 KiB
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const NETWORKS = require("./networks");
|
|
const types = require("./types");
|
|
const ecc = require('tiny-secp256k1');
|
|
const randomBytes = require('randombytes');
|
|
const typeforce = require('typeforce');
|
|
const wif = require('wif');
|
|
const isOptions = typeforce.maybe(typeforce.compile({
|
|
compressed: types.maybe(types.Boolean),
|
|
network: types.maybe(types.Network),
|
|
}));
|
|
class ECPair {
|
|
constructor(d, Q, options) {
|
|
if (options === undefined)
|
|
options = {};
|
|
this.compressed =
|
|
options.compressed === undefined ? true : options.compressed;
|
|
this.network = options.network || NETWORKS.bitcoin;
|
|
this.__D = undefined;
|
|
this.__Q = undefined;
|
|
if (d !== undefined)
|
|
this.__D = d;
|
|
if (Q !== undefined)
|
|
this.__Q = ecc.pointCompress(Q, this.compressed);
|
|
}
|
|
get privateKey() {
|
|
return this.__D;
|
|
}
|
|
get publicKey() {
|
|
if (!this.__Q)
|
|
this.__Q = ecc.pointFromScalar(this.__D, this.compressed);
|
|
return this.__Q;
|
|
}
|
|
toWIF() {
|
|
if (!this.__D)
|
|
throw new Error('Missing private key');
|
|
return wif.encode(this.network.wif, this.__D, this.compressed);
|
|
}
|
|
sign(hash) {
|
|
if (!this.__D)
|
|
throw new Error('Missing private key');
|
|
return ecc.sign(hash, this.__D);
|
|
}
|
|
verify(hash, signature) {
|
|
return ecc.verify(hash, this.publicKey, signature);
|
|
}
|
|
}
|
|
function fromPrivateKey(buffer, options) {
|
|
typeforce(types.Buffer256bit, buffer);
|
|
if (!ecc.isPrivate(buffer))
|
|
throw new TypeError('Private key not in range [1, n)');
|
|
typeforce(isOptions, options);
|
|
return new ECPair(buffer, undefined, options);
|
|
}
|
|
exports.fromPrivateKey = fromPrivateKey;
|
|
function fromPublicKey(buffer, options) {
|
|
typeforce(ecc.isPoint, buffer);
|
|
typeforce(isOptions, options);
|
|
return new ECPair(undefined, buffer, options);
|
|
}
|
|
exports.fromPublicKey = fromPublicKey;
|
|
function fromWIF(wifString, network) {
|
|
const decoded = wif.decode(wifString);
|
|
const version = decoded.version;
|
|
// list of networks?
|
|
if (types.Array(network)) {
|
|
network = network
|
|
.filter((x) => {
|
|
return version === x.wif;
|
|
})
|
|
.pop();
|
|
if (!network)
|
|
throw new Error('Unknown network version');
|
|
// otherwise, assume a network object (or default to bitcoin)
|
|
}
|
|
else {
|
|
network = network || NETWORKS.bitcoin;
|
|
if (version !== network.wif)
|
|
throw new Error('Invalid network version');
|
|
}
|
|
return fromPrivateKey(decoded.privateKey, {
|
|
compressed: decoded.compressed,
|
|
network: network,
|
|
});
|
|
}
|
|
exports.fromWIF = fromWIF;
|
|
function makeRandom(options) {
|
|
typeforce(isOptions, options);
|
|
if (options === undefined)
|
|
options = {};
|
|
const rng = options.rng || randomBytes;
|
|
let d;
|
|
do {
|
|
d = rng(32);
|
|
typeforce(types.Buffer256bit, d);
|
|
} while (!ecc.isPrivate(d));
|
|
return fromPrivateKey(d, options);
|
|
}
|
|
exports.makeRandom = makeRandom;
|
|
|