钱包集成
将 Unlukey 客户端 SDK 集成到钱包中,当用户的恢复短语是由已知的弱种子生成漏洞生成时向其发出警告。
该 SDK 发布在
coinspect/unlukey 仓库中。
检测原理
- 钱包从恢复短语派生出 BIP-39 熵。
- 客户端 SDK 使用 SHA-256 对熵进行哈希,并截取结果哈希的一小段前缀。
- 它仅从静态托管服务下载与该前缀匹配的数据集分桶(bucket)。
- 它在本地将哈希的剩余部分与该分桶中的条目进行比对。
前缀将许多可能的密钥归入同一个分桶(k-匿名性)。静态托管服务只能看到请求的是哪个分桶,永远无法得知被检测的完整密钥,也无法得知是否匹配。
数据集按熵长度划分:一个用于 128 位(12 个单词)熵,另一个用于 256 位(24 个单词)熵。客户端会自动选择正确的数据集。
安装
npm install @unlukey/client
(在该包正式发布之前,可直接从仓库安装:npm install github:coinspect/unlukey#path:client。)
基本用法
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) {
// 警告用户:该恢复短语与已知的弱种子匹配,
// 应将资金转移到新生成的钱包中。
}
查询逻辑在客户端本地运行。恢复短语和熵永远不会离开设备;只有熵哈希的一个前缀会被发送到数据集托管服务。entropy 是一个 Uint8Array,其长度必须为:
- 16 字节,对应 12 个单词的助记词,或
- 32 字节,对应 24 个单词的助记词。
处理结果
check() 返回 { vulnerable, key, prefix, bucketPath, reason? }:
-
vulnerable: true— 该熵与已知的弱种子候选项匹配。提示用户将资金移至使用安全随机数生成的新钱包。 -
vulnerable: false— 未找到匹配项。这并不能证明该恢复短语是安全的;它只说明该熵与 Unlukey 当前数据集中的任何候选项都不匹配。覆盖范围仍在扩大,参见路线图。
reason 提供用于调试集成的诊断信息,不会改变 vulnerable 的含义。
何时运行检测
在用户导入已有恢复短语、且钱包已经派生出 BIP-39 熵之后运行该检测。
自定义托管
默认情况下,客户端从 Unlukey 的公共数据集托管服务下载分桶。可以向 check() 传入不同的基础 URL,以使用其他数据集托管服务(例如你自己的 CDN):
const result = await check(
entropy,
'https://your-cdn.example.com/unlukey-datasets'
)
如需完全控制数据集分桶的获取方式,可使用 checkWith(entropy, readBucket),并提供你自己的 readBucket(bits, prefixHex) 实现。参见 SDK 仓库中的
client/index.js。
本地测试
SDK 仓库的 CLI 工具可用于在不搭建界面的情况下测试集成:
node client/cli.js --remote 72039ecb02a3c880d4249e4b206933945a4f3a76ebaab26fa14e47a24e0f907e
# VULNERABLE
参见 SDK 仓库的 README,了解如何生成本地示例数据集并针对该数据集测试客户端。