简体   繁体   English

Java,PHP和Objective-C中的pbkdf2 pkcs5兼容哈希

[英]pbkdf2 pkcs5 compatible hashing in Java, PHP and Objective-C

I'm developing an app that requires pbkdf2 pkcs5 for password hashing. 我正在开发一个需要pbkdf2 pkcs5进行密码哈希处理的应用程序。 I think I have some working code in PHP & Java but I'm not sure why they are producing different results. 我想我在PHP和Java中有一些有效的代码,但是我不确定为什么它们会产生不同的结果。

Here are the code. 这是代码。

Php code: 邮递区号:

function hash_password($password, $salt, $user_id, $iterations) {
    $user_id = (string) $user_id;
    $raw_pass = $salt . $user_id . $password;

    $hash = hash_pbkdf2("sha512", $raw_pass, $salt, $iterations, 64, false);

    return $hash;
}

echo hash_password("password", $salt, 2058, 1);
echo PHP_EOL;

Java code: Java代码:

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.nio.charset.StandardCharsets;
import java.lang.RuntimeException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.math.BigInteger;
import javax.xml.bind.DatatypeConverter;


public final class Testing {
    private static String mSalt = "fd6c3dc0165dc420b4e9225bc9bee9684387e9621b2e2c00cfffebf1ec7c30b4";

    private static String hashPassword(String password, String salt, int userId, int iterations) throws RuntimeException {
        String uid = String.valueOf(userId);
        StringBuilder pwBuilder = new StringBuilder(salt);
        pwBuilder.append(uid);
        pwBuilder.append(password);
        String rawPass = pwBuilder.toString();

        try {
            SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), mSalt.getBytes(), iterations, 256);
            byte[] result = skf.generateSecret(spec).getEncoded();

            StringBuilder hashBuilder = new StringBuilder(result.length * 2);

            for (byte r : result) {
                hashBuilder.append(String.format("%02x", r));
            }

            return hashBuilder.toString();
       } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            throw new RuntimeException( e );
       }
    }

    public static void main(String[] args) {
        System.out.println(hashPassword("password", mSalt, 2058, 1000000));
        System.out.println("\n");
    }
}

Php output is: 3754036ea2f37af8160e45d15c2e4d6597157ead118f060e76152c0813f806e8 PHP输出是: 3754036ea2f37af8160e45d15c2e4d6597157ead118f060e76152c0813f806e8
Java output is: 8b135bb19263677b70f1d5cbda5a23bc16df38e5e1a624c6df9a462975cac899 Java输出是: 8b135bb19263677b70f1d5cbda5a23bc16df38e5e1a624c6df9a462975cac899

Can you recommend a library or a gist somewhere that has both compatible implementation? 您可以在兼具兼容实现的地方推荐一个库或要点吗?

You have two issues with your existing code: 您现有的代码有两个问题:

  1. Use the same number of iterations. 使用相同的迭代次数。

  2. Use the same concatenated password. 使用相同的串联密码。

In PHP: 在PHP中:

Use 采用

var_dump(hash_password("password", $salt, 2058, 1000000));

instead of 代替

var_dump(hash_password("password", $salt, 2058, 1));

In Java: 在Java中:

Use 采用

PBEKeySpec spec = new PBEKeySpec(rawPass.toCharArray(), mSalt.getBytes(), iterations, 256);

instead of 代替

PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), mSalt.getBytes(), iterations, 256);

After you've made those changes, both will produce the same result: 进行这些更改之后,两者都会产生相同的结果:

424a0b30ea0cdef2ff0185f49ce67ee44273ce7e41026044d527c85550b3a207

Other issues: 其他事宜:

  • Never use String#getBytes without a specific character set. 切勿String#getBytes没有特定字符集的情况下使用String#getBytes Otherwise, the system default will be used which can be different in different JVM's. 否则,将使用系统默认值,该默认值在不同的JVM中可能会有所不同。

  • If you're using PBKDF2 to hash passwords, then you will need to compare two hashes when verifying the re-entered password. 如果您使用PBKDF2对密码进行哈希处理,则在验证重新输入的密码时需要比较两个哈希值。 This requires a constant-time comparison function to prevent timing-based attacks. 这需要恒定时间比较功能以防止基于定时的攻击。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM