Wallet integration
Integrate the Unlukey client SDK into a wallet to warn users when their recovery phrase was generated by a known weak seed-generation vulnerability.
The SDK is published in the
coinspect/unlukey repository.
How the check works
- The wallet derives the BIP-39 entropy from the recovery phrase.
- The client SDK hashes the entropy with SHA-256 and takes a short prefix of the resulting hash.
- It fetches only the dataset bucket matching that prefix from static hosting.
- It compares the remaining hash bytes against the entries in that bucket, locally.
The prefix groups many possible keys into the same bucket (k-anonymity). The static hosting provider only sees which bucket was requested, never the full key being checked or whether it matched.
Datasets are split by entropy length: one dataset for 128-bit (12-word) entropy and one for 256-bit (24-word) entropy. The client selects the right one automatically.
Install
npm install @unlukey/client
(Until the package is published, install directly from the repo: npm install github:coinspect/unlukey#path:client.)
Basic usage
import { check } from '@unlukey/client'
import { mnemonicToEntropy } from '@scure/bip39'
import { wordlist } from '@scure/bip39/wordlists/english'
const entropy = mnemonicToEntropy(secretRecoveryPhrase, wordlist)
const { vulnerable } = await check(entropy)
if (vulnerable) {
// Warn the user: this recovery phrase matches a known weak seed and
// funds should be moved to a newly generated wallet.
}
The lookup logic runs client-side. The recovery phrase and entropy never
leave the device; only a prefix of the entropy hash is sent to the dataset
host. entropy is a Uint8Array and must be either:
- 16 bytes, for 12-word mnemonics, or
- 32 bytes, for 24-word mnemonics.
Handling the result
check() resolves to { vulnerable, key, prefix, bucketPath, reason? }:
-
vulnerable: true— the entropy matches a known weak-seed candidate. Prompt the user to move funds to a new wallet generated with secure randomness. -
vulnerable: false— no match was found. This does not prove the recovery phrase is safe; it only means it does not match any candidate in Unlukey’s current datasets. Coverage is expanding; see the roadmap.
reason provides diagnostic information for debugging integrations. It does
not change the meaning of vulnerable.
When to run the check
Run the check when a user imports an existing recovery phrase, once the wallet has derived the BIP-39 entropy.
Custom hosting
By default, the client fetches buckets from Unlukey’s public dataset host.
Pass a different base URL to check() to use a different dataset host,
such as your own CDN:
const result = await check(
entropy,
'https://your-cdn.example.com/unlukey-datasets'
)
For full control over how dataset buckets are fetched, use
checkWith(entropy, readBucket) and supply your own
readBucket(bits, prefixHex) implementation. See
client/index.js
in the SDK repo.
Testing locally
The SDK repo’s CLI is useful for testing the integration without wiring up UI:
node client/cli.js --remote 72039ecb02a3c880d4249e4b206933945a4f3a76ebaab26fa14e47a24e0f907e
# VULNERABLE
See the SDK repo’s README for building a local sample dataset and testing the client against it.