4

I was experimenting with key derivation functions and I noticed that the secret keys I generate via all the PBE algorithms encode to the plain text password.

With that I mean that:

public class Main {
    public static void main(String[] args) throws Exception {
        byte[] salt = new byte[256/8];
        SecureRandom.getInstanceStrong().nextBytes(salt);
        KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, /*iterations*/ 1000, /*key length*/ 1024);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithHMACSHA512AndAES_256"); // PBE with HMAC SHA512 and AES_256
        SecretKey secret = factory.generateSecret(spec);
        System.out.println(new String(secret.getEncoded()));
    }
}

prints password where I expected 1024 seemingly-random bytes. This doesn't quite add up for me.. can you explain it?

BTW: Note the same code does seem to work as I expect with PBKDF2 algorithms.

PS: In case it matters, I'm using vanilla OpenJDK 13 on mac (13.0.1.hs-adpt)

giorgiga
  • 1,758
  • 12
  • 29
  • What provider are you using, BouncyCastle?. if BC then you would typically use SecretKeyFactory.getInstance("algo", "provider"), possibly your issue is provider dependent – Nigel Savage Nov 26 '19 at 20:07
  • @NigelSavage thanks for chiming in – I'm using vanilla openjdk 13 (13.0.1.hs-adpt) on mac – giorgiga Nov 27 '19 at 18:12
  • I think you may have found a bug, everything checks out for your code, the "PBEWithHMACSHA512AndAES_256" is provided by the SunJCE provider, I can reproduce your issue on openjdk11, to the best of my understanding the code should work – Nigel Savage Nov 27 '19 at 20:17
  • Is PBE the same as PBKDF2? I thought it actually uses the key you provide and not derived secret, nothing about key derivation hints in it's name. – Pavlus Nov 29 '19 at 21:27
  • IDK for sure, but I think the PBE algorithms are generalizations of the encryption schemes from PKCS #5 (see rfc8018).Maybe the point I don't get is why the contructor for `PBEKeySpec` takes salt, iterations and desired key length if they are ignored. – giorgiga Nov 30 '19 at 19:18

1 Answers1

2

Encoded doesn't mean encrypted. As per Key class javadoc getEncoded() method returns a representation of the key:

 * This is an external encoded form for the key used when a standard
 * representation of the key is needed outside the Java Virtual Machine,
 * as when transmitting the key to some other party. The key
 * is encoded according to a standard format (such as
 * X.509 {@code SubjectPublicKeyInfo} or PKCS#8), and
 * is returned using the {@link #getEncoded() getEncoded} method.

Since PBEWithHMACSHA512AndAES_256 is a symmetric algorithm the observed behavior makes sense. The same key is used to perform both encryption and decryption, it can't be modified.

Taking a look at How do I properly use the “PBEWithHmacSHA512AndAES_256” algorithm? question. You need to encrypt the input, below byte[] messageBytes, with correct Cipher instance:

Cipher cipherEncrypt = Cipher.getInstance("PBEWithHMACSHA512AndAES_256");
cipherEncrypt.init(Cipher.ENCRYPT_MODE, key);

byte[] cipherBytes = cipherEncrypt.doFinal(messageBytes);
byte[] iv = cipherEncrypt.getIV();
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111