我正在对同事任务进行代码审查,并遇到以下代码行(他正在实现基于Spring Security的登录系统)。
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(ENCODING_STRENGTH, new SecureRandom(SEED_BYTES));
}
使用常量种子初始化此特定SecureRandom
是一个好主意吗?我不这么认为,但无法解释原因。
答案 0 :(得分:5)
请参阅SecureRandom
:
此外,SecureRandom必须产生非确定性输出。因此,传递给SecureRandom对象的任何种子材料必须是不可预测的,并且所有SecureRandom输出序列必须加密强大,如 RFC 1750:安全性随机性建议中所述。
如果SEED_BYTES
是常量,则可以预测。
BCryptPasswordEncoder
仅使用加密强SecureRandom
来生成盐,请参阅BCrypt#gensalt
:
random - 要使用的SecureRandom实例
这导致可预测的盐。
盐应该(最多)是唯一的,请参阅A Future-Adaptable Password Scheme:
然而,正如Morris和Thompson [9]所提出的,查找表可以用F的第二个输入来阻止,他们称之为盐。如果每当用户建立新密码时选择随机盐,并且如果盐空间足够大以确保可以忽略的重复概率,则查找表提供对手没有优势;他也可以在攻击时计算F.另一方面,如果盐空间太小,则F的输出位成为密码的有用谓词,这是第6节中描述的QCrack [12]程序所利用的事实。
如果使用常量种子,则每次重新启动应用程序后都会获得相同的盐序列。这导致salt collisions。
盐冲突和可预测的盐会削弱您的安全性,请参阅Seven Ways To Screw Up BCrypt:
#1:使用非随机盐
[...]如果任何两个哈希值的盐相同,则攻击者可以重新使用计算同时攻击两者(对于暴力攻击样式)。 [...]
#2:使用不正确的随机源生成盐
[...]此外,一些弱随机源遭遇称为“种子中毒”的问题,攻击者可以在其中影响未来产生的随机性。