如何将密码文本与 bcrypt 哈希值进行比较?

Posted

技术标签:

【中文标题】如何将密码文本与 bcrypt 哈希值进行比较?【英文标题】:how to compare a password text with the bcrypt hashes? 【发布时间】:2019-07-02 23:53:52 【问题描述】:

我的应用程序中有一个用例,它应该阻止用户在重置密码时选择最后 3 个密码之一。我使用 Angular 作为前端,使用 Spring Boot 作为后端。在我的场景中,用户密码存储为 bcrypt 哈希。

如何将用户输入的密码与最近 3 个存储的 bcrypt 密码进​​行比较?

当我运行以下代码片段示例时,

BCryptPasswordEncoder b = new BCryptPasswordEncoder();

    for(int i =0;i<10;i++) 
        System.out.println(b.encode("passw0rd"));

    

它会生成以下 bcrypt 哈希值。每个哈希值都不同,这是合理的,因为当我检查org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder 时,我可以看到生成的盐是随机值。

$2a$10$tztZsPFZ.T.82Gl/VIuMt.RDjayTwuMLAkRkO9SB.rd92vHWKZmRm
$2a$10$yTHyWDmcCBq3OSPOxjj4TuW9qXYE31CU.fFlWxppii9AizL0lKMzO
$2a$10$Z6aVwg.FNq/2I4zmDjDOceT9ha0Ur/UKsCfdADLvNHiZpR7Sz53fC
$2a$10$yKDVeOUvfTQuTnCHGJp.LeURFcXK6JcHB6lrSgoX1pRjxXDoc8up.
$2a$10$ZuAL06GS7shHz.U/ywb2iuhv2Spubl7Xo4NZ7QOYw3cHWK7/7ZKcC
$2a$10$4T37YehBTmPWuN9j.ga2XeF9GHy6EWDhQS5Uc9bHvJTK8.xIm1coS
$2a$10$o/zxjGkArT7YdDkrk5Qer.oJbZAYpJW39iWAWFqbOhpTf3FmyfWRC
$2a$10$eo7yuuE2f7XqJL8Wjyz.F.xj78ltWuMS1P0O/I6X7iNPwdsWMVzu6
$2a$10$3ErH2GtZpYJGg1BhfgcO/uOt/L2wYg4RoO8.fNRam458WWdymdQLW
$2a$10$IksOJvL/a0ebl4R2/nbMQ.XmjNARIzNo8.aLXiTFs1Pxd06SsnOWa

Spring 安全配置。

  @Configuration
    @Import(SecurityProblemSupport.class)
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

        @PostConstruct
        public void init() 
            try 
                authenticationManagerBuilder
                    .userDetailsService(userDetailsService)
                    .passwordEncoder(passwordEncoder());
             catch (Exception e) 
                throw new BeanInitializationException("Security configuration failed", e);
            
        
       @Bean
        public PasswordEncoder passwordEncoder() 
            return new BCryptPasswordEncoder();
        
    

【问题讨论】:

【参考方案1】:

其实我找到了答案。 我意识到我可以在类 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder 中使用matches 函数。

System.out.println(b.matches("passw0rd", "$2a$10$tztZsPFZ.T.82Gl/VIuMt.RDjayTwuMLAkRkO9SB.rd92vHWKZmRm"));

【讨论】:

这是解决方案,你能帮我理解spring security如何匹配存储在数据库中的哈希密码和用户提供的文本密码,当然这在编码后将是不同的哈希!!!???【参考方案2】:

您可以在 BCryptPasswordEncoder 中使用matches 方法,如下所示:

b.matches("passw0rd", hash)

【讨论】:

这是解决方案,你能帮我理解spring security如何匹配存储在数据库中的哈希密码和用户提供的文本密码,当然这在编码后将是不同的哈希!!!???【参考方案3】:

Spring Security 只是从之前生成的 hash 中读取 salt,并使用相同的 salt 再次重新散列输入密码。它会比较两个最终的哈希值,显然它是相同的。

例子:

密码:test

哈希:$2a$10$nCgoWdqJwQs9prt7X5a/2eWLn88I8pon6iNat90u4rq4mHqtoPGQy

哈希有 3 个段,每个段由 $ 符号分隔。 2a 是 Bcrypt 的版本,10 是总轮数,nCgoWdqJwQs9prt7X5a/2e 是盐。

所以 spring security 获取密码 test 和 salt nCgoWdqJwQs9prt7X5a/2e 并运行哈希方法。显然它会生成与密码和盐匹配相​​同的哈希。

【讨论】:

以上是关于如何将密码文本与 bcrypt 哈希值进行比较?的主要内容,如果未能解决你的问题,请参考以下文章

用 bcrypt (PHP) 比较两个哈希值

nodejs - 如何比较bcrypt的两个哈希密码

如何迁移密码哈希?

[将Bcrypt与phpto哈希密码结合使用不起作用

带有 BCrypt 哈希的 AES 256。如何从数据库中检查用户密码? [复制]

为啥不需要 salt 来比较 bcrypt 中的密码是不是正确?