Skip to content

security(Bip44Utils): getEntropy 返回 32 字节 ASCII-hex(实际 128 bit),且 recoverCode 为 null 时种子会塌缩 #22

Description

@mave99a

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

问题 1:熵缓冲区是 ASCII-hex,实际熵只有名义的一半

wallet-sdk/src/main/java/io/arcblock/walletkit/bip44/Bip44Utils.java:

private static byte[] getEntropy(String secretCode, String recoverCode) {
    // SHA3(SHA3(user_entered_key) + seed)
    String result = BaseEncoding.base16()
      .encode(ArcKeccakf1600Hasher.sha256(
        (BaseEncoding.base16().encode(ArcKeccakf1600Hasher.sha256(secretCode.getBytes(), 1))
          + recoverCode).getBytes(), 1));
    return result.substring(0, 32).getBytes();
}

result 是 base16(hex)字符串,.substring(0,32).getBytes() 得到 32 字节,但每字节取值只在 [0-9A-F] 这 16 个值里 —— 32 × 4 = 128 bit 有效熵。

genSeed() 把它交给 bitcoinj new DeterministicSeed(entropy, passphrase, creationTimeSeconds),32 字节熵 → 24 词助记词。

不可利用(recoverCode = genRecoverCode() 的 16 字节 SecureRandom,128 bit 是安全的),但标称 256 bit / 实际 128 bit 对不上。这正是 Coldcard 复盘里那个缺陷类别,只是量级差很远。

问题 2:recoverCode 为 null 时种子会塌缩

调用方 arc-wallet-android 的 CreatePasswordActivity.kt:

@JvmField @Autowired var recoverCode: String? = null
...
:263  BaseEncoding.base64().encode(Bip44Utils.genSeed(secretCode, recoverCode, "").seedBytes ?: ByteArray(0))

recoverCode 是 ARouter 注入的可空字段。Java 里 ... + recoverCode 对 null 会拼成字符串 "null",不抛异常 —— 于是种子退化成只依赖 secretCode(一个用户口令)的确定性函数。

当前不可达:CreatePasswordActivity 的 type 只有 0 和 2 被派发(ImportMnemonicActivity.kt:254 传 withInt("type", 2)),走 genSeed 的 type == 1 分支没有任何调用方。但这是一条只要有人接错路由就会静默生效的路径。

建议

  1. getEntropy 是历史钱包的恢复算法,算法本身不能改(改了老用户恢复不出来),但要加注释写清"输出是 32 字节 ASCII-hex,有效熵 128 bit"。
  2. genSeed(String, String, String) 三个参数加 @NonNull,并在方法入口对 recoverCode 做非空 + 长度校验,让 null 快速失败而不是拼成 "null"。
  3. 调用侧(arc-wallet-android CreatePasswordActivity 的 type == 1 分支)已是死代码,建议一并删除。
  4. ArcBlock/walletkit-android 里 walletkit/src/main/java/io/arcblock/walletkit/bip44/Bip44Utils.java 是同一份代码的另一个副本(我逐行 diff 过,除 javadoc 和 creationTimeSeconds 外完全一致)。两份并存本身也值得收敛。
  5. iOS 侧有逐字对应的实现(BIP44Utils.getEntropy),已在 ArcBlock/arcblock-ios-sdk 另开 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