Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PBKDF2WithHmacSHA1 key generation Takes too long on Android

I want to generate key using PBKDF2WithHmacSHA1, but it takes too long to calculate on android. I am using same number of iteration on iOS with common crypto and it takes approximately 6 seconds where as on android it takes 100 seconds.

Here is the code:

public static String generateStorngPasswordHash(String password)
{
    try
    {
        char[] chars = password.toCharArray();
        byte[] salt = getSalt();

        PBEKeySpec spec = new PBEKeySpec(chars, salt, 1010101, 32 * 8);
        SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        byte[] hash = skf.generateSecret(spec).getEncoded();

        return toHex(salt) + ":" + toHex(hash);
    } catch (Exception e)
    {
        Logger.e("Exception: Error in generating password" + e.toString());
    }
    return "";
}

private static byte[] getSalt() throws NoSuchAlgorithmException
{
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    byte[] salt = new byte[32];
    sr.nextBytes(salt);
    return salt;
}

Please let me know if there is any problem with this code?

EDIT

One more thing, I am also using sqlCipher in my application. They use openssl for calculating PKDF2 and I have read somewhere that openssl implementation is very faster than java implementation to find PKDF2. So my question is:

  1. Is this true that openssl can give me better performace on android?
  2. Can I use openssl implementation used in sqlCipherg?
  3. If yes how can I use caclulate PKDF2 using openssl?
  4. If No then how can I use openssl to find PBKDF2WithHmacSHA1 in android. I have
    searched over the net but didn't found any example.
like image 493
Nauman Afzaal Avatar asked Jul 09 '14 11:07

Nauman Afzaal


1 Answers

Yes, Java is significantly slower than (Objective) C with regards to performing SHA in a loop. Java is not particularly fast for crypto compared to compiled languages. On the other hand it allows for relatively safe code. So your result don't come to a shock to me. Unless you can use another, faster provider that uses native code then you should expect results like this.

There are however methods to mitigate what is happening. You could for instance lower your number of iterations. Higher numbers are safer, but they only help you to increase the workload of an attacker linearly. Taking other measures such as a limited number of tries, a safer DB or requiring better passphrases may provide better security than just upping the iteration count. If possible, do not overly rely on key strengthening provided by PBKDF2.

Furthermore, you are requesting 32 bytes from PBKDF2. As the output of a single run of the inner loop of PBKDF2 only produces 20 bytes output (SHA-1 creates 160 bit hashes) that loop is run twice, once for the initial 20 bytes, then again for the 12 bytes that are left. If the attacker only requires the initial 16 bytes to validate the passphrase, then you have twice the work of the attacker. If you just use it as a password hash then just ask for 20 bytes output. If you require 32 bytes for key or IV, then use a KBKDF over the output of the PBKDF. Or, if you want a shortcut, perform SHA-256 over the output.

Code for that last part below:

/**
 * Same security, twice the speed.
 */
public static String generateStorngPasswordHashWithSHA256(String password) {
    try {
        char[] chars = password.toCharArray();
        byte[] salt = getSalt();

        PBEKeySpec spec = new PBEKeySpec(chars, salt, 1010101,
                20 * Byte.SIZE);
        SecretKeyFactory skf = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        byte[] hash = skf.generateSecret(spec).getEncoded();

        MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
        hash = sha256.digest();

        return toHex(salt) + ":" + toHex(hash);
    } catch (Exception e) {
        System.out.println("Exception: Error in generating password"
                + e.toString());
    }
    return "";
}
like image 52
Maarten Bodewes Avatar answered Oct 03 '22 12:10

Maarten Bodewes