0

Have to implement the openssl function - PKCS5_PBKDF2_HMAC_SHA1(keyData, 8, salt, 8, iterCount, KEY_SIZE, key)) in Java.

Below is my code in Java

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(customerId.toCharArray(), RefundUtil.getSalt(), iterationCount, bitLength);
SecretKey tmp = factory.generateSecret(spec);
byte[] pbkdf2Key = tmp.getEncoded();

Is the above Java code correct?

stack123
  • 37
  • 1
  • 10
  • 1
    You can alternatively verify your code online, e.g. [here](https://asecuritysite.com/encryption/PBKDF2z). Apart from different names there are only minor differences: (1) `RefundUtil.getSalt()` and `pbkdf2Key` are byte arrays whereas on the Web-Site both are hexadecimal strings. However, the conversion from a byte array to a hexadecimal string is simple, e.g. [`bytesToHex`](https://stackoverflow.com/a/9855338/9014097). (2) The key length on the Web-site is given in bytes, in your snippet in bits. That's it. There are further web sites for verification e.g. [here](https://8gwifi.org/pbkdf.jsp). – Topaco Nov 26 '19 at 19:12
  • I cross-checked the derived key with the website output and its correct. Thanks for the direction :) – stack123 Nov 27 '19 at 09:40

1 Answers1

1

This is usually how I implement PBKDF2_HMAC_SHA1:

private static byte[] getSalt(int saltSize){
        SecureRandom secureRandom = new SecureRandom();
        byte[] salt = new byte[saltSize];
        secureRandom.nextBytes(salt);
        this.MC = salt;
        return salt;
    }

    public static byte[] hashPassword(char[] password, int saltSize) throws NoSuchAlgorithmException, InvalidKeySpecException{
        byte[] salt = getSalt(saltSize);

        PBEKeySpec pbeKeySpec = new PBEKeySpec(password,salt,iterations,hashBites);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        return keyFactory.generateSecret(pbeKeySpec).getEncoded();
    }  

Your implementation is going to work just fine

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Shankha057
  • 1,296
  • 1
  • 20
  • 38
  • I could not find any major difference in my code and this one except that you've used PBKDF2WithHmacSHA512 whereas I used PBKDF2WithHmacSHA1 – stack123 Nov 26 '19 at 10:36
  • @stack123 yes, there is not much of a difference and you can use the algorithm that has been proposed. In a nutshell, you are doing fine. I addition to your implementation, I have provided salting implementation as well. – Shankha057 Nov 26 '19 at 10:40
  • 1
    Okay, I had done salting, just that I didn't add it in the question. Thanks for the validation. – stack123 Nov 26 '19 at 10:52
  • @stack123 I have used this approach in a project which is in production and it works well. But honestly, if you're hashing passwords for persistence, then you would better off by using [Argon2](https://en.wikipedia.org/wiki/Argon2) or [BCrypt](https://en.wikipedia.org/wiki/Bcrypt) – Shankha057 Nov 26 '19 at 10:56
  • I am trying to replicate the implementation done in C++. So have to go by how it's done in C. You could check my earlier [question](https://codereview.stackexchange.com/a/232873?noredirect=1) in case you'd like to know more – stack123 Nov 26 '19 at 11:10
  • The reason that the password is a char array is that it is possible to clear a char array, while strings are commonly interned and remain in memory. Having a function that requires a string is therefore not a good idea. – Maarten Bodewes Nov 27 '19 at 18:02
  • @MaartenBodewes what you are saying is true but in actuality this only lowers the window an attacker has. But then again, for doing that don't you think that if an attacker was able to get passwords by performing core dumps, don't you think there would be other ways to get the password? – Shankha057 Nov 27 '19 at 21:23
  • @MaartenBodewes Also consider the case where the passwords is sent over by a web-client in the form of a `String`, the `Servlet` container and/or the JSON deserializer internally uses them as `String`. How would you handle this case? You eventually have at some point of time in the application that the password will be in `String` format. If you can prevent that, then please suggest ways to do it. – Shankha057 Nov 27 '19 at 21:27
  • 1
    These are all good arguments, but core dumps *are* dangerous and having a generic `hashPassword` function that takes a string removes the security that *could* be provided. Anyway, edited and problem removed. – Maarten Bodewes Nov 27 '19 at 21:37
  • @MaartenBodewes but how likely can an attacker hijack the JVM and get core dumps? And if so, then isn't leaking non-GC'd `String` passwords getting leaked are as big an issue compared to the bigger picture? – Shankha057 Nov 27 '19 at 21:49
  • We can go into *in depth* defense strategies, but that may take a while. And for each in depth defense that is not strictly / logically required you can post a well argued "but" :) – Maarten Bodewes Nov 27 '19 at 21:56
  • 1
    Bring out a security critical application on a platform that cannot receive updates for the next 10 years and see how you sleep after that. In depth defense then makes you sleep better, trust me on that :) – Maarten Bodewes Nov 27 '19 at 22:29