diff --git a/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java index 1f2e1b244e913..838fbd20e44a6 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/encryption/keystore/KeystoreEncryptionSpi.java @@ -151,7 +151,8 @@ public class KeystoreEncryptionSpi extends IgniteSpiAdapter implements Encryptio @Override public void spiStop() throws IgniteSpiException { ensureStarted(); - //empty. + aesWithPadding.remove(); + aesWithoutPadding.remove(); } /** {@inheritDoc} */ @@ -188,12 +189,26 @@ public class KeystoreEncryptionSpi extends IgniteSpiAdapter implements Encryptio /** {@inheritDoc} */ @Override public void encrypt(ByteBuffer data, Serializable key, ByteBuffer res) { - doEncryption(data, aesWithPadding.get(), key, res); + Cipher cipher = aesWithPadding.get(); + + try { + doEncryption(data, cipher, key, res); + } + finally { + aesWithPadding.remove(); + } } /** {@inheritDoc} */ @Override public void encryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res) { - doEncryption(data, aesWithoutPadding.get(), key, res); + Cipher cipher = aesWithoutPadding.get(); + + try { + doEncryption(data, cipher, key, res); + } + finally { + aesWithoutPadding.remove(); + } } /** {@inheritDoc} */ @@ -202,11 +217,11 @@ public class KeystoreEncryptionSpi extends IgniteSpiAdapter implements Encryptio ensureStarted(); + Cipher cipher = aesWithPadding.get(); + try { SecretKeySpec keySpec = new SecretKeySpec(((KeystoreEncryptionKey)key).key().getEncoded(), CIPHER_ALGO); - Cipher cipher = aesWithPadding.get(); - cipher.init(DECRYPT_MODE, keySpec, new IvParameterSpec(data, 0, cipher.getBlockSize())); return cipher.doFinal(data, cipher.getBlockSize(), data.length - cipher.getBlockSize()); @@ -215,16 +230,33 @@ public class KeystoreEncryptionSpi extends IgniteSpiAdapter implements Encryptio BadPaddingException e) { throw new IgniteSpiException(e); } + finally { + aesWithPadding.remove(); + } } /** {@inheritDoc} */ @Override public void decrypt(ByteBuffer data, Serializable key, ByteBuffer res) { - doDecryption(data, aesWithPadding.get(), key, res); + Cipher cipher = aesWithPadding.get(); + + try { + doDecryption(data, cipher, key, res); + } + finally { + aesWithPadding.remove(); + } } /** {@inheritDoc} */ @Override public void decryptNoPadding(ByteBuffer data, Serializable key, ByteBuffer res) { - doDecryption(data, aesWithoutPadding.get(), key, res); + Cipher cipher = aesWithoutPadding.get(); + + try { + doDecryption(data, cipher, key, res); + } + finally { + aesWithoutPadding.remove(); + } } /** diff --git a/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java index a3313a603e3d9..223d86af51c95 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java @@ -17,7 +17,10 @@ package org.apache.ignite.spi.encryption; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.nio.ByteBuffer; +import javax.crypto.Cipher; import java.util.Arrays; import org.apache.ignite.IgniteException; import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey; @@ -33,10 +36,64 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; /** */ public class KeystoreEncryptionSpiSelfTest { + + /** */ + @Test + public void testCipherThreadLocalsRemovedAfterUse() throws Exception { + KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi(); + + encSpi.setKeyStorePath(KEYSTORE_PATH); + encSpi.setKeyStorePassword(KEYSTORE_PASSWORD.toCharArray()); + + GridTestUtils.invoke(encSpi, "onBeforeStart"); + + encSpi.spiStart("default"); + + KeystoreEncryptionKey k = (KeystoreEncryptionKey)encSpi.create(); + + byte[] plainText = "ThreadLocal cleanup test".getBytes(UTF_8); + byte[] cipherText = new byte[encSpi.encryptedSize(plainText.length)]; + + ThreadLocal aesWithPadding = cipherThreadLocal("aesWithPadding"); + + Cipher paddingCipherBeforeEncrypt = aesWithPadding.get(); + + encSpi.encrypt(ByteBuffer.wrap(plainText), k, ByteBuffer.wrap(cipherText)); + + assertNotSame(paddingCipherBeforeEncrypt, aesWithPadding.get()); + + Cipher paddingCipherBeforeDecrypt = aesWithPadding.get(); + + encSpi.decrypt(cipherText, k); + + assertNotSame(paddingCipherBeforeDecrypt, aesWithPadding.get()); + + ThreadLocal aesWithoutPadding = cipherThreadLocal("aesWithoutPadding"); + + Cipher noPaddingCipherBeforeStop = aesWithoutPadding.get(); + + encSpi.spiStop(); + + assertNotSame(noPaddingCipherBeforeStop, aesWithoutPadding.get()); + } + + /** */ + @SuppressWarnings("unchecked") + private static ThreadLocal cipherThreadLocal(String fldName) throws Exception { + Field fld = KeystoreEncryptionSpi.class.getDeclaredField(fldName); + + assertTrue(Modifier.isStatic(fld.getModifiers())); + + fld.setAccessible(true); + + return (ThreadLocal)fld.get(null); + } + /** @throws Exception If failed. */ @Test public void testCantStartWithEmptyParam() throws Exception {