gpt4 book ai didi

java - 如何在数据库中持久保存指定长度的盐

转载 作者:行者123 更新时间:2023-11-30 06:14:44 26 4
gpt4 key购买 nike

我已经有一个数据库,其中包含一个名为 User 的表,该表包含食盐、密码等...

  1. salt 列的数据长度为 43
  2. 密码列包含长度为 88 的数据

我的数据库是由 symfony(ORM+FOSUserBundle) 创建的,他使用 sha512。

我试图获取盐和密码,并将它们从桌面java应用程序存储到数据库中,所以我尝试了这个类:

import com.google.common.io.BaseEncoding;
import org.slf4j.Logger;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.google.common.primitives.Bytes;
import org.slf4j.LoggerFactory;

public class SHA512 {
private static final Logger log = LoggerFactory.getLogger(SHA512.class);
private static final String ALGORITHM = "SHA-512";
private static final int ITERATIONS = 5000;
private static final int SALT_SIZE = 43;


/**
* Private constructor.
*/
private SHA512() {
}

public static void main(String[] args) {
String password = "0000";

try {

byte[] salt = generateSalt();
log.info("Password {}. hash algorithm {}, iterations {}, salt {}", password, ALGORITHM, ITERATIONS,
BaseEncoding.base64().encode(salt));
byte[] hash = calculateHash(password, salt);
boolean correct = verifyPassword(hash, password, salt);

log.info("Entered password is correct: {}", correct);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
log.error(ex.getMessage(), ex);
}
}


private static byte[] generateSalt() {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[SALT_SIZE];
random.nextBytes(salt);

return salt;
}

private static byte[] calculateHash(String password, byte[] salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance(ALGORITHM);
md.reset();
md.update(Bytes.concat(password.getBytes("UTF-8"), salt));
byte[] hash = md.digest();

for (int i = 0; i < ITERATIONS; i++) {
md.reset();
hash = md.digest(hash);
}
return hash;
}

private static boolean verifyPassword(byte[] originalHash, String password, byte[] salt) throws
NoSuchAlgorithmException, UnsupportedEncodingException {
byte[] comparisonHash = calculateHash(password, salt);

log.info("hash 1: {}", BaseEncoding.base64().encode(originalHash));
log.info("hash 2: {}", BaseEncoding.base64().encode(comparisonHash));

return comparePasswords(originalHash, comparisonHash);
}

/**
* Compares the two byte arrays in length-constant time using XOR.
*
* @param originalHash The original password hash
* @param comparisonHash The comparison password hash
* @return True if both match, false otherwise
*/
private static boolean comparePasswords(byte[] originalHash, byte[] comparisonHash) {
int diff = originalHash.length ^ comparisonHash.length;
for (int i = 0; i < originalHash.length && i < comparisonHash.length; i++) {
diff |= originalHash[i] ^ comparisonHash[i];
}

return diff == 0;
}
}

我需要长度为 43 的盐,但是 BaseEncoding.base64().encode(salt) 输出长度等于 60 的盐。我将 SALT_SIZE 修改为 30 并 BaseEncoding.base64().encode(salt) 输出长度等于 40 的盐,但是,当我使用该盐添加用户并生成哈希值时,我可以't 从我的 Web 应用程序中使用此用户登录(已经说过 FOSUserBundle 控制身份验证和编码/解码算法)

最佳答案

如果我没看错的话,那么您的摘要编码器实现中有一个错误。

引用点:

<强> MessageDigestPasswordEncoder.php

<强> BasePasswordEncoder.php

当您请求手动生成摘要时,基本上有两个步骤:

  1. 对连接进行哈希处理:password + { + salt + }
  2. 对于每个额外的迭代:对前一个摘要 + salt 的 concat 进行哈希处理(请注意,此步骤不会添加 { } 字符)

所以,我在您的实现中发现了两个问题:

  1. 在我看来,您没有在迭代 #0 中包含这些 {}
  2. 您尚未在以后的任何迭代中添加盐

希望这能有所帮助......

关于java - 如何在数据库中持久保存指定长度的盐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49476116/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com