Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | 2x 2x 2x 2x 2x 2x 3x 3x 3x 2x 1x 1x 1x 1x 2x 3x 3x 3x 2x 3x 3x 3x 3x 3x | import { HDKey } from '@scure/bip32'; import { bytesToHex, utf8ToBytes } from 'micro-stacks/common'; import { hashSha256 } from 'micro-stacks/crypto-sha'; import { DATA_DERIVATION_PATH, WALLET_CONFIG_PATH } from '../constants'; import { isHardened } from '../utils'; import type { WalletKeys } from '../types'; /** * Derive the `configPrivateKey` for a wallet. * * This key is derived from the path `m/44/5757'/0'/1`, using `1` for change option, * following the bip44 recommendation for keys relating to non-public data. * * > m / purpose' / coin_type' / account' / change / address_index * * This key is used to encrypt configuration data related to a wallet, so the user's * configuration can be synced across wallets. * * @param rootNode A keychain that was created using the wallet mnemonic phrase */ export const deriveConfigPrivateKey = (rootNode: HDKey): string => { const derivedConfigKey = rootNode.derive(WALLET_CONFIG_PATH).privateKey; Iif (!derivedConfigKey) throw new TypeError('Unable to derive config key for wallet identities'); return bytesToHex(derivedConfigKey); }; /** * Before modern Stacks Wallets, previous authenticators used a different format * and path for the config file. * * The path for this key is `m/45'` * @param rootKey A base64 encoded HDKeychain (BIP32) that was created using the wallet mnemonic phrase * @return privateKey Hex encoded legacy private key */ export const deriveLegacyConfigPrivateKey = (rootKey: string): string => { const rootNode = HDKey.fromExtendedKey(rootKey); const legacyNode = rootNode.deriveChild(isHardened(45)); const derivedLegacyPrivateKey = legacyNode.privateKey; Iif (!derivedLegacyPrivateKey) throw new TypeError('Unable to derive config key for wallet identities'); return bytesToHex(derivedLegacyPrivateKey); }; /** * Generate a salt, which is used for generating an app-specific private key * the salt is the hex encoded public key converted to bytes, SHA256 hashed and then hex encoded * @param rootNode A keychain that was created using the wallet mnemonic phrase * @return salt A hex encoded hash */ export function deriveSalt(rootNode: HDKey): string { const publicKey = rootNode.derive(DATA_DERIVATION_PATH).publicKey; Iif (!publicKey) throw new TypeError('Unable to derive public key from data derivation path'); return bytesToHex(hashSha256(utf8ToBytes(bytesToHex(publicKey)))); } export function deriveWalletKeys(rootNode: HDKey): WalletKeys { Iif (!rootNode.privateKey) throw Error('no private key'); const salt = deriveSalt(rootNode); const rootKey = rootNode.privateExtendedKey; const configPrivateKey = deriveConfigPrivateKey(rootNode); return { salt, rootKey, configPrivateKey, }; } |