Skip to content

security(BIP44Utils): getEntropy 返回 32 字节 ASCII-hex,实际熵只有 128 bit 却生成 24 词助记词 #132

Open

Description

@mave99a

属于 seed/熵审计任务 ArcBlock/arc-wallet-ios#4647 的分项。

问题

ArcBlockSDK/ABSDKCoreKit/BIP44Utils.swift:60-64:

private static func getEntropy(secretCode: String, recoveryCode: String) -> Data? {
    var entropy = (secretCode.sha3(.keccak256).uppercased() + recoveryCode).sha3(.keccak256).uppercased()
    entropy = String(entropy.prefix(32))
    return entropy.data(using: .ascii)
}

CryptoSwift 的 String.sha3(_:) 返回的是十六进制字符串,不是 bytes。所以:

  1. 内层 .sha3() → 64 个 hex 字符
  2. 拼上 recoveryCode,外层 .sha3() → 又是 64 个 hex 字符
  3. .prefix(32) → 32 个 hex 字符
  4. .data(using: .ascii) → 32 字节,但每字节取值只在 [0-9A-F] 这 16 个值里

即:一个 32 字节的熵缓冲区,实际只承载 32 × 4 = 128 bit。

然后 generateSeed(secretCode:recoveryCode:) 把它喂给 BIP39.seedFromEntropy(entropy) —— 32 字节熵在 BIP39 里对应 24 词助记词。

影响

不可利用。 recoveryCode 来自 generateRecoveryCode() → MCrypto.generateRandomBytes(bytesCount: 16) → SecRandomCopyBytes,是 128 bit 真随机;128 bit 是安全的。

但这是标称强度 ≠ 实际强度:用户拿到一条 24 词助记词,按 BIP39 的常识那代表 256 bit,实际只有 128 bit。这正是 Coldcard 那篇复盘在讲的缺陷类别 —— 名义熵和有效熵对不上,只是我们这边差 2×、他们差 2^88。

任何在这条路上创建过钱包的用户,手里的 24 词其实值 128 bit。

当前可达性

BIP44Utils.generateSeed(secretCode:recoveryCode:) 在 arc-wallet-ios 里只有一个调用方:

  • WalletInitManager.codeRecovery(secretCode:recoveryCode:password:)(WalletInitManager.swift:208)
  • 被 ImportBackupPasswordViewController.swift:232 调用 —— 恢复/导入流程,不是创建流程

也就是说这条路今天只用于恢复历史钱包,新钱包走的是 generateMnemonics() → BIP39.generateMnemonics(bitsOfEntropy: 128)(SecRandomCopyBytes,正确)。

建议

  1. getEntropy 保留原样 —— 它是历史钱包的恢复算法,不能改,改了老用户恢复不出来。
  2. 但要加注释说明"输出是 32 字节 ASCII-hex,实际熵 128 bit",避免后来人误以为这是 256 bit 派生,或把它复用到新路径上。
  3. 确认没有任何创建(而非恢复)路径还在调用 generateSeed(secretCode:recoveryCode:)。
  4. Android 侧有逐字对应的实现(Bip44Utils.getEntropy,用 BaseEncoding.base16() 做同样的事),已在 ArcBlock/did-wallet-sdk-android 另开 issue。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions