使用盐处理密码散列的问题
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
然后在您的代码中与 hash
、hashSize
、算法和 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
后,这就是您在数据库中保存为文本的内容(varchar
或 char
)。您不将其分开并单独存储salt
。把它们全部混合在一起。
当用户想要登录时,他们会提供密码。现在你从数据库中为用户获取 parts
,你从 parts
中提取 salt
,iterations
的数量等等,因为毕竟你知道它是怎么回事串联。然后您使用该信息再次对用户输入的密码进行哈希处理。现在将新哈希与旧哈希进行比较。如果它们相同,那么用户就提供了正确的密码,如果不相同,则用户没有提供。
Always writes [B@29453f44
In the console.
正如@JonSkeet所说,答案在Converting String to Sha-256 Hash
中给出
这是我第一次在 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
然后在您的代码中与 hash
、hashSize
、算法和 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
后,这就是您在数据库中保存为文本的内容(varchar
或 char
)。您不将其分开并单独存储salt
。把它们全部混合在一起。
当用户想要登录时,他们会提供密码。现在你从数据库中为用户获取 parts
,你从 parts
中提取 salt
,iterations
的数量等等,因为毕竟你知道它是怎么回事串联。然后您使用该信息再次对用户输入的密码进行哈希处理。现在将新哈希与旧哈希进行比较。如果它们相同,那么用户就提供了正确的密码,如果不相同,则用户没有提供。
Always writes
[B@29453f44
In the console.
正如@JonSkeet所说,答案在Converting String to Sha-256 Hash
中给出