所以我有两个项目,它们应该相互沟通。一个是Android,另一个是Sping Boot 。它们都应该使用Bcrypt作为哈希编码器。
在我的Android项目(客户端)中,用户注册他们的详细信息。主要的是用户名和密码。
我明白,在这一点上,客户端应该是散列的密码,也盐?然后,它需要将数据安全地传输到服务器。
从那里,服务器然后需要处理信息并存储散列密码和盐。
下次用户希望登录应用程序时,他们再次提供用户名和密码,客户端再次进行哈希处理,然后发送到服务器。
此时,服务器应该将散列密码与存储在数据库中的密码进行比较,并且一切顺利,它们匹配。
这就是问题所在。
在我的客户端项目中,我注册了用户,并使用以下代码将哈希密码发送到服务器:
...
password = passwordEncoder().encode(password)
apiService.addCustomer(
ApiCustomer(
username = username,
password = password,
dob = LocalDate.parse(convertDOB(dob)).toString(),
firstName = firstName,
lastName = lastName,
isActive = true,
email = email,
mobileNumber = mobileNumber,
)
)
...
passwordEncoder()
通过以下方式初始化:
fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()
如果密码为password1
,则创建了$2a$10$FgIbXCXzYrpwcKV8bS2BoulXDDBvwywXKB5MMyiUkQzDk66zTFli6
的has
到目前为止一切顺利。然后我的服务器从客户端接收到这个密码,然后存储散列密码(还不确定我将如何实现salt)。再说一次,到目前为止一切顺利。它就是这样。
现在,用户稍后沿着,需要重新登录。所以他们提供他们的用户名和输入他们的原始密码-与上面相同的细节。
我的当事人重新散列了密码。password1
变为$2a$10$J33C5WCT0zRh/P17R6soMupgQmkIh6JD9bPKPi4kUJhjGWnv0R6OW
即使从快速浏览,你可以看到,这并不匹配!
我猜这和我之前提到的盐有关。然而,我不确定如何在客户端提取盐,然后在服务器端使用它来比较新的哈希密码。
1条答案
按热度按时间rsl1atfo1#
首先,bcrypt每次都会生成不同的哈希值,这是正常的行为,因为它在哈希之前会向纯文本密码添加一个随机生成的值(以防止rainbow table attacks)
所以你给予它的密码123它添加随机盐“123+盐(16字节)”然后散列整个文本的东西像这样
**注意盐包含在散列版本中
这被保存到你的数据库,然后再次生成哈希将使用不同的随机盐,然后整个(123+diffSalt)将是不同的输入,因此不同的哈希。
比较明文密码和哈希值的正确方法是从数据库中获取哈希值,使用其上的盐对明文密码进行哈希,然后比较它们。
你可以在springboot中使用
encoder.matches(CharSequence rawPassword, String encodedPassword)
我不确定如何在客户端提取盐
你不应该在客户端这样做(你必须发送哈希密码到客户端来获取盐和比较)所有的哈希和比较应该在服务器端完成。
推荐的方法是通过安全连接(例如,HTTPS)发送到服务器,在那里可以使用bcrypt进行散列并安全存储。然后,当用户登录时,使用HTTPS以纯文本再次发送凭证,现在服务器获取散列,将登录密码与使用散列上相同盐的散列密码进行比较。