【发布时间】:2021-06-06 01:21:42
【问题描述】:
我使用此代码登录用户。密码使用bcrypt 加密,SALT_ROUNDS 对每个用户都相同
const user = await User.findOne({email: args.email});
if (!user || !await user.comparePassword(args.password)) throw new Error("User or Password is not correct");
(comparePassword 是一个猫鼬函数)
UserSchema.methods.comparePassword = async function (candidatePassword) {
return await bcrypt.compare(candidatePassword, this.password);
};
如您所见,由于短路,if-check 可能需要不同的时间来执行 - 这对于客户端来说是可衡量的。
这意味着,客户可以查明某封电子邮件是否使用了我们的服务 - 这是轻微的数据泄露。
我需要这样的脚本:
const err = new Error("User or Password is not correct.")
if (!user) {
await "wait as long as a password comparison would usually take"
throw err
} else if (!await user.comparePassword(args.password)) {
throw err
}
但不知道如何实现。
一个想法是创建一个虚拟用户以在!user 上创建comparePassword,但我不确定这样做的优点/缺点或是否有更好的解决方案。
编辑:我将所有这些都包装在setTimeout 函数中怎么样?无论如何都需要 1 秒(或 500 毫秒或其他时间)。
【问题讨论】:
-
有人还可以在
comparePassword方法上设置断点,以查看它是否被调用 - 所以“等待一段时间”只是进一步踢罐子。 -
只是想注意这在 npm 包自述文件 npmjs.com/package/bcrypt#a-note-on-timing-attacks 中得到了解决
-
@ihodonald 好像我读过最后一段。我认为比较也会节省时间。由于这个原因,低风险和我缺乏节省时间的技能,我想我会继续前进。
-
@riggedCoinflip 如果您在服务器上(或在无服务器函数中)使用此代码,则用户无法访问任何此代码。我不会把它放在客户端上。
-
这是一个后端功能,我永远不会相信客户端会自己登录。但是可以测量服务器响应登录所需的时间。
标签: javascript bcrypt timing-attack