@crpdo/key
Version:
Streamlines key generation, derivation, and management through its simple and intuitive API
173 lines (156 loc) • 5.47 kB
JavaScript
const Nacl = require('@crpdo/crypto/nacl')
const CoinUtils = require('@crpdo/coins')
const BaseKey = require('./base-key')
const HDKey = require('hdkey')
const { _: { _, log }} = require('@crpdo/crypto')
/**
* Class representing a Hierarchical Deterministic Key (HdKey)
* @extends BaseKey
*/
class HdKey extends BaseKey {
static get HDKey() { return HDKey }
/**
* Create a HdKey.
* @param {string} seed - The seed to initialize the HdKey.
*/
constructor(seed) {
super(seed.startsWith('xprv') ? HDKey.fromExtendedKey(seed) : HDKey.fromMasterSeed(seed))
}
/**
* Get the depth of the key derivation.
* @return {number} The depth of the key.
*/
get depth() {
return this.key.depth
}
/**
* Get the public key.
* @return {string} The public key.
*/
get publicKey() {
return this.key.publicExtendedKey
}
/**
* Get the private key.
* @return {string} The private key.
*/
get privateKey() {
return this.key.privateExtendedKey
}
/**
* Get the public extended key.
* @return {string} The public extended key.
*/
get publicExtendedKey() {
return this.key.publicExtendedKey
}
/**
* Get the private extended key.
* @return {string} The private extended key.
*/
get privateExtendedKey() {
return this.key.privateExtendedKey
}
/**
* Derive a new key from the current key.
* @param {string} path - The derivation path.
* @return {HDKey} The derived key.
*/
derive(path) {
return this.key.derive(path)
}
/**
* Sign a piece of data with this key.
* @param {string|Buffer} data - The data to sign.
* @return {string} The signature.
*/
sign(data) {
if (!_.isBinary(data) || data.length !== _.BYTE_LENGTH)
data = _.hash(data, _.BYTE_LENGTH, false)
const signature = this.key.sign(data)
return _.encode(signature)
}
/**
* Verify a signature on a piece of data with this key.
* @param {string|Buffer} data - The data whose signature to verify.
* @param {string} signature - The signature to verify.
* @param {HDKey} publicKey - The public key to verify the signature against.
* @return {boolean} Whether the signature is valid.
*/
verify(data, signature, publicKey) {
if (!_.isBinary(data) || data.length !== _.BYTE_LENGTH)
data = _.hash(data, _.BYTE_LENGTH, false)
publicKey = publicKey || this.key.publicExtendedKey
if (!(publicKey instanceof HDKey))
publicKey = HDKey.fromExtendedKey(publicKey)
signature = _.isString(signature) ? _.decode(signature) : signature
return publicKey.verify(data, signature)
}
/**
* Derive a softened key from the current key.
* @param {string} coinSymbol - The coin symbol, default is 'BTC'.
* @param {number} account - The account number, default is 0.
* @param {number} change - The change number, default is 0.
* @param {number} index - The index number.
* @return {HDKey} The derived softened key.
*/
deriveSoftened(coinSymbol = 'BTC', account = 0, change = 0, index) {
return HdKey.deriveSoftenedNode(this.key, coinSymbol, account, change, index)
}
/**
* Derive a softened public key from the current key.
* @param {string} coinSymbol - The coin symbol, default is 'BTC'.
* @param {number} account - The account number, default is 0.
* @param {number} change - The change number, default is 0.
* @param {number} index - The index number.
* @return {string} The derived softened public key.
*/
deriveSoftenedPublicKey(coinSymbol = 'BTC', account = 0, change = 0, index) {
return HdKey.deriveSoftenedPublicKey(this.key, coinSymbol, account, change, index)
}
/**
* Derives a node from an input and path.
* @static
* @param {HDKey | string} input - The input to derive the node from, either an instance of HDKey or a string to create an HDKey from.
* @param {string} [path='m'] - The path to derive the node at.
* @return {HDKey} The derived node.
*/
static deriveNode(input, path = 'm') {
if (!(input instanceof HDKey))
input = HDKey.fromExtendedKey(input)
return input.derive(path)
}
/**
* Derives a softened node from an input and additional arguments.
* @static
* @param {HDKey | string} input - The input to derive the softened node from, either an instance of HDKey or a string to create an HDKey from.
* @param {...any} args - The additional arguments for deriving the path.
* @return {HDKey} The derived softened node.
*/
static deriveSoftenedNode(input, ...args) {
const derivePath = CoinUtils.getDerivePath(...args)
const node = this.deriveNode(input, derivePath)
this.neuterNode(node)
return node
}
/**
* Derives a softened public key from an input and additional arguments.
* @static
* @param {HDKey | string} input - The input to derive the softened public key from, either an instance of HDKey or a string to create an HDKey from.
* @param {...any} args - The additional arguments for deriving the path.
* @return {string} The derived softened public key.
*/
static deriveSoftenedPublicKey(input, ...args) {
const node = this.deriveSoftenedNode(input, ...args)
return node.publicExtendedKey
}
/**
* Removes private data from a node, rendering it a public node.
* @static
* @param {HDKey} node - The node to neuter.
*/
static neuterNode(node) {
node.wipePrivateData()
}
}
module.exports = HdKey