攻击可行性分析:48-bit 种子空间够不够被破解
|---| | 算法 | new Random().nextInt(62) | | 字符集 | A-Z, a-z, 0-9(62个字符) | | Token 长度 | 16 位 | | 存储位置 | categories: - Course - INFO5995 tags: - INFO5995 - Assignment - Security - Task 3 abbrlink: info5995-task3 date: 2026-03-31 00:10:00 ---
攻击可行性分析:48-bit 种子空间够不够被破解
攻击者已知的信息(通过反编译 APK)
| 攻击者知道的 | 值 |
|---|---|
| 算法 | new Random().nextInt(62) |
| 字符集 | A-Z, a-z, 0-9(62个字符) |
| Token 长度 | 16 位 |
| 存储位置 | SharedPreferences,key = "sessionToken" |
Java Random 的本质
Java 的 java.util.Random
是线性同余生成器(LCG):
下一个随机数 = (当前种子 × 乘数 + 增量) mod 模数 |
参数是固定的: - 乘数 a - 增量 c - 模数
m = 2^48
48-bit 种子空间
2^48 = 281,474,976,710,656 |
听起来很大,但实际上:
- 用普通电脑(每秒计算 10 亿次)
- 约 28 万秒 ≈ 3-4 天可以枚举完
- 如果用 GPU 并行计算,这个时间可以大幅缩短
两种攻击路径
路径 A:从已知输出反推种子
攻击者需要观察一些 token 输出:
观察 token1, token2, token3 ... token16 |
16 次 nextInt(62) 输出 → 可以确定性反推出 48-bit
种子。
这在有代码可见性的情况下是可行的。
路径 B:离线暴力枚举
攻击者不需要任何观察,直接算:
for (每个可能的 48-bit 种子) { |
2.8 × 10^14 次计算,在现代计算资源下是可行的。
和真实攻击的距离
| 条件 | 是否满足 |
|---|---|
| 攻击者能拿到 token? | 需要在目标设备上运行 App 或读取 SharedPreferences |
| 攻击者能反编译看到算法? | ✅ 任何人都可以(APK 就在那里) |
| 计算资源够用? | ✅ 普通笔记本几天内可算完 |
这不是理论攻击——是实际可行的。
为什么说"比看起来更严重"
这个 App 虽然简单,但:
- 代码开源可查 → 算法完全已知
- 本地存储 → 有 Android 设备的攻击者可以读取
- 没有速率限制 → 可以快速尝试
- Session Token 可预测 → 不需要用户名密码就能进入账户
预测出的 token ≠ 知道密码,但等于可以直接冒充这个用户。
和真正安全的 Session Token 比
| 弱随机数 Token | 安全 Token | |
|---|---|---|
| 生成算法 | java.util.Random |
SecureRandom |
| 种子大小 | 48-bit | ≥128-bit |
| 暴力破解时间 | 几天(普通硬件) | 不可能(当前算力) |
| 预测可行性 | 确定性可预测 | 计算上不可行 |