在使用Base64和MessageDigest生成的MySQL中存储SHA512哈希

时间:2016-06-08 20:26:20

标签: java mysql hash

我有一个实用程序类,其中有一个负责加密用户密码的方法。这是方法:

public static String encryptPassword(String password) {
    MessageDigest md = null;

    try {
        md = getInstance("sha-512");
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(PasswordUtils.class.getName()).log(Level.SEVERE, null, ex);
        throw new IllegalArgumentException();
    }

    md.update(password.getBytes());
    return Base64.getEncoder().encodeToString(md.digest());
}

我正在使用MySQL来保留我的数据,并希望将密码保留为VARCHAR。为了了解所需的长度,我做了一些研究,发现this postthis one谈论了所需的长度128.我用几个字符串和String.length()方法手动测试了方法散列字符串的长度为88.我还看到了一个示例项目并使用'VARCHAR(100)'来存储密码。

此算法的VARCHAR的最佳大小是多少?提前感谢您的回答。

2 个答案:

答案 0 :(得分:1)

sha512哈希的长度是512bit = 64byte / chars。因此,如果您只是将普通哈希存储为MySQL中的二进制字段,则需要64字节。

如果使用base64存储它们,则需要88个字符:base64每个字符只能存储6位信息,而不是普通字符的8位信息。所以你需要512bit / 6bit / char = 85,3bit。 Base64有一些填充规则,它必须始终用零填充数据,直到位数为6的倍数,因此填充到528bit / 6bit = 88bit。这是你需要的固定号码。

除此之外,存储简单哈希的密码永远不是一个好主意。它们可以通过彩虹表攻击轻松逆转。我确信有一些Linux crypt()兼容的java函数,它使用salt和几千轮来防止彩虹表攻击。

答案 1 :(得分:-1)

  1. SHA-512以及所有哈希函数都不加密。

  2. 简单地哈希密码不够且不安全,它们会遭受彩虹表攻击。至少需要一个含有随机盐的HMAC,但我们可以而且应该做得更好。

  3. 使用诸如Bcrypt,password_hash,PBKDF2等类似使用HMAC的函数并迭代使得该函数需要大约100ms,这是工作因素。

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

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

    只有在您希望密码安全时才需要这样做 - 您的用户应该这样做。

    来自DRAFT NIST Special Publication 800-63B Digital Authentication Guideline

      

    Verifiers SHALL以一种抵抗离线攻击的形式存储记忆的秘密。秘密应使用批准的哈希函数(如[SP800-132]中所述的PBKDF2)用盐值进行哈希处理。盐值应该是由批准的随机数生成器生成的32位(或更长)随机值,并与散列结果一起存储。应该执行散列函数的至少10,000次迭代。