import { Point, getPublicKey as secp256k1_getPublicKey } from '@noble/secp256k1'
+type Curve = 'Bitcoin seed' | 'ed25519 seed'
type ExtendedKey = {
privateKey: ArrayBuffer
chainCode: ArrayBuffer
publicKey?: ArrayBuffer
}
-
-type Curve = 'Bitcoin seed' | 'ed25519 seed'
-
const BIP44_PURPOSE: 44 = 44
const HARDENED_OFFSET: 0x80000000 = 0x80000000
* @param {number} [address] - Sequentially increasing index of addresses to use for each account
* @returns {Promise<ArrayBuffer>} Private child key for the account
*/
-export function ckd (curve: Curve, seed: ArrayBuffer, coin: number, account: number, change?: number, address?: number): Promise<ArrayBuffer> {
+export function Bip44 (curve: Curve, seed: ArrayBuffer, coin: number, account: number, change?: number, address?: number): Promise<ArrayBuffer>
+export function Bip44 (curve: unknown, seed: unknown, coin: unknown, account: unknown, change?: unknown, address?: unknown): Promise<ArrayBuffer> {
if (curve !== 'Bitcoin seed' && curve !== 'ed25519 seed') {
throw new TypeError(`Unsupported curve ${curve}`)
}
+ if (!(seed instanceof ArrayBuffer)) {
+ throw new RangeError(`Invalid seed buffer ${seed}`)
+ }
if (seed.byteLength < 16 || seed.byteLength > 64) {
throw new RangeError(`Invalid seed byte length ${seed.byteLength}`)
}
+ if (typeof coin !== 'number') {
+ throw new RangeError(`Invalid coin ${coin}`)
+ }
if (!Number.isSafeInteger(coin) || coin < 0 || coin > 0x7fffffff) {
throw new RangeError(`Invalid coin 0x${coin.toString(16)}`)
}
+ if (typeof account !== 'number') {
+ throw new RangeError(`Invalid account index ${account}`)
+ }
if (!Number.isSafeInteger(account) || account < 0 || account > 0x7fffffff) {
throw new RangeError(`Invalid account index 0x${account.toString(16)}`)
}
+ if (change !== undefined && typeof change !== 'number') {
+ throw new RangeError(`Invalid change index ${change}`)
+ }
if (change !== undefined && (!Number.isSafeInteger(change) || change < 0 || change > 1)) {
throw new RangeError(`Invalid change index 0x${account.toString(16)}`)
}
+ if (address !== undefined && typeof address !== 'number') {
+ throw new RangeError(`Invalid address index ${address}`)
+ }
if (address !== undefined && (!Number.isSafeInteger(address) || address < 0 || address > 0x7fffffff)) {
throw new RangeError(`Invalid address index 0x${account.toString(16)}`)
}
+ return ckd(curve, seed, coin, account, change, address)
+}
+
+function ckd (curve: Curve, seed: ArrayBuffer, coin: number, account: number, change?: number, address?: number): Promise<ArrayBuffer> {
return slip10(curve, seed)
.then(masterKey => CKDpriv(curve, masterKey, BIP44_PURPOSE + HARDENED_OFFSET))
.then(purposeKey => CKDpriv(curve, purposeKey, coin + HARDENED_OFFSET))
}
function hmac (key: Uint8Array<ArrayBuffer>, data: Uint8Array<ArrayBuffer>): Promise<ArrayBuffer> {
- return crypto.subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-512' }, false, ['sign'])
- .then(pk => {
- return crypto.subtle.sign('HMAC', pk, data)
- })
+ return crypto.subtle
+ .importKey('raw', key, { name: 'HMAC', hash: 'SHA-512' }, false, ['sign'])
+ .then(pk => crypto.subtle.sign('HMAC', pk, data))
}