PBKDF2KeyImpl should offer a way to clear plaintext password from memory

Sebastian Boschert sebastian at 2007.org
Sun May 24 14:38:18 UTC 2015


Hello,

I am currently working on a project that uses JDK's crypto libs to encrypt passwords using PBKDF2. During development I noticed that the PBKDF2KeyImpl class (which implements the SecretKey interface) retains a copy of the plaintext password char[] array. It seems to be impossible to clear the plaintext password after use. In my opinion, this is a security issue as an attacker could easily retrieve plaintext passwords that have not yet been garbage-collected, e.g. by analyzing a heap dump.

I would have expected PBKDF2KeyImpl's destroy() method to overwrite the passwd char[], but instead PBKDF2KeyImpl does not override the default implementation from the Destroyable interface. This results in DestroyFailedExceptions being thrown whenever the destroy() method is called.

In my opinion, JDK should probably include a way to clear the plaintext password. My suggestion would be to just provide an implementation of destroy(). This has the advantage of not having to add any new API. However, PBKDF2KeyImpl's getPassword() method would probably stop working as expected.

I am new to JDK development (in fact this e-mail is my first involvement in it), but I have been using Java and the JDK for well over a decade. Therefore, I'd be happy to help in finding a solution and to offer my time in helping to implement it. Since I'm sure there's some process involved, I could probably use some guidance on how I could contribute to this issue.

Here's the code that I currently have that made me aware of the issue. When debugging this code, it's obvious that secretKey's passwd field still contains the plaintext password, even after the DestroyFailedException is thrown.

--------------------------------------------------------------------
SecretKeyFactory secretKeyFactory =
    SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec spec = null;
SecretKey secretKey = null;

try {
    spec = new PBEKeySpec(plaintext, salt, iterations, keySizeBits);
    secretKey = secretKeyFactory.generateSecret(spec);
    return secretKey.getEncoded();
} catch (InvalidKeySpecException e) {
    throw new Error("Could not create valid key spec.", e);
} finally {
    // Destroy the secret key because it might still contain the
    // plaintext password.
    if (secretKey != null && !secretKey.isDestroyed()) {
        try {
            secretKey.destroy();
        } catch (DestroyFailedException e) {
            throw new Error("Could not destroy secret key after use.", e);
        }
    }

    // Clear the password from the key spec.
    if (spec != null) {
        spec.clearPassword();
    }
}
--------------------------------------------------------------------

Kind regards,
Sebastian Boschert


More information about the security-dev mailing list