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)
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();