这是我第一次在Web应用程序中处理密码散列。 我使用https://www.codeproject.com/articles/704865/salted-password-hashing-doing-it-right作为理论并从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数据库中?或者我的方法是否错误?
答案 0 :(得分:0)
如果我理解你的问题,那么:
根据我的理解,每个帐户的盐应该是唯一的。
byte[] salt = new byte[SALT_BYTE_SIZE];
random.nextBytes(salt);
生成随机盐,使其独一无二。
您也可以使用ID
从数据库或其他独特的用户,但随机生成的盐也是唯一的,因为毕竟,为每个新用户随机生成一个新的盐。
然后,您的代码中的salt
与hash
,hashSize
,算法以及iterations
的数量parts
连接在一起1} p>
// format: algorithm:iterations:hashSize:salt:hash
String parts = "sha1:" +
PBKDF2_ITERATIONS +
":" + hashSize +
":" +
toBase64(salt) +
":" +
toBase64(hash);
return parts;
通常你知道parts
中不同部分的长度(字节大小),因此可以提取你需要的部分。在您的情况下,您甚至添加了:
作为分隔符,这使得提取您感兴趣的部分变得更加简单。
我需要将哪种数据类型存储在mysql数据库中?
获得parts
后,这就是您在数据库中以文字(varchar
或char
)保存的内容。您不要将其分开并单独存储salt
。把它们混合在一起吧。
当用户想要登录时,他们会提供密码。现在,您从数据库中为用户提取parts
,从salt
中提取iterations
,parts
的数量,依此类推,因为毕竟,您确切知道它是怎么回事级联。然后,您使用该信息再次对用户输入的密码进行哈希处理。现在,您将新哈希与旧哈希进行比较。如果它们是相同的,那么用户给出了正确的密码,如果没有,他就没有。
始终在控制台中写
[B@29453f44
。
正如@JonSkeet所说,答案在Converting String to Sha-256 Hash
中给出