chainCode: DataView
}
-const BIP44_COIN_NANO = 165
-const BIP44_PURPOSE = 44
-const HARDENED_OFFSET = 0x80000000
-const SLIP10_ED25519 = 'ed25519 seed'
+async function fn () {
+ const BIP44_COIN_NANO = 165
+ const BIP44_PURPOSE = 44
+ const HARDENED_OFFSET = 0x80000000
+ const SLIP10_ED25519 = 'ed25519 seed'
-/**
-* Listens for messages from a calling function.
-*/
-addEventListener('message', (message) => {
- const { seed, index } = message.data ?? message
- nanoCKD(seed, index).then(key => postMessage({ index, key }))
-})
+ /**
+ * Listens for messages from a calling function.
+ */
+ addEventListener('message', (message) => {
+ const { seed, index } = message.data ?? message
+ nanoCKD(seed, index).then(key => postMessage({ index, key }))
+ })
-/**
-* Derives a private child key following the BIP-32 and BIP-44 derivation path
-* registered to the Nano block lattice. Only hardened child keys are defined.
-*
-* @param {string} seed - Hexadecimal seed derived from mnemonic phrase
-* @param {number} index - Account number between 0 and 2^31-1
-* @returns Private child key for the account
-*/
-async function nanoCKD (seed: string, index: number): Promise<string> {
- if (seed.length < 32 || seed.length > 128) {
- throw new RangeError(`Invalid seed length`)
+ /**
+ * Derives a private child key following the BIP-32 and BIP-44 derivation path
+ * registered to the Nano block lattice. Only hardened child keys are defined.
+ *
+ * @param {string} seed - Hexadecimal seed derived from mnemonic phrase
+ * @param {number} index - Account number between 0 and 2^31-1
+ * @returns Private child key for the account
+ */
+ async function nanoCKD (seed: string, index: number): Promise<string> {
+ console.log(`seed: ${seed}; index: ${index}`)
+ 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, BIP44_COIN_NANO + HARDENED_OFFSET)
+ const accountKey = await CKDpriv(coinKey, index + HARDENED_OFFSET)
+ const privateKey = new Uint8Array(accountKey.privateKey.buffer)
+ return privateKey.reduce((key, byte) => key.concat(byte.toString(16).padStart(2, '0')), '')
}
- 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, BIP44_COIN_NANO + HARDENED_OFFSET)
- const accountKey = await CKDpriv(coinKey, index + HARDENED_OFFSET)
- const privateKey = new Uint8Array(accountKey.privateKey.buffer)
- return privateKey.reduce((key, byte) => key.concat(byte.toString(16).padStart(2, '0')), '')
-}
-
-async function 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 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> {
- 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)
- 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 {
- if (typeof integer !== 'number') {
- throw new TypeError(`Expected a number, received ${typeof integer}`)
+ async function 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 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 })
}
- if (integer > 0xffffffff) {
- throw new RangeError(`Expected 32-bit integer, received ${integer.toString(2).length}-bit value: ${integer}`)
+
+ async function 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)
+ 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 })
}
- const view = new DataView(new ArrayBuffer(4))
- view.setUint32(0, integer, false)
- return new Uint8Array(view.buffer)
-}
-function ser256 (integer: DataView): Uint8Array {
- if (integer.constructor !== DataView) {
- throw new TypeError(`Expected DataView, received ${typeof integer}`)
+ function ser32 (integer: number): Uint8Array {
+ if (typeof integer !== 'number') {
+ throw new TypeError(`Expected a number, received ${typeof integer}`)
+ }
+ if (integer > 0xffffffff) {
+ throw new RangeError(`Expected 32-bit integer, received ${integer.toString(2).length}-bit value: ${integer}`)
+ }
+ const view = new DataView(new ArrayBuffer(4))
+ view.setUint32(0, integer, false)
+ return new Uint8Array(view.buffer)
}
- if (integer.byteLength > 32) {
- throw new RangeError(`Expected 32-byte integer, received ${integer.byteLength}-byte value: ${integer}`)
+
+ function ser256 (integer: DataView): Uint8Array {
+ if (integer.constructor !== DataView) {
+ throw new TypeError(`Expected DataView, received ${typeof integer}`)
+ }
+ if (integer.byteLength > 32) {
+ throw new RangeError(`Expected 32-byte integer, received ${integer.byteLength}-byte value: ${integer}`)
+ }
+ return new Uint8Array(integer.buffer)
}
- return new Uint8Array(integer.buffer)
-}
-async function 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)
+ async function 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)
+ }
}
-export default import.meta.url
+export default `(${fn.toString()})()`
// SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
// SPDX-License-Identifier: GPL-3.0-or-later
-import blake2b from 'blake2b'
+async function fn () {
+ /**
+ * Listens for messages from a calling function.
+ */
+ addEventListener('message', (message) => {
+ const { seed, index, blake2b } = message.data ?? message
+ ckdBlake2b(seed, index, blake2b).then(key => postMessage({ index, key }))
+ })
-/**
-* Listens for messages from a calling function.
-*/
-addEventListener('message', (message) => {
- const { seed, index } = message.data ?? message
- ckdBlake2b(seed, index).then(key => postMessage({ index, key }))
-})
-
-/**
-* Derives BLAKE2b account private keys.
-*
-* @param {number} index - Index of the account
-* @returns {Promise<string>}
-*/
-async function ckdBlake2b (seed: string, index: number): Promise<string> {
- const indexHex = index.toString(16).padStart(8, '0').toUpperCase()
- const inputHex = `${seed}${indexHex}`.padStart(72, '0')
- const inputArray = (inputHex.match(/.{1,2}/g) ?? []).map(h => parseInt(h, 16))
- const inputBytes = Uint8Array.from(inputArray)
- const hash = blake2b(32).update(inputBytes).digest('hex')
- return hash
+ /**
+ * Derives BLAKE2b account private keys.
+ *
+ * @param {number} index - Index of the account
+ * @returns {Promise<string>}
+ */
+ async function ckdBlake2b (seed: string, index: number, blake2b: string): Promise<string> {
+ const blake = Function(`return ${blake2b}`)
+ console.log(blake)
+ const indexHex = index.toString(16).padStart(8, '0').toUpperCase()
+ const inputHex = `${seed}${indexHex}`.padStart(72, '0')
+ const inputArray = (inputHex.match(/.{1,2}/g) ?? []).map(h => parseInt(h, 16))
+ const inputBytes = Uint8Array.from(inputArray)
+ const hash = blake(32).update(inputBytes).digest('hex')
+ return hash
+ }
}
-export default import.meta.url
+export default `(${fn.toString()})()`