为何md5($user_id . time())生成的密码重置令牌熵值较弱?
密码重置令牌生成方案的熵值问题分析
为什么md5($user_id . time())是不可取的方案
即使假设MD5无法被逆向,这个方案的核心问题在于输入的随机空间太小,攻击者可以轻松枚举所有可能的令牌:
- 用户ID通常是可预测的:多数网站用自增整数作为用户ID,攻击者可以从1开始枚举所有可能的用户ID(比如网站有10万用户,最多枚举10万次)。
- 时间戳的范围极窄:密码重置令牌的有效期一般是几分钟到几小时,攻击者只要知道请求的大致时间范围(比如1小时内),时间戳的可能值只有3600种左右。
- 两者组合后的总可能输入量极低:比如10万用户+1小时时间窗口,总组合数是10万×3600=3.6亿,这个量级的枚举对现代服务器来说完全是小菜一碟,攻击者可以短时间内遍历所有可能的MD5结果,找到有效的令牌。
如何说明它的熵值低
熵值是衡量数据不确定性的指标,单位为比特,熵值越低,数据越容易被预测。这个方案的熵值仅来自两个部分:用户ID的熵和时间戳的熵:
- 用户ID的熵:如果网站有M个注册用户,熵值为
log2(M)比特。比如10万用户,log2(100000)≈17比特。 - 时间戳的熵:如果攻击者能覆盖T秒的时间窗口,熵值为
log2(T)比特。比如1小时窗口,log2(3600)≈12比特。 - 总熵值:两者相加,约为29比特。而安全的密码重置令牌至少需要64比特以上的熵,才能让暴力枚举变得不现实。
熵值的计算方法
计算这个方案的熵值可以按以下步骤:
- 确定用户ID的可能取值数量:即网站的注册用户总数M(如果用户ID是自增的,M就是最大用户ID值)。
- 确定攻击者能覆盖的时间窗口内的时间戳数量T:比如令牌有效期1小时,T=3600。
- 计算总可能输入组合数:
总组合数 = M × T。 - 熵值(比特)=
log2(总组合数),也就是log2(M) + log2(T)。
内容的提问来源于stack exchange,提问作者Johnny
相关产品推荐
相关产品推荐

