Skip to content

CynegeticIO/key-tree

 
 

Repository files navigation

@metamask/key-tree

An interface over SLIP-10 and BIP-44 key derivation paths.

Installation

yarn add @metamask/key-tree

or

npm install @metamask/key-tree

Usage

This package is designed to accommodate the creation of keys for any level of a SLIP-10 or BIP-44 path. Recall that a BIP-44 HD tree path consists of the following nodes (and depths):

m / 44' / coin_type' / account' / change / address_index

0 / 1 / 2 / 3 / 4 / 5

Where m is the "master" or seed node, coin_type indicates the protocol for which deeper keys are intended, and address_index usually furnishes key pairs intended for user addresses / accounts. For details, refer to the BIP-44 specification. For the authoritative list of protocol coin_type indices, see SLIP-44.

The SLIP-10 interface provides a more generic way for deriving keys, which is not constrained to the BIP-44 path nodes. Currently only Secp256k1 and Ed25519 are supported for SLIP-10, but NIST P-256 may be added if there is sufficient demand for it.

This package exports a few classes intended to facilitate the creation of keys in contexts with different privileges. They are used as follows.

import { BIP44CoinTypeNode } from '@metamask/key-tree';

// Per SLIP-44, Ethereum has a coin_type of 60.
// Ethereum is only used by way of example.
const coinType = 60;

// Imagine that this takes place in some privileged context with access to
// the user's mnemonic.
const mnemonic = getMnemonic();

const coinTypeNode = await BIP44CoinTypeNode.fromDerivationPath([
  `bip39:${mnemonic}`,
  `bip32:44'`, // By BIP-44, the "purpose" node must be "44'"
  `bip32:${coinType}'`,
]);

// Imagine that this is some Node.js stream, but it could be anything that
// can transmit JSON messages, such as window.postMessage.
// Alternatively you can use `coinTypeNode.extendedKey` as well.
stream.write(coinTypeNode.toJSON());

//===============================
// Then, on the receiving end...
//===============================

import { getBIP44AddressKeyDeriver } from '@metamask/key-tree';

// Get the node sent from the privileged context.
// It will have the following shape:
//   {
//     privateKey, // A hexadecimal string of the private key
//     publicKey, // A hexadecimal string of the public key
//     chainCode, // A hexadecimal string of the chain code
//     depth, // The number 2, which is the depth of coin_type nodes
//     parentFingerprint, // The fingerprint of the parent node as number
//     index, // The index of the node as number
//     coin_type, // In this case, the number 60
//     path, // For visualization only. In this case: m / 44' / 60'
//   }
const coinTypeNode = await getCoinTypeNode();

// Get an address key deriver for the coin_type node.
// In this case, its path will be: m / 44' / 60' / 0' / 0 / address_index
// Alternatively you can use an extended key (`xprv`) as well.
const addressKeyDeriver = getBIP44AddressKeyDeriver(coinTypeNode);

// These are Node.js Buffer representations of the extended private keys for
// the respective addresses.

// m / 44' / 60' / 0' / 0 / 0
const addressKey0 = await addressKeyDeriver(0);

// m / 44' / 60' / 0' / 0 / 1
const addressKey1 = await addressKeyDeriver(1);

// m / 44' / 60' / 0' / 0 / 2'
const addressKey2 = await addressKeyDeriver(2, true);

// Now, the extended private keys can be used to derive the corresponding public
// keys and protocol addresses.

You can derive SLIP-10 keys as follows.

import { SLIP10Node } from '@metamask/key-tree';

// Create a SLIP10Node from a derivation path. You can also specify a key and depth instead.
const node = await SLIP10Node.fromDerivationPath({
  curve: 'secp256k1', // or 'ed25519'
  derivationPath: [`bip39:${mnemonic}`, `bip32:0'`],
});

// Derive the child node at m / 0' / 1' / 2'. This results in a new SLIP10Node.
// Note that you cannot derive unhardened child nodes when using Ed25519
const childNode = await node.derive([`bip32:1'`, `bip32:2'`]);

There are other ways of deriving keys in addition to the above example. See the docstrings in the BIP44Node, BIP44CoinTypeNode and SLIP10Node files for details.

Internals

This package also has methods for deriving arbitrary BIP-32 keys, and generating seeds from BIP-39 mnemonics. These methods do not constitute a safe key derivation API, and their use is strongly discouraged. Nevertheless, since those methods were the main exports of this package prior to version 3.0.0, consumers can still access them by importing @metamask/key-tree/derivation.

Security

This package is rigorously tested against reference implementations and the BIP-32 specification. See the reference implementation tests for details.

Further Reading

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 98.9%
  • JavaScript 1.1%