使用盐处理密码散列的问题

Problems working with Password Hashing using salt

这是我第一次在 Web 应用程序中处理密码散列。 我用了https://www.codeproject.com/articles/704865/salted-password-hashing-doing-it-right for theory and copied a sample from https://github.com/defuse/password-hashing。 以我的理解,每个帐户的盐都应该是唯一的。所以我的问题是:

为什么这个方法会产生盐分:

 public static String createHash(char[] password)
    throws CannotPerformOperationException
{
    // Generate a random salt
    SecureRandom random = new SecureRandom();
    byte[] salt = new byte[SALT_BYTE_SIZE];
    random.nextBytes(salt);

    // Hash the password
    byte[] hash = pbkdf2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
    int hashSize = hash.length;

    // format: algorithm:iterations:hashSize:salt:hash
    String parts = "sha1:" +
        PBKDF2_ITERATIONS +
        ":" + hashSize +
        ":" +
        toBase64(salt) +
        ":" +
        toBase64(hash);
    return parts;
}

我需要的是一个函数,它存储哈希密码和数据库中使用的盐。我怎样才能从这里取回用过的盐?

System.out.println(salt);

总是写

[B@29453f44

在控制台中。为什么会这样?我需要什么数据类型来将盐存储在 mysql 数据库中?还是我方法不对?

如果我正确理解你的问题,那么:

In my understanding, the salt should be unique for every account.

byte[] salt = new byte[SALT_BYTE_SIZE];
random.nextBytes(salt);

生成随机盐,使其独一无二。 您也可以对数据库中的用户或其他唯一的用户使用 ID,但随机生成的盐也是唯一的,因为毕竟,对于每个新用户,都会随机生成一个新的盐。

这个 salt 然后在您的代码中与 hashhashSize、算法和 iterations 的数量连接在一起成为 parts

 // format: algorithm:iterations:hashSize:salt:hash
String parts = "sha1:" +
    PBKDF2_ITERATIONS +
    ":" + hashSize +
    ":" +
    toBase64(salt) +
    ":" +
    toBase64(hash);
return parts;

通常您知道 parts 中不同部分的长度(字节大小),因此可以提取您需要的部分。在您的情况下,您甚至添加了一个 : 作为分隔符,这使得提取您感兴趣的部分变得更加简单。

And what data type would I Need to store the salt in the mysql database?

获得 parts 后,这就是您在数据库中保存为文本的内容(varcharchar)。您不将其分开并单独存储salt。把它们全部混合在一起。

当用户想要登录时,他们会提供密码。现在你从数据库中为用户获取 parts,你从 parts 中提取 saltiterations 的数量等等,因为毕竟你知道它是怎么回事串联。然后您使用该信息再次对用户输入的密码进行哈希处理。现在将新哈希与旧哈希进行比较。如果它们相同,那么用户就提供了正确的密码,如果不相同,则用户没有提供。

Always writes [B@29453f44 In the console.

正如@JonSkeet所说,答案在Converting String to Sha-256 Hash

中给出