我正在开发一个带有 MySQL 数据库的 Android 应用程序,用于存储用户登录凭据。在将密码存储在数据库中之前,我使用jBCrypt对密码进行哈希处理。注册时,密码在客户端进行哈希处理,如下所示:
String salt = BCrypt.gensalt();
String hash = BCrypt.hashpw("password", salt).split("\\$")[3];
salt = salt.split("\\$")[3];
hash = hash.substring(salt.length(), hash.length());
在这种情况下,BCrypt.hashpw()会给我哈希
$2a$10$rrll.6qqZFLPe8.usJj.je0MayttjWiUuw/x3ubsHCivFsPIKsPgq
然后我删除参数 ( $2a$10$) 并将前 22 个字符作为盐存储,最后 31 个作为哈希存储在数据库中:
------------------------------------------------------------------------
| uid | salt | hash |
------------------------------------------------------------------------
| 1 | rrll.6qqZFLPe8.usJj.je | 0MayttjWiUuw/x3ubsHCivFsPIKsPgq |
------------------------------------------------------------------------
现在,每当客户想要登录时,他们都会输入他们的用户名和密码,并且只会从数据库中返回salt 。客户端通过调用BCrypt.hashpw()他们的盐来计算他们的哈希:
String salt = "$2a$10$" + returnedSalt;
String hash = BCrypt.hashpw(“password”, salt).split("\\$")[3];
hash = hash.substring(salt.length(), hash.length());
给我:
hash = "0MayttjWiUuw/x3ubsHCivFsPIKsPgq"
这等于存储在数据库中的哈希值。然后客户端将用户名和计算的哈希发送回服务器。如果它们匹配,则用户将登录。
我知道我可以通过直接获取整个 BCrypt 哈希并将其与给定密码进行比较来简化此过程
if (BCrypt.checkpw(“password”, bCryptHash))
// match
但是将整个散列密码发送给用户进行检查感觉不对。
我知道最好在服务器端散列密码,但是这个解决方案有什么问题吗?我错过了什么吗?
假设我在电话和服务器之间有一个未加密的 HTTP 连接。这会是一个安全的解决方案吗?