我已经有一个包含名为User的表的数据库,该表包含表盐,密码等...
我的数据库是由symfony(ORM+FOSUserBundle)
使用sha512创建的。
我正在尝试获取salt和密码,并将它们从桌面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的salt但是,当我添加一个用户使用该盐并生成哈希时,我无法从我的Web应用程序登录此用户(已经说FOSUserBundle控制认证和编码/解码算法)
答案 0 :(得分:1)
如果我正确阅读,您的摘要编码器实施中会出错。
参考点:
<强> MessageDigestPasswordEncoder.php 强>
<强> BasePasswordEncoder.php 强>
当您请求手动生成摘要时,基本上有两个步骤:
password
+ {
+ salt
+ }
previous digest
+ salt
的concat进行哈希处理(请注意,此步骤不会添加{
或}
字符)所以,我在你的实现中看到了两个问题:
{
和}
希望这有点帮助...