Skip to content

Try to remove sensitive parts from memory more aggressively - #123

Open
kwin wants to merge 1 commit into
codehaus-plexus:masterfrom
kwin:feature/try-to-dispose-key-asap
Open

Try to remove sensitive parts from memory more aggressively#123
kwin wants to merge 1 commit into
codehaus-plexus:masterfrom
kwin:feature/try-to-dispose-key-asap

Conversation

@kwin

@kwin kwin commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Call SecretKey.destroy() and PBEKeySpec.clearPassword() to overwrite memory locations with 0 instead of just waiting for GC. Unfortunately right now not well supported by Java (https://bugs.openjdk.org/browse/JDK-8389121).

@kwin
kwin requested a review from cstamas July 29, 2026 12:03
Call SecretKey.destroy() and PBEKeySpec.clearPassword() to overwrite
memory locations with 0 instead of just waiting for GC.
Unfortunately right now not well supported by Java
(https://bugs.openjdk.org/browse/JDK-8389121).
@kwin
kwin force-pushed the feature/try-to-dispose-key-asap branch from efd1d76 to 1ca998a Compare July 29, 2026 12:03
@kwin
kwin requested a review from Copilot July 29, 2026 12:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to more aggressively reduce the lifetime of sensitive key material in memory during AES-GCM encryption/decryption by explicitly clearing password-derived key data instead of relying solely on garbage collection.

Changes:

  • Clears PBEKeySpec password material via clearPassword() after key derivation.
  • Attempts to destroy derived SecretKey instances via a new destroyQuietly(...) helper.
  • Destroys encryption/decryption keys after doFinal(...).
Comments suppressed due to low confidence (2)

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/cipher/AESGCMNoPadding.java:91

  • secretKey is only destroyed on the happy path. If decoding, key derivation, init(...), or doFinal(...) throws, the key won't be destroyed. Wrap the method body so destroyQuietly(secretKey) always runs in finally.
            SecretKey secretKey = getAESKeyFromPassword(password.toCharArray(), salt);
            Cipher cipher = Cipher.getInstance(CIPHER_ALG);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
            byte[] plainText = cipher.doFinal(cipherText);
            destroyQuietly(secretKey);
            return new String(plainText, StandardCharsets.UTF_8);

src/main/java/org/codehaus/plexus/components/secdispatcher/internal/cipher/AESGCMNoPadding.java:110

  • spec.clearPassword() and destroyQuietly(originalKey) should run even if generateSecret(...) or getEncoded() throws. Using try/finally here ensures password/key material is cleared on both success and failure paths.
        PBEKeySpec spec = new PBEKeySpec(password, salt, PBE_ITERATIONS, PBE_KEY_SIZE);
        SecretKey originalKey = factory.generateSecret(spec);
        spec.clearPassword();
        SecretKey derivedKey = new SecretKeySpec(originalKey.getEncoded(), KEY_ALGORITHM);
        destroyQuietly(originalKey);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +114 to 121
private static void destroyQuietly(SecretKey key) {
try {
key.destroy();
} catch (DestroyFailedException e) {
// Ignore exception during key destruction as not all SecretKey implementations support destruction
// https://bugs.openjdk.org/browse/JDK-8389121
}
}
Comment on lines 59 to 64
SecretKey secretKey = getAESKeyFromPassword(password.toCharArray(), salt);
Cipher cipher = Cipher.getInstance(CIPHER_ALG);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
byte[] cipherText = cipher.doFinal(clearText.getBytes(StandardCharsets.UTF_8));
destroyQuietly(secretKey);
byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length)
@slachiewicz slachiewicz added the enhancement New feature or request label Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants