【问题标题】:Standard way of comparing the password/sensitive fields [closed]比较密码/敏感字段的标准方法[关闭]
【发布时间】:2016-11-09 12:26:25
【问题描述】:

我有一个场景,我必须匹配密码/敏感信息并检查验证。 现在我可以想出两种方法。

1) 我们可以通过从以加密形式存储在那里的数据库中获取正确的密码来比较加密形式的密码/敏感字段。

2) 或者我们可以先将密码解密为纯文本格式,然后进行比较。现在在这种情况下,需要额外调用解密实用程序,这是一种开销。

我查看了 String 类的“equals()”方法,它在摊销的常数时间内运行。因此,如果加密字符串是非常长的字符串,那么它将影响“equals()”方法的性能。 但在我的情况下,加密字符串并没有那么长。

但我主要关心的是通常遵循的标准是什么。 更新 1:

public static String encrypt(String text, String algo, byte[] bytes)     throws NoSuchPaddingException, NoSuchAlgorithmException,
            IllegalBlockSizeException, BadPaddingException,     InvalidKeyException {
        if (text == null || algo == null || bytes == null) {
            //log properly
            System.out.println("Please provide a valid text, algo or key bytes");
            return null;
        }
       Key key = generateKey(bytes, algo);
        Cipher c = Cipher.getInstance(algo);
         c.init(Cipher.ENCRYPT_MODE, key);
        byte[] envValue = c.doFinal(text.getBytes());
        String encVal2 = new BASE64Encoder().encode(envValue);
        return encVal2;
    }`

更新 2:

 while (i < 300000) {
            String value = KeyValidator.getSystemLicKey(KEY_);
            if (!value.equals(value1))
                System.out.println("--- : false");
            value1 = value;
            i++;
        }

【问题讨论】:

  • 典型的方法是比较两个加密密码。使用正确的算法,字符串“非常长”的可能性很小。

标签: java encryption


【解决方案1】:

不要加密密码。使用随机盐在 HMAC 上迭代大约 100 毫秒(盐需要与哈希一起保存)。使用 password_hash、PBKDF2、Bcrypt 等函数和类似函数。关键是让攻击者花费大量时间通过蛮力寻找密码。

请参阅 OWASP(开放式 Web 应用程序安全项目)Password Storage Cheat Sheet

请参阅 Security Stackexchange 上的 How to securely hash passwords, The Theory

要查看哈希密码是如何受到攻击的,请参阅:
密码列表SecLists.
信息安全password-cracking-tools
ArstechnicaHow I became a password cracker.

【讨论】:

  • 带有“an HMAC”,您指的是哪些消息和密钥?我很困惑,因为密码只是一个部分,而 hmac 用于使用某些密钥对加密消息进行身份验证,还是我遗漏了什么? (从代表来看,我错过了一些东西......)
  • 向 HMAC 提供了两件事,密码和随机盐。随机盐与散列密码一起存储,不需要保密。 salt 的目的,对于每个密码来说本质上是不同的,它的目的是如果多个用户有相同的密码,那么哈希值就会不同。如果哈希值没有差异,则发现一个用户的密码也会泄露所有其他具有相同密码的用户。盐还可以防止使用rainbow tables
  • @dandavis 虽然 HMAC 用于验证加密消息并不是唯一的用途,但许多加密功能有多种用途,在设计时的用途不同于最初的意图,PBKDF2 是另一个非常适合的例子为了密码安全。当使用盐只是将其连接到密码并且散列不安全时,HMAC 通过使用两个散列操作来避免这种不安全性。见HAMC
  • 非常感谢您提供的信息;说得通。我一直看到很多人在我认为没有意义的情况下谈论 HMAC,因为那里的大多数读物只谈论它是如何在不透露密钥的情况下验证消息和密钥的一种方式。
【解决方案2】:

永远不要加密你的密码总是散列它!!! 参考:https://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet(规则 - 存储密码的单向和加盐值)

让 shiro 使用盐和哈希

检查How to stock and use a shiro's salt from database 在数据库中存储盐和密码。

【讨论】:

  • 好建议 WRT 永远不要加密密码,但会遗漏一个工作因素。
  • 这些天盐和哈希是不够的,来吧人们,努力跟上!
  • 我不明白对这个问题投反对票的原因。有人可以帮我理解这一点。这样我以后就可以避免同样的事情了。
【解决方案3】:

如果您使用的是哈希算法(例如 SHA1、SHA256 等),您需要对输入运行相同的算法并比较结果。

如果您使用加密算法(例如 AES),通常您必须先解密。 请注意,在加密某些东西时,一个好的算法会使用一些盐,这意味着在对同一字符串应用相同的算法时,您会得到不同的结果,因此解密是您唯一的选择。

密码通常以散列方式存储,因为您不需要知道真正的密码,而其他敏感数据(例如信用卡号)则以加密方式存储。

最后一点:散列算法和加密算法都提供字节数组,而不是字符串。所以你应该存储和比较字节数组而不是字符串。如果您需要存储/比较字符串,您可以使用某种编码算法对结果进行编码,例如BASE64。

更新: OWASP 有一个很好的Cheat Sheet 关于密码存储。

更新 2: 关于加密,使用 Apache Shiro 的小例子。运行一下,你会发现没有两行是一样的。

    Key key = new AesCipherService().generateNewKey(128);
    AesCipherService cipher = new AesCipherService();
    for (int i = 0; i <20; ++i) {
        System.out.println(Hex.encode(cipher.encrypt("abcde".getBytes(StandardCharsets.UTF_8), key.getEncoded()).getBytes()));
    }

【讨论】:

  • 我在 JCA java 中使用了 AES 实现,并尝试将相同的字符串加密 300000 次,但每次都得到相同的字符串。我有没有错过什么。 @Tarlog
  • 是的,你错过了一些东西。除非你在这里发布你的代码,否则我不能准确地说出什么,但即使使用相同的密钥加密相同的文本,你也不能得到相同的结果。
  • 查看更新 2 的 AES 示例。
  • public static String getSystemLicKey(String deviceId) { final String algo = "AES";最终字节[] BYTE_KEY = 新字节[]{'A','B','C','D','E','F','G','H','I','J' ,'K','L','M','N','O','P'};尝试 { 返回 AESEncryptExample.encrypt(deviceId, algo, BYTE_KEY); } catch (Exception ex) { //日志异常发生 return null; } }
  • 这个答案提供的安全性比使用最佳实践轻松实现的安全性要弱得多。
猜你喜欢
  • 2019-09-27
  • 2013-04-01
  • 1970-01-01
  • 2016-11-19
  • 1970-01-01
  • 1970-01-01
  • 2021-03-06
  • 2014-10-26
  • 2018-01-14
相关资源
最近更新 更多