Support for xpub and xpriv derivation and generating extended keys; no fromExtendedKey yet (#405).
This commit is contained in:
parent
36172f7f7b
commit
18ee2c518c
@ -111,7 +111,7 @@ function taskBundle(name, options) {
|
||||
"elliptic/package.json" : ellipticPackage,
|
||||
|
||||
// Remove RIPEMD160 and unneeded hashing algorithms
|
||||
"hash.js/lib/hash/ripemd.js": "module.exports = {ripemd160: null}",
|
||||
//"hash.js/lib/hash/ripemd.js": "module.exports = {ripemd160: null}",
|
||||
"hash.js/lib/hash/sha/1.js": empty,
|
||||
"hash.js/lib/hash/sha/224.js": empty,
|
||||
"hash.js/lib/hash/sha/384.js": empty,
|
||||
|
143
src.ts/utils/basex.ts
Normal file
143
src.ts/utils/basex.ts
Normal file
@ -0,0 +1,143 @@
|
||||
/**
|
||||
* var basex = require('base-x');
|
||||
*
|
||||
* This implementation is heavily based on base-x. The main reason to
|
||||
* deviate was to prevent the dependency of Buffer.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* base-x encoding
|
||||
* Forked from https://github.com/cryptocoinjs/bs58
|
||||
* Originally written by Mike Hearn for BitcoinJ
|
||||
* Copyright (c) 2011 Google Inc
|
||||
* Ported to JavaScript by Stefan Thomas
|
||||
* Merged Buffer refactorings from base58-native by Stephen Pair
|
||||
* Copyright (c) 2013 BitPay Inc
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright base-x contributors (c) 2016
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
import { arrayify, Arrayish } from "./bytes";
|
||||
import { defineReadOnly } from "./properties";
|
||||
|
||||
export class BaseX {
|
||||
readonly alphabet: string;
|
||||
readonly base: number;
|
||||
|
||||
private _alphabetMap: { [ character: string ]: number };
|
||||
private _leader: string;
|
||||
|
||||
constructor(alphabet: string) {
|
||||
defineReadOnly(this, "alphabet", alphabet);
|
||||
defineReadOnly(this, "base", alphabet.length);
|
||||
|
||||
defineReadOnly(this, "_alphabetMap", { });
|
||||
defineReadOnly(this, "_leader", alphabet.charAt(0));
|
||||
|
||||
// pre-compute lookup table
|
||||
for (let i = 0; i < alphabet.length; i++) {
|
||||
this._alphabetMap[alphabet.charAt(i)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
encode(value: Arrayish | string): string {
|
||||
let source = arrayify(value);
|
||||
|
||||
if (source.length === 0) { return ''; }
|
||||
|
||||
let digits = [ 0 ]
|
||||
for (let i = 0; i < source.length; ++i) {
|
||||
let carry = source[i];
|
||||
for (let j = 0; j < digits.length; ++j) {
|
||||
carry += digits[j] << 8;
|
||||
digits[j] = carry % this.base;
|
||||
carry = (carry / this.base) | 0;
|
||||
}
|
||||
|
||||
while (carry > 0) {
|
||||
digits.push(carry % this.base);
|
||||
carry = (carry / this.base) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
let string = ''
|
||||
|
||||
// deal with leading zeros
|
||||
for (let k = 0; source[k] === 0 && k < source.length - 1; ++k) {
|
||||
string += this._leader;
|
||||
}
|
||||
|
||||
// convert digits to a string
|
||||
for (let q = digits.length - 1; q >= 0; --q) {
|
||||
string += this.alphabet[digits[q]];
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
decode(value: string): Uint8Array {
|
||||
if (typeof(value) !== 'string') {
|
||||
throw new TypeError('Expected String');
|
||||
}
|
||||
|
||||
let bytes: Array<number> = [];
|
||||
if (value.length === 0) { return new Uint8Array(bytes); }
|
||||
|
||||
bytes.push(0);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
let byte = this._alphabetMap[value[i]];
|
||||
|
||||
if (byte === undefined) {
|
||||
throw new Error('Non-base' + this.base + ' character');
|
||||
}
|
||||
|
||||
let carry = byte;
|
||||
for (let j = 0; j < bytes.length; ++j) {
|
||||
carry += bytes[j] * this.base;
|
||||
bytes[j] = carry & 0xff;
|
||||
carry >>= 8;
|
||||
}
|
||||
|
||||
while (carry > 0) {
|
||||
bytes.push(carry & 0xff);
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// deal with leading zeros
|
||||
for (let k = 0; value[k] === this._leader && k < value.length - 1; ++k) {
|
||||
bytes.push(0)
|
||||
}
|
||||
|
||||
return new Uint8Array(bytes.reverse())
|
||||
}
|
||||
}
|
||||
|
||||
const Base32 = new BaseX("abcdefghijklmnopqrstuvwxyz234567");
|
||||
const Base58 = new BaseX("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
||||
|
||||
export { Base32, Base58 };
|
||||
|
||||
//console.log(Base58.decode("Qmd2V777o5XvJbYMeMb8k2nU5f8d3ciUQ5YpYuWhzv8iDj"))
|
||||
//console.log(Base58.encode(Base58.decode("Qmd2V777o5XvJbYMeMb8k2nU5f8d3ciUQ5YpYuWhzv8iDj")))
|
@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||||
@ -13,14 +13,15 @@ import { langEn } from '../wordlists/lang-en';
|
||||
//import { register } from '../wordlists/wordlist';
|
||||
//register(langEn);
|
||||
|
||||
import { arrayify, hexlify } from './bytes';
|
||||
import { bigNumberify } from './bignumber';
|
||||
import { Base58 } from "./basex";
|
||||
import { arrayify, concat, hexDataSlice, hexZeroPad, hexlify } from './bytes';
|
||||
import { BigNumber, bigNumberify } from './bignumber';
|
||||
import { toUtf8Bytes, UnicodeNormalizationForm } from './utf8';
|
||||
import { pbkdf2 } from './pbkdf2';
|
||||
import { computeHmac, SupportedAlgorithms } from './hmac';
|
||||
import { defineReadOnly, isType, setType } from './properties';
|
||||
import { computeAddress, KeyPair } from './secp256k1';
|
||||
import { sha256 } from './sha2';
|
||||
import { ripemd160, sha256 } from './sha2';
|
||||
|
||||
const N = bigNumberify("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
||||
|
||||
@ -30,9 +31,9 @@ import { Wordlist } from './wordlist';
|
||||
|
||||
|
||||
// "Bitcoin seed"
|
||||
var MasterSecret = toUtf8Bytes('Bitcoin seed');
|
||||
const MasterSecret = toUtf8Bytes('Bitcoin seed');
|
||||
|
||||
var HardenedBit = 0x80000000;
|
||||
const HardenedBit = 0x80000000;
|
||||
|
||||
// Returns a byte with the MSB bits set
|
||||
function getUpperMask(bits: number): number {
|
||||
@ -44,16 +45,26 @@ function getLowerMask(bits: number): number {
|
||||
return (1 << bits) - 1;
|
||||
}
|
||||
|
||||
function bytes32(value: Arrayish | BigNumber | number): string {
|
||||
return hexZeroPad(hexlify(value), 32);
|
||||
}
|
||||
|
||||
function base58check(data: Uint8Array): string {
|
||||
let checksum = hexDataSlice(sha256(sha256(data)), 0, 4);
|
||||
return Base58.encode(concat([ data, checksum ]));
|
||||
}
|
||||
|
||||
const _constructorGuard: any = {};
|
||||
|
||||
export const defaultPath = "m/44'/60'/0'/0/0";
|
||||
|
||||
export class HDNode {
|
||||
private readonly keyPair: KeyPair;
|
||||
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
|
||||
readonly fingerprint: string;
|
||||
readonly parentFingerprint: string;
|
||||
|
||||
readonly address: string;
|
||||
|
||||
readonly mnemonic: string;
|
||||
@ -71,21 +82,28 @@ export class HDNode {
|
||||
* - fromMnemonic
|
||||
* - fromSeed
|
||||
*/
|
||||
constructor(constructorGuard: any, privateKey: Arrayish, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string) {
|
||||
constructor(constructorGuard: any, privateKey: string, publicKey: string, parentFingerprint: string, chainCode: string, index: number, depth: number, mnemonic: string, path: string) {
|
||||
errors.checkNew(this, HDNode);
|
||||
|
||||
if (constructorGuard !== _constructorGuard) {
|
||||
throw new Error('HDNode constructor cannot be called directly');
|
||||
}
|
||||
|
||||
defineReadOnly(this, 'keyPair', new KeyPair(privateKey));
|
||||
if (privateKey) {
|
||||
let keyPair = new KeyPair(privateKey);
|
||||
defineReadOnly(this, 'privateKey', keyPair.privateKey);
|
||||
defineReadOnly(this, 'publicKey', keyPair.compressedPublicKey);
|
||||
} else {
|
||||
defineReadOnly(this, 'privateKey', null);
|
||||
defineReadOnly(this, 'publicKey', hexlify(publicKey));
|
||||
}
|
||||
|
||||
defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
defineReadOnly(this, 'parentFingerprint', parentFingerprint);
|
||||
defineReadOnly(this, 'fingerprint', hexDataSlice(ripemd160(sha256(this.publicKey)), 0, 4));
|
||||
|
||||
defineReadOnly(this, 'address', computeAddress(this.publicKey));
|
||||
|
||||
defineReadOnly(this, 'chainCode', hexlify(chainCode));
|
||||
defineReadOnly(this, 'chainCode', chainCode);
|
||||
|
||||
defineReadOnly(this, 'index', index);
|
||||
defineReadOnly(this, 'depth', depth);
|
||||
@ -96,22 +114,43 @@ export class HDNode {
|
||||
setType(this, 'HDNode');
|
||||
}
|
||||
|
||||
get extendedKey(): string {
|
||||
// We only support the mainnet values for now, but if anyone needs
|
||||
// testnet values, let me know. I believe current senitment is that
|
||||
// we should always use mainnet, and use BIP-44 to derive the network
|
||||
// - Mainnet: public=0x0488B21E, private=0x0488ADE4
|
||||
// - Testnet: public=0x043587CF, private=0x04358394
|
||||
|
||||
if (this.depth >= 256) { throw new Error("Depth too large!"); }
|
||||
|
||||
return base58check(concat([
|
||||
((this.privateKey != null) ? "0x0488ADE4": "0x0488B21E"),
|
||||
hexlify(this.depth),
|
||||
this.parentFingerprint,
|
||||
hexZeroPad(hexlify(this.index), 4),
|
||||
this.chainCode,
|
||||
((this.privateKey != null) ? concat([ "0x00", this.privateKey ]): this.publicKey),
|
||||
]));
|
||||
}
|
||||
|
||||
neuter(): HDNode {
|
||||
return new HDNode(_constructorGuard, null, this.publicKey, this.parentFingerprint, this.chainCode, this.index, this.depth, null, this.path);
|
||||
}
|
||||
|
||||
private _derive(index: number): HDNode {
|
||||
|
||||
// Public parent key -> public child key
|
||||
if (!this.privateKey) {
|
||||
if (index >= HardenedBit) { throw new Error('cannot derive child of neutered node'); }
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
var data = new Uint8Array(37);
|
||||
if (index > 0xffffffff) { throw new Error("invalid index - " + String(index)); }
|
||||
|
||||
// Base path
|
||||
var mnemonic = this.mnemonic;
|
||||
var path = this.path;
|
||||
let path = this.path;
|
||||
if (path) { path += '/' + (index & ~HardenedBit); }
|
||||
|
||||
let data = new Uint8Array(37);
|
||||
|
||||
if (index & HardenedBit) {
|
||||
if (!this.privateKey) {
|
||||
throw new Error('cannot derive child of neutered node');
|
||||
}
|
||||
|
||||
// Data = 0x00 || ser_256(k_par)
|
||||
data.set(arrayify(this.privateKey), 1);
|
||||
|
||||
@ -120,39 +159,50 @@ export class HDNode {
|
||||
|
||||
} else {
|
||||
// Data = ser_p(point(k_par))
|
||||
data.set(this.keyPair.publicKeyBytes);
|
||||
data.set(arrayify(this.publicKey));
|
||||
}
|
||||
|
||||
// Data += ser_32(i)
|
||||
for (var i = 24; i >= 0; i -= 8) { data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff); }
|
||||
for (let i = 24; i >= 0; i -= 8) { data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff); }
|
||||
|
||||
var I = computeHmac(SupportedAlgorithms.sha512, this.chainCode, data);
|
||||
var IL = bigNumberify(I.slice(0, 32));
|
||||
var IR = I.slice(32);
|
||||
let I = computeHmac(SupportedAlgorithms.sha512, this.chainCode, data);
|
||||
let IL = I.slice(0, 32);
|
||||
let IR = I.slice(32);
|
||||
|
||||
var ki = IL.add(this.keyPair.privateKey).mod(N);
|
||||
// The private key
|
||||
|
||||
return new HDNode(_constructorGuard, arrayify(ki), IR, index, this.depth + 1, mnemonic, path);
|
||||
let ki: string = null
|
||||
// The public key
|
||||
let Ki: string = null;
|
||||
|
||||
if (this.privateKey) {
|
||||
ki = bytes32(bigNumberify(IL).add(this.privateKey).mod(N));
|
||||
} else {
|
||||
let ek = new KeyPair(hexlify(IL));
|
||||
Ki = ek._addPoint(this.publicKey);
|
||||
}
|
||||
|
||||
return new HDNode(_constructorGuard, ki, Ki, this.fingerprint, bytes32(IR), index, this.depth + 1, this.mnemonic, path);
|
||||
}
|
||||
|
||||
derivePath(path: string): HDNode {
|
||||
var components = path.split('/');
|
||||
let components = path.split('/');
|
||||
|
||||
if (components.length === 0 || (components[0] === 'm' && this.depth !== 0)) {
|
||||
throw new Error('invalid path');
|
||||
throw new Error('invalid path - ' + path);
|
||||
}
|
||||
|
||||
if (components[0] === 'm') { components.shift(); }
|
||||
|
||||
var result: HDNode = this;
|
||||
for (var i = 0; i < components.length; i++) {
|
||||
var component = components[i];
|
||||
let result: HDNode = this;
|
||||
for (let i = 0; i < components.length; i++) {
|
||||
let component = components[i];
|
||||
if (component.match(/^[0-9]+'$/)) {
|
||||
var index = parseInt(component.substring(0, component.length - 1));
|
||||
let index = parseInt(component.substring(0, component.length - 1));
|
||||
if (index >= HardenedBit) { throw new Error('invalid path index - ' + component); }
|
||||
result = result._derive(HardenedBit + index);
|
||||
} else if (component.match(/^[0-9]+$/)) {
|
||||
var index = parseInt(component);
|
||||
let index = parseInt(component);
|
||||
if (index >= HardenedBit) { throw new Error('invalid path index - ' + component); }
|
||||
result = result._derive(index);
|
||||
} else {
|
||||
@ -166,17 +216,19 @@ export class HDNode {
|
||||
static isHDNode(value: any): value is HDNode {
|
||||
return isType(value, 'HDNode');
|
||||
}
|
||||
|
||||
static fromExtendedKey(extendedKey: string): HDNode {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function _fromSeed(seed: Arrayish, mnemonic: string): HDNode {
|
||||
let seedArray: Uint8Array = arrayify(seed);
|
||||
if (seedArray.length < 16 || seedArray.length > 64) { throw new Error('invalid seed'); }
|
||||
|
||||
var I: Uint8Array = arrayify(computeHmac(SupportedAlgorithms.sha512, MasterSecret, seedArray));
|
||||
let I: Uint8Array = arrayify(computeHmac(SupportedAlgorithms.sha512, MasterSecret, seedArray));
|
||||
|
||||
return new HDNode(_constructorGuard, I.slice(0, 32), I.slice(32), 0, 0, mnemonic, 'm');
|
||||
return new HDNode(_constructorGuard, bytes32(I.slice(0, 32)), null, "0x00000000", bytes32(I.slice(32)), 0, 0, mnemonic, 'm');
|
||||
}
|
||||
|
||||
export function fromMnemonic(mnemonic: string, wordlist?: Wordlist): HDNode {
|
||||
@ -193,7 +245,7 @@ export function fromSeed(seed: Arrayish): HDNode {
|
||||
export function mnemonicToSeed(mnemonic: string, password?: string): string {
|
||||
if (!password) { password = ''; }
|
||||
|
||||
var salt = toUtf8Bytes('mnemonic' + password, UnicodeNormalizationForm.NFKD);
|
||||
let salt = toUtf8Bytes('mnemonic' + password, UnicodeNormalizationForm.NFKD);
|
||||
|
||||
return hexlify(pbkdf2(toUtf8Bytes(mnemonic, UnicodeNormalizationForm.NFKD), salt, 2048, 64, 'sha512'));
|
||||
}
|
||||
@ -202,18 +254,18 @@ export function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string
|
||||
if (!wordlist) { wordlist = langEn; }
|
||||
|
||||
errors.checkNormalize();
|
||||
|
||||
var words = wordlist.split(mnemonic);
|
||||
|
||||
let words = wordlist.split(mnemonic);
|
||||
if ((words.length % 3) !== 0) { throw new Error('invalid mnemonic'); }
|
||||
|
||||
var entropy = arrayify(new Uint8Array(Math.ceil(11 * words.length / 8)));
|
||||
let entropy = arrayify(new Uint8Array(Math.ceil(11 * words.length / 8)));
|
||||
|
||||
var offset = 0;
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var index = wordlist.getWordIndex(words[i].normalize('NFKD'));
|
||||
let offset = 0;
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
let index = wordlist.getWordIndex(words[i].normalize('NFKD'));
|
||||
if (index === -1) { throw new Error('invalid mnemonic'); }
|
||||
|
||||
for (var bit = 0; bit < 11; bit++) {
|
||||
for (let bit = 0; bit < 11; bit++) {
|
||||
if (index & (1 << (10 - bit))) {
|
||||
entropy[offset >> 3] |= (1 << (7 - (offset % 8)));
|
||||
}
|
||||
@ -221,12 +273,12 @@ export function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string
|
||||
}
|
||||
}
|
||||
|
||||
var entropyBits = 32 * words.length / 3;
|
||||
let entropyBits = 32 * words.length / 3;
|
||||
|
||||
var checksumBits = words.length / 3;
|
||||
var checksumMask = getUpperMask(checksumBits);
|
||||
let checksumBits = words.length / 3;
|
||||
let checksumMask = getUpperMask(checksumBits);
|
||||
|
||||
var checksum = arrayify(sha256(entropy.slice(0, entropyBits / 8)))[0];
|
||||
let checksum = arrayify(sha256(entropy.slice(0, entropyBits / 8)))[0];
|
||||
checksum &= checksumMask;
|
||||
|
||||
if (checksum !== (entropy[entropy.length - 1] & checksumMask)) {
|
||||
@ -243,10 +295,10 @@ export function entropyToMnemonic(entropy: Arrayish, wordlist?: Wordlist): strin
|
||||
throw new Error('invalid entropy');
|
||||
}
|
||||
|
||||
var indices: Array<number> = [ 0 ];
|
||||
let indices: Array<number> = [ 0 ];
|
||||
|
||||
var remainingBits = 11;
|
||||
for (var i = 0; i < entropy.length; i++) {
|
||||
let remainingBits = 11;
|
||||
for (let i = 0; i < entropy.length; i++) {
|
||||
|
||||
// Consume the whole byte (with still more to go)
|
||||
if (remainingBits > 8) {
|
||||
@ -268,8 +320,8 @@ export function entropyToMnemonic(entropy: Arrayish, wordlist?: Wordlist): strin
|
||||
}
|
||||
|
||||
// Compute the checksum bits
|
||||
var checksum = arrayify(sha256(entropy))[0];
|
||||
var checksumBits = entropy.length / 4;
|
||||
let checksum = arrayify(sha256(entropy))[0];
|
||||
let checksumBits = entropy.length / 4;
|
||||
checksum &= getUpperMask(checksumBits);
|
||||
|
||||
// Shift the checksum into the word indices
|
||||
|
@ -62,6 +62,12 @@ export class KeyPair {
|
||||
let otherKeyPair = getCurve().keyFromPublic(arrayify(computePublicKey(otherKey)));
|
||||
return hexZeroPad('0x' + keyPair.derive(otherKeyPair.getPublic()).toString(16), 32);
|
||||
}
|
||||
|
||||
_addPoint(other: Arrayish | string): string {
|
||||
let p0 = getCurve().keyFromPublic(arrayify(this.publicKey));
|
||||
let p1 = getCurve().keyFromPublic(arrayify(other));
|
||||
return "0x" + p0.pub.add(p1.pub).encodeCompressed("hex");
|
||||
}
|
||||
}
|
||||
|
||||
export function computePublicKey(key: Arrayish | string, compressed?: boolean): string {
|
||||
|
@ -7,6 +7,10 @@ import { arrayify } from './bytes';
|
||||
// Types
|
||||
import { Arrayish } from './bytes';
|
||||
|
||||
export function ripemd160(data: Arrayish): string {
|
||||
return '0x' + (hash.ripemd160().update(arrayify(data)).digest('hex'));
|
||||
}
|
||||
|
||||
export function sha256(data: Arrayish): string {
|
||||
return '0x' + (hash.sha256().update(arrayify(data)).digest('hex'));
|
||||
}
|
||||
|
8
thirdparty.d.ts
vendored
8
thirdparty.d.ts
vendored
@ -65,6 +65,11 @@ declare module "elliptic" {
|
||||
recoveryParam: number
|
||||
}
|
||||
|
||||
interface Point {
|
||||
add(point: Point): Point;
|
||||
encodeCompressed(enc: string): string
|
||||
}
|
||||
|
||||
interface KeyPair {
|
||||
sign(message: Uint8Array, options: { canonical?: boolean }): Signature;
|
||||
getPublic(compressed: boolean, encoding?: string): string;
|
||||
@ -72,6 +77,7 @@ declare module "elliptic" {
|
||||
getPrivate(encoding?: string): string;
|
||||
encode(encoding: string, compressed: boolean): string;
|
||||
derive(publicKey: BN): BN;
|
||||
pub: Point;
|
||||
priv: BN;
|
||||
}
|
||||
|
||||
@ -83,6 +89,8 @@ declare module "elliptic" {
|
||||
keyFromPublic(publicKey: string | Uint8Array): KeyPair;
|
||||
keyFromPrivate(privateKey: string | Uint8Array): KeyPair;
|
||||
recoverPubKey(data: Uint8Array, signature: BasicSignature, recoveryParam: number): KeyPair;
|
||||
|
||||
// curve: Curve;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user