【发布时间】:2015-07-04 09:36:40
【问题描述】:
为了登录目的,我必须创建一个带有用户表的休息服务器。移动设备将连接到此服务器以供用户登录。 我想创建一个安全的系统,我想到了这个解决方案:
用户表:
- PasswordHash - CHAR(64) 用于存储 SHA256(密码)
- PasswordToken - CHAR(25) 用于存储随机可能唯一的令牌
用户注册:
设备会生成用户提供的密码的SHA256;
哈希将通过SSL发送到服务器;
服务器会将此哈希值存储在PasswordHash字段中,并将随机令牌存储在PasswordToken字段中;
用户登录:
- 设备会生成用户提供的密码的SHA256[passwordDevice];
- 服务器会生成一个 SHA512 的 (PasswordHash + PasswordToken) [hashServer];
- 服务器将生成 (passwordDevice + PasswordToken) [hashDevice] 的 SHA512;
- 服务器会生成一个 BCrypt 字符串 (hashServer + serverSideKey) [bCryptServer];
-
服务器会生成一个BCrypt String of (hashDevice + serverSideKey) [bCryptDevice];
if (bCryptServer == bCryptDevice) LOGIN OK; else LOGIN REFUSED;
那么,这种方法合适吗?
安全吗?
我可以避免一些操作吗?
我可以优化一些东西吗?
提前致谢。
【问题讨论】:
-
在客户端生成哈希没有意义。这样,攻击者就可以像使用密码一样使用哈希值。您应该在服务器上创建哈希。
-
但是如果我发送明文,攻击者可以简单地准备好密码..
-
用户表在哪里,在服务器上还是在设备上?为什么要在服务器端计算四种不同的哈希值?为什么不使用 bcrypt 存储密码? serverSideKey 的用途是什么?最后,它看起来过于复杂了。
-
存储原始密码的哈希是一种过时的做法,容易受到rainbow table 攻击。您应该只存储加盐密码的哈希值。
-
显然您应该永远通过未加密的连接发送身份验证令牌。如果您打算这样做,则散列无济于事。这是原始的混淆,它在没有安全的地方假装安全。不要上当!