11

I'm working on a Java authentication subsystem that specs the storage of passwords in the DB as PBKDF2-generated hashes, and I'm now trying to decide whether I should use SHA1 or SHA512 as PFR. I'm under the impression that the consensus is that SHA1 has some theoretical weaknesses, and that SHA512 should be chosen instead. However the standard javax.crypto package does not offer a PBKDF2WithHmacSHA512 implementation, how is that so?

For reference purposes, here’s my code:

private static final int HASH_BYTE_SIZE = 64; // 512 bits
private static final int PBKDF2_ITERATIONS = 1000;      

// generate random salt
SecureRandom random = new SecureRandom();
byte salt[] = new byte[SALT_BYTE_SIZE]; // use salt size at least as long as hash
random.nextBytes(salt);

// generate Hash
PBEKeySpec spec = new PBEKeySpec(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); // this throws a NoSuchAlgorithmException if I replace with "PBKDF2WithHmacSHA512"
byte[] hash = skf.generateSecret(spec).getEncoded();

// convert hash and salt to hex and store in DB as CHAR(64)...
Mike Edward Moras
  • 18,161
  • 12
  • 87
  • 240
Jim
  • 111
  • 1
  • 1
  • 3

3 Answers3

9

Hash algorithm strength is important, but it is not so important in key derivation functions. It is unlikely that even if SHA-1 is broken that it would influence the security of PBKDF2. You are better off using SHA-1, and increase the iteration count up to a level that is tweaked for your specific configuration.

If you must, you could use Bouncy Castle to create an implementation of PBKDF2 with SHA-256. The internal security of the algorithm is not that important, if your server is relatively safe against side channel attacks (and for PBKDF2 it likely is). So using a non-certified open source solution would probably not compromise your security.

Your efforts are probably better spend elsewhere. Congratulate yourself on choosing a relatively good password based KDF, choose a 64 bit random salt and use a higher iteration count, and move on...


Note: if you want to protect against hardware accelerated attacks, you may want to consider scrypt instead of PBKDF2.


The Oracle JDK 1.8 contains PBKDF2 implementations for SHA-512 "PBKDF2WithHmacSHA512". This can be used for compatibility with other systems or for deprecating SHA-1 entirely.

Maarten Bodewes
  • 96,351
  • 14
  • 169
  • 323
1

Short answer: You can use SHA1 in this situation. Rather than using PBKDF2, you should consider using SCrypt or some other time-memory algorithm. You need to up your iteration count to something like 10,000,000: think Moore's law increase since 1000 was published in the spec in the late 1990s.

Long answer: The attacks against SHA1 are for collision resistance, and not for preimage or 2nd preimage resistance. See https://stackoverflow.com/questions/8860512/whats-the-difference-between-collision-resistance-and-preimage-resistance for what this means. For PBKDF2, the type of resistance which is important is the preimage and 2nd preimage resistance.

SHA1 provides 160 bits of security strength when used for preimage and 2nd preimage resistance. 160 bits of security strength is quite fine to use now and in the medium term. See http://www.keylength.com/ for thoughts on how long a certain key size / security strength can be used for.

Peter
  • 11
  • 1
-1

...the standard javax.crypto package does not offer a PBKDF2WithHmacSHA512 implementation, how is that so?

Starting with Java8, there is support for PBKDF2With<prf> where <prf> can be any number pseudo-random functions, including HmacSHA512.

So it is now supported.

Any thoughts?

What the others have said is good advice. If for some reason you really wanted to use PBKDF2 with HmacSHA512 in standard java, you can if you switch to Java8.

mikeazo
  • 39,117
  • 9
  • 118
  • 183