【问题标题】:Apache Shiro - password format issueApache Shiro - 密码格式问题
【发布时间】:2015-01-05 11:16:12
【问题描述】:

我尝试将 PasswordMatcher 与 DefaultPasswordService 与 DefaultHashService 一起使用。

DefaultHashService hashService = new DefaultHashService();
hashService.setHashIterations(10000); 
hashService.setHashAlgorithmName(Sha512Hash.ALGORITHM_NAME);
hashService.setGeneratePublicSalt(true);

DefaultPasswordService passwordService = new DefaultPasswordService();
passwordService.setHashService(hashService);
String encryptedPassword = passwordService.encryptPassword("password");
System.out.println("Result:"+encryptedPassword);

这是我必须在密码列中保存到数据库中的结果。

$shiro1$SHA-512$10000$T5nkQEA3qjMLPuB/x+WN4Q==$qWViYjBljsMwH7FSvhecKlxQqXY11lv8eS4guxD9t8D4HTeKclN/muyTnhzYZ+YvI1YkEg6L7T2kM3qykUG0XQ==

一切正常。但是我的问题是为什么迭代次数和算法名称与盐和密码一起保存?在这种情况下,我们会通知潜在的攻击者,他们会转储我们的数据库有关这些重要属性的信息。

【问题讨论】:

    标签: java jakarta-ee hash shiro


    【解决方案1】:

    如今,我们的目标是保护用户密码,即使攻击者知道所有实施机密。这被称为“white-box encryption”:

    在这种情况下,“白盒攻击者”可以完全访问加密算法的软件实现:攻击者完全可以看到和更改二进制文件;并且攻击者可以完全控制执行平台(CPU 调用、内存寄存器等)。因此,实现本身是唯一的防线。

    话虽如此,您可以将哈希算法和迭代计数与密码一起存储,因为您必须假设攻击者也可以访问代码/二进制文件(如果他们可以访问数据库,这并非不可能) .

    将迭代次数与哈希一起存储还有一个额外的好处:将来您可能希望更改为更多的迭代次数,因为处理能力已经提高。然后,您可以轻松升级您的数据库,方法是使用旧迭代次数检查所有哈希,应用一些额外的迭代并将新结果存储在数据库中,升级到更安全的方案。

    同样,如果您将哈希算法添加到哈希中,您可以在以后轻松更改为其他密码方案(bcrypt,...),并在用户下次登录时优雅地升级。

    【讨论】:

    • 非常感谢。但是为什么我们在 shiro 中设置以下设置,如果它们是从 pass 中获取的,我的意思是:hashService.hashIterations = 10000,hashService.hashAlgorithmName = SHA-512, hashService.generatePublicSalt = true。没必要吗?
    • 我不熟悉 Shiro API,但无论哪种情况,您都必须在第一次为用户创建哈希时设置它们,我不知道 Shiro 是否可以从生成哈希本身,或者如果您必须提供这些值。
    • 实际上这些设置不应该在代码中。 DefaultPasswordService 实际上甚至不使用它们,请参阅stackoverflow.com/a/12902798/2969332
    • 感谢您的参考。那里提到的邮件列表线程写道:“这是因为在使用 PasswordService 时,凭证对象是一个模块化加密格式 [1] 字符串,其中嵌入了盐(和任何其他必要的数据)在字符串中。由于这个假设 (...),实现不检查除了 authcInfo.getCredentials() 之外的任何属性;"所以 Shiro 实际上在解密时确实从密码字符串中检索了迭代,并且在加密时只尊重迭代设置。
    【解决方案2】:

    因此,当您更改密码服务的默认算法时,您仍然可以检查先前生成的密码的哈希值。

    至于你对帮助潜在黑客的担忧,有一个简单的方法可以规避这个问题,在哈希算法中添加一个私有盐字符串:

    private static final String PRIVATE_SALT = "some_random_string_you_only_know";
    ...
    hashService.setPrivateSalt(new SimpleByteSource(PRIVATE_SALT));
    

    【讨论】:

      猜你喜欢
      • 2021-12-18
      • 2015-10-24
      • 2014-08-06
      • 2014-09-18
      • 2016-04-02
      • 2011-10-04
      • 2014-12-06
      • 2020-12-11
      • 2017-10-20
      相关资源
      最近更新 更多