java 中的 Symfony FOSUser Hash 算法

Symfony FOSUser Hash algorithm in java

嘿,每个人都在试图找出我使用的是哪种哈希算法 symfony FOS User Bundle 我做了一些研究,其中提到 FOSUser Bundle 默认安全配置使用 Sha512() 和迭代 5000 次 + salt 然后是 bas64 编码 我实际上是这些 hash 算法的新手,但是这是 php

中的算法
$password = 'toto';
$salt = '1234';
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, true);

for ($i=1; $i<5000; $i++) {
  $digest = hash('sha512', $digest.$salted, true);
}

$encodedPassword = base64_encode($digest); 
}

取自此postHow do I generate a SALT in Java for Salted-Hash?

因为我不熟悉 java hash libraries 谁能帮我把这段代码翻译成 Java

密码加密的 Symfony 默认设置是 Bcrypt 您的 security.yml 配置文件中提到的代码

encoders:
    Symfony\Component\Security\Core\User\User:
        algorithm: bcrypt
        cost:      15

在我的例子中,我使用了一个技巧,因为我所有的密码都以上午 13 点开始,假设 salt 等于 13 所以我尝试使用 java BCrypt

将其翻译成 java
public boolean checkPassword(String passwordText, String DbHash) {
    boolean password_verified = false;
    if (null == DbHash || !DbHash.startsWith("a$")) {
        throw new java.lang.IllegalArgumentException("Invalid hash provided for comparison");
    }
    password_verified = BCrypt.checkpw(passwordText, DbHash);
    return (password_verified);
 }

passwordText 您的实际密码,DbHash 存储的哈希值

此代码检查密码哈希是否匹配密码

有一个技巧 symfony 散列密码以 y$ 开头所以要完成这项工作你需要将 y$ 更改为 a$

例如,我的密码的哈希值存储在我的数据库中

String passwordText = "admin"; 
String DbHash  = "y$VVmaKXzaS2QWgU1S4I8h5eJgC/DduF2fXmnhvcynro004GCUAQfr2";

改变这个:

String DbHash  = "y$VVmaKXzaS2QWgU1S4I8h5eJgC/DduF2fXmnhvcynro004GCUAQfr2"; 

对此:

String DbHash  = "a$VVmaKXzaS2QWgU1S4I8h5eJgC/DduF2fXmnhvcynro004GCUAQfr2";  

解决方案是使用 Java API 对密码进行编码,例如 MessageDigestPasswordEncoder:

  1. 生成盐(长度=43):

    private static String generateSalt() {
    SecureRandom random = new SecureRandom();
    byte[] salt = new byte[SALT_SIZE];
    random.nextBytes(salt);
    String saltBase64_encoded=BaseEncoding.base64().encode(salt);
    String saltPlusDot= saltBase64_encoded.replace("+",".");
    return saltPlusDot.substring(0,saltPlusDot.length()-1);
    

    }

BaseEncoding.base64() 是 commons-codec api

中的 class
  1. concat: 密码 + { + 盐 + }:

    private static String mergePasswordAndSalt(String pass, String salt) {
    if (salt == null) {
        return salt;
    }
    String cg="{";String cd="}";
    return pass+cg+salt+cd;
    

    }

  2. 对于每个额外的迭代:散列前一个摘要的连接 + 盐:

private static byte[] encodePassword(String password,String salt) 抛出 NoSuchAlgorithmException,UnsupportedEncodingException {

    String mergedPasswordAndSalt =mergePasswordAndSalt(password, salt);  
    MessageDigest digester = MessageDigest.getInstance(ALGORITHM);

    byte[] hash = digester.digest(mergedPasswordAndSalt .getBytes("UTF-8"));

    for (int i = 1; i < ITERATIONS; ++i) {


     hash = digester.digest(Bytes.concat(hash, mergedPasswordAndSalt.getBytes("UTF-8")));   

    }
        return hash;
    }

Bytes.concat(bytes ...) 是 guava 19.0 api

中的一种方法

这是githubFOSJcrypt

中的API