chainCode: DataView
}
-const b = () => {
+export class Bip44Ckd {
- const BIP44_COIN_NANO = 165
- const BIP44_PURPOSE = 44
- const HARDENED_OFFSET = 0x80000000
- const SLIP10_ED25519 = 'ed25519 seed'
+ static BIP44_COIN_NANO = 165
+ static BIP44_PURPOSE = 44
+ static HARDENED_OFFSET = 0x80000000
+ static SLIP10_ED25519 = 'ed25519 seed'
-
- async function calculate (data: any[]): Promise<any[]> {
+ static async calculate (data: any[]): Promise<any[]> {
for (const d of data) {
- if (d.coin != null && d.coin !== BIP44_PURPOSE) {
- d.privateKey = await ckd(d.seed, d.coin, d.index)
+ if (d.coin != null && d.coin !== this.BIP44_PURPOSE) {
+ d.privateKey = await this.ckd(d.seed, d.coin, d.index)
} else {
- d.privateKey = await nanoCKD(d.seed, d.index)
+ d.privateKey = await this.nanoCKD(d.seed, d.index)
}
}
return data
* @param {number} index - Account number between 0 and 2^31-1
* @returns {Promise<string>} Private child key for the account
*/
- async function nanoCKD (seed: string, index: number): Promise<string> {
+ static async nanoCKD (seed: string, index: number): Promise<string> {
if (!Number.isSafeInteger(index) || index < 0 || index > 0x7fffffff) {
throw new RangeError(`Invalid child key index 0x${index.toString(16)}`)
}
- return await ckd(seed, BIP44_COIN_NANO, index)
+ return await this.ckd(seed, this.BIP44_COIN_NANO, index)
}
/**
* @param {number} index - Account number between 0 and 2^31-1
* @returns {Promise<string>} Private child key for the account
*/
- async function ckd (seed: string, coin: number, index: number): Promise<string> {
+ static async ckd (seed: string, coin: number, index: number): Promise<string> {
if (seed.length < 32 || seed.length > 128) {
throw new RangeError(`Invalid seed length`)
}
if (!Number.isSafeInteger(index) || index < 0 || index > 0x7fffffff) {
throw new RangeError(`Invalid child key index 0x${index.toString(16)}`)
}
- const masterKey = await slip10(SLIP10_ED25519, seed)
- const purposeKey = await CKDpriv(masterKey, BIP44_PURPOSE + HARDENED_OFFSET)
- const coinKey = await CKDpriv(purposeKey, coin + HARDENED_OFFSET)
- const accountKey = await CKDpriv(coinKey, index + HARDENED_OFFSET)
+ const masterKey = await this.slip10(this.SLIP10_ED25519, seed)
+ const purposeKey = await this.CKDpriv(masterKey, this.BIP44_PURPOSE + this.HARDENED_OFFSET)
+ const coinKey = await this.CKDpriv(purposeKey, coin + this.HARDENED_OFFSET)
+ const accountKey = await this.CKDpriv(coinKey, index + this.HARDENED_OFFSET)
const privateKey = new Uint8Array(accountKey.privateKey.buffer)
let hex = ''
for (let i = 0; i < privateKey.length; i++) {
return hex
}
- async function slip10 (curve: string, S: string): Promise<ExtendedKey> {
+ static async slip10 (curve: string, S: string): Promise<ExtendedKey> {
const key = new TextEncoder().encode(curve)
const data = new Uint8Array(64)
data.set(S.match(/.{1,2}/g)!.map(byte => parseInt(byte, 16)))
- const I = await hmac(key, data)
+ const I = await this.hmac(key, data)
const IL = new DataView(I.buffer.slice(0, I.length / 2))
const IR = new DataView(I.buffer.slice(I.length / 2))
return ({ privateKey: IL, chainCode: IR })
}
- async function CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise<ExtendedKey> {
+ static async CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise<ExtendedKey> {
const key = new Uint8Array(chainCode.buffer)
const data = new Uint8Array(37)
data.set([0])
- data.set(ser256(privateKey), 1)
- data.set(ser32(index), 33)
- const I = await hmac(key, data)
+ data.set(this.ser256(privateKey), 1)
+ data.set(this.ser32(index), 33)
+ const I = await this.hmac(key, data)
const IL = new DataView(I.buffer.slice(0, I.length / 2))
const IR = new DataView(I.buffer.slice(I.length / 2))
return ({ privateKey: IL, chainCode: IR })
}
- function ser32 (integer: number): Uint8Array {
+ static ser32 (integer: number): Uint8Array {
if (typeof integer !== 'number') {
throw new TypeError(`Expected a number, received ${typeof integer}`)
}
return new Uint8Array(view.buffer)
}
- function ser256 (integer: DataView): Uint8Array {
+ static ser256 (integer: DataView): Uint8Array {
if (integer.constructor !== DataView) {
throw new TypeError(`Expected DataView, received ${typeof integer}`)
}
return new Uint8Array(integer.buffer)
}
- async function hmac (key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
+ static async hmac (key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
const { subtle } = globalThis.crypto
const pk = await subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-512' }, false, ['sign'])
const signature = await subtle.sign('HMAC', pk, data)
return new Uint8Array(signature)
}
-
- return { ckd, nanoCKD }
}
-export const Bip44Ckd = b()
-
-const start = b.toString().indexOf('{') + 1
-const end = b.toString().lastIndexOf('return')
-export const worker = b.toString().substring(start, end)
+export default Bip44Ckd.toString()