如何将盐与生成的密码进行比较?
How do I compare salt with a generated password?
所以我正在尝试将我的原始密码与经过加盐处理的密码进行比较。我知道如何比较哈希密码,我将原始密码添加到它的哈希中并且它有效。但是,我不知道如何比较盐。
public static String saltPassword(String password) throws NoSuchAlgorithmException{
String salt = getSalt();
return password + salt;
}
public static String getSalt(){
Random r = new SecureRandom();
byte[] saltBytes = new byte[32];
r.nextBytes(saltBytes);
return Base64.getEncoder().encodeToString(saltBytes);
}
我需要做什么才能将原始密码与此进行比较?
这就是我的作业所说的,
"Compare the generated password with the stored salt and hashed password".
你也应该储存盐。当两个用户选择相同的密码时,Salt 用于防止生成相同的散列密码。类似于以下代码的东西可用于将密码保存为 hashedPassord 并验证输入 password.It 不完整但可用作示例代码。
private static void savePassword(String rawPassword) throws InvalidKeySpecException, NoSuchAlgorithmException {
byte[] salt = getSalt();
String hashedPassword = getHashedPassword(rawPassword, salt);
String encodedSalt = base64Encode(salt);
/* todo: store hashPassword and encodedSalt */
}
private static boolean verifyPassword(String rawPassword, String hashedPassword, String encodedSalt) throws InvalidKeySpecException, NoSuchAlgorithmException {
return Objects.equals(hashedPassword, getHashedPassword(rawPassword, base64Decode(encodedSalt)));
}
private static String getHashedPassword(String rawPassword, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec spec = new PBEKeySpec(rawPassword.toCharArray(), salt, 65536, 128);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = factory.generateSecret(spec).getEncoded();
return base64Encode(hash);
}
private static byte[] getSalt() {
Random r = new SecureRandom();
byte[] saltBytes = new byte[32];
r.nextBytes(saltBytes);
return saltBytes;
}
private static String base64Encode(byte[] src) {
return Base64.getEncoder().encodeToString(src);
}
private static byte[] base64Decode(String src) {
return Base64.getDecoder().decode(src);
}
How do I compare salt with a generated password?
What do I have to do to compare the original password with this?
答案是,如果这些事情你都不做。
要注册原始密码,请执行以下操作:
- 获得盐1
- 将原始密码与salt合并
- 散列。
- 存储盐和散列。
然后您丢弃原始密码。
要检查您提供的密码是否正确,请执行以下操作:
- 查找注册时创建的存储哈希和相应的盐;见上文。
- 以与上述相同的方式组合提供的密码和盐。
- 如上哈希。
- 将生成的哈希值与存储的哈希值进行比较。如果它们相同,那么提供的密码就是正确的密码。
如您所见,您没有将加盐值或原始密码与任何东西进行比较。
但在为原始密码和您正在检查的密码生成哈希值时,使用相同的盐也很重要。如果不这样做,密码检查将不起作用。
1 - salt 只是一个数字或字符串。理想情况下,盐值应该不同。加盐的目的是避免所谓的 "rainbow table" attack 从被盗(未加盐)的密码哈希中恢复原始密码。如果有(比如说)一百万个可能的盐值,那么坏人就需要生成一百万个不同的彩虹表。生成和存储许多彩虹表变得不切实际。
好的,这就是我所拥有的。我很想查找存储的密码,但我的老师在她的解决方案视频中没有那样做
public static String saltPassword(String password) throws NoSuchAlgorithmException{
String salt = getSalt();
return hashPassword(password + salt);
}
public static String getSalt(){
Random r = new SecureRandom();
byte[] saltBytes = new byte[32];
r.nextBytes(saltBytes);
return Base64.getEncoder().encodeToString(saltBytes);
}
public static String generatePassword(){
String charSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-+!@#$%";
String password = "";
int start = 0;
int stop = 0;
int minLength = 8;
for (int i = 0; i <= minLength; i++) {
// get a random character from the chars string
start = getRandomNumber(charSet.length());
stop = start + 1;
password += charSet.substring(start, stop);
}
return password;
}
private static int getRandomNumber(int maxValue){
double randomNumber;
randomNumber = Math.floor(Math.random() * maxValue);
return (int)randomNumber;
}
public static String hashPassword(String password)throws NoSuchAlgorithmException{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes());
byte[] mdArray = md.digest();
StringBuilder sb = new StringBuilder(mdArray.length * 2);
for (byte b : mdArray){
int v = b & 0xff;
if(v < 16){
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString();
}
然后创建它我要去
String newPassword = PasswordUtil.generatePassword();
String hashedPassword = "";
String saltedPassword = "";
try{
hashedPassword = PasswordUtil.hashPassword(newPassword);
}
catch(NoSuchAlgorithmException e){
System.out.println();
}
try{
saltedPassword = PasswordUtil.saltPassword(hashedPassword);
}
catch(NoSuchAlgorithmException e) {
System.out.println();
}
接下来会发生什么?
这是哈希密码:
50f99d2a635cc9bac7e001506789b55a7c603d93c89d362cc5d95ab257fc2666
这是加了盐的散列
e954fbc2309cc359cd603effb6d0644947a3253110ad6c3b2416dd49168331a3
所以我正在尝试将我的原始密码与经过加盐处理的密码进行比较。我知道如何比较哈希密码,我将原始密码添加到它的哈希中并且它有效。但是,我不知道如何比较盐。
public static String saltPassword(String password) throws NoSuchAlgorithmException{
String salt = getSalt();
return password + salt;
}
public static String getSalt(){
Random r = new SecureRandom();
byte[] saltBytes = new byte[32];
r.nextBytes(saltBytes);
return Base64.getEncoder().encodeToString(saltBytes);
}
我需要做什么才能将原始密码与此进行比较?
这就是我的作业所说的, "Compare the generated password with the stored salt and hashed password".
你也应该储存盐。当两个用户选择相同的密码时,Salt 用于防止生成相同的散列密码。类似于以下代码的东西可用于将密码保存为 hashedPassord 并验证输入 password.It 不完整但可用作示例代码。
private static void savePassword(String rawPassword) throws InvalidKeySpecException, NoSuchAlgorithmException {
byte[] salt = getSalt();
String hashedPassword = getHashedPassword(rawPassword, salt);
String encodedSalt = base64Encode(salt);
/* todo: store hashPassword and encodedSalt */
}
private static boolean verifyPassword(String rawPassword, String hashedPassword, String encodedSalt) throws InvalidKeySpecException, NoSuchAlgorithmException {
return Objects.equals(hashedPassword, getHashedPassword(rawPassword, base64Decode(encodedSalt)));
}
private static String getHashedPassword(String rawPassword, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec spec = new PBEKeySpec(rawPassword.toCharArray(), salt, 65536, 128);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = factory.generateSecret(spec).getEncoded();
return base64Encode(hash);
}
private static byte[] getSalt() {
Random r = new SecureRandom();
byte[] saltBytes = new byte[32];
r.nextBytes(saltBytes);
return saltBytes;
}
private static String base64Encode(byte[] src) {
return Base64.getEncoder().encodeToString(src);
}
private static byte[] base64Decode(String src) {
return Base64.getDecoder().decode(src);
}
How do I compare salt with a generated password?
What do I have to do to compare the original password with this?
答案是,如果这些事情你都不做。
要注册原始密码,请执行以下操作:
- 获得盐1
- 将原始密码与salt合并
- 散列。
- 存储盐和散列。
然后您丢弃原始密码。
要检查您提供的密码是否正确,请执行以下操作:
- 查找注册时创建的存储哈希和相应的盐;见上文。
- 以与上述相同的方式组合提供的密码和盐。
- 如上哈希。
- 将生成的哈希值与存储的哈希值进行比较。如果它们相同,那么提供的密码就是正确的密码。
如您所见,您没有将加盐值或原始密码与任何东西进行比较。
但在为原始密码和您正在检查的密码生成哈希值时,使用相同的盐也很重要。如果不这样做,密码检查将不起作用。
1 - salt 只是一个数字或字符串。理想情况下,盐值应该不同。加盐的目的是避免所谓的 "rainbow table" attack 从被盗(未加盐)的密码哈希中恢复原始密码。如果有(比如说)一百万个可能的盐值,那么坏人就需要生成一百万个不同的彩虹表。生成和存储许多彩虹表变得不切实际。
好的,这就是我所拥有的。我很想查找存储的密码,但我的老师在她的解决方案视频中没有那样做
public static String saltPassword(String password) throws NoSuchAlgorithmException{
String salt = getSalt();
return hashPassword(password + salt);
}
public static String getSalt(){
Random r = new SecureRandom();
byte[] saltBytes = new byte[32];
r.nextBytes(saltBytes);
return Base64.getEncoder().encodeToString(saltBytes);
}
public static String generatePassword(){
String charSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-+!@#$%";
String password = "";
int start = 0;
int stop = 0;
int minLength = 8;
for (int i = 0; i <= minLength; i++) {
// get a random character from the chars string
start = getRandomNumber(charSet.length());
stop = start + 1;
password += charSet.substring(start, stop);
}
return password;
}
private static int getRandomNumber(int maxValue){
double randomNumber;
randomNumber = Math.floor(Math.random() * maxValue);
return (int)randomNumber;
}
public static String hashPassword(String password)throws NoSuchAlgorithmException{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes());
byte[] mdArray = md.digest();
StringBuilder sb = new StringBuilder(mdArray.length * 2);
for (byte b : mdArray){
int v = b & 0xff;
if(v < 16){
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString();
}
然后创建它我要去
String newPassword = PasswordUtil.generatePassword();
String hashedPassword = "";
String saltedPassword = "";
try{
hashedPassword = PasswordUtil.hashPassword(newPassword);
}
catch(NoSuchAlgorithmException e){
System.out.println();
}
try{
saltedPassword = PasswordUtil.saltPassword(hashedPassword);
}
catch(NoSuchAlgorithmException e) {
System.out.println();
}
接下来会发生什么?
这是哈希密码:
50f99d2a635cc9bac7e001506789b55a7c603d93c89d362cc5d95ab257fc2666
这是加了盐的散列
e954fbc2309cc359cd603effb6d0644947a3253110ad6c3b2416dd49168331a3