ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nizhi...@apache.org
Subject [2/6] ignite git commit: IGNITE-8485: TDE implementation. - Fixes #4167.
Date Fri, 05 Oct 2018 10:03:45 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..dd3b164
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/encryption/KeystoreEncryptionSpiSelfTest.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.spi.encryption;
+
+import java.nio.ByteBuffer;
+import junit.framework.TestCase;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.NotNull;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.ignite.internal.encryption.AbstractEncryptionTest.KEYSTORE_PASSWORD;
+import static org.apache.ignite.internal.encryption.AbstractEncryptionTest.KEYSTORE_PATH;
+
+/** */
+public class KeystoreEncryptionSpiSelfTest extends TestCase {
+    /** @throws Exception If failed. */
+    public void testCantStartWithEmptyParam() throws Exception {
+        GridTestUtils.assertThrowsWithCause(() -> {
+            EncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+            encSpi.spiStart("default");
+        }, IgniteException.class);
+    }
+
+    /** @throws Exception If failed. */
+    public void testCantStartWithoutPassword() throws Exception {
+        GridTestUtils.assertThrowsWithCause(() -> {
+            KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+            encSpi.setKeyStorePath("/ignite/is/cool/path/doesnt/exists");
+
+            encSpi.spiStart("default");
+        }, IgniteException.class);
+    }
+
+    /** @throws Exception If failed. */
+    public void testCantStartKeystoreDoesntExists() throws Exception {
+        GridTestUtils.assertThrowsWithCause(() -> {
+            KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+            encSpi.setKeyStorePath("/ignite/is/cool/path/doesnt/exists");
+            encSpi.setKeyStorePassword(KEYSTORE_PASSWORD.toCharArray());
+
+            encSpi.spiStart("default");
+        }, IgniteException.class);
+    }
+
+    /** @throws Exception If failed. */
+    public void testEncryptDecrypt() throws Exception {
+        EncryptionSpi encSpi = spi();
+
+        KeystoreEncryptionKey k = GridTestUtils.getFieldValue(encSpi, "masterKey");
+        
+        assertNotNull(k);
+        assertNotNull(k.key());
+
+        byte[] plainText = "Just a test string to encrypt!".getBytes(UTF_8);
+        byte[] cipherText = new byte[spi().encryptedSize(plainText.length)];
+
+        encSpi.encrypt(ByteBuffer.wrap(plainText), k, ByteBuffer.wrap(cipherText));
+
+        assertNotNull(cipherText);
+        assertEquals(encSpi.encryptedSize(plainText.length), cipherText.length);
+        
+        byte[] decryptedText = encSpi.decrypt(cipherText, k);
+
+        assertNotNull(decryptedText);
+        assertEquals(plainText.length, decryptedText.length);
+
+        assertEquals(new String(plainText, UTF_8), new String(decryptedText, UTF_8));
+    }
+
+    /** @throws Exception If failed. */
+    public void testKeyEncryptDecrypt() throws Exception {
+        EncryptionSpi encSpi = spi();
+        
+        KeystoreEncryptionKey k = (KeystoreEncryptionKey)encSpi.create();
+
+        assertNotNull(k);
+        assertNotNull(k.key());
+
+        byte[] encGrpKey = encSpi.encryptKey(k);
+
+        assertNotNull(encGrpKey);
+        assertTrue(encGrpKey.length > 0);
+
+        KeystoreEncryptionKey k2 = (KeystoreEncryptionKey)encSpi.decryptKey(encGrpKey);
+
+        assertEquals(k.key(), k2.key());
+    }
+
+    /** */
+    @NotNull private EncryptionSpi spi() throws Exception {
+        KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
+
+        encSpi.setKeyStorePath(KEYSTORE_PATH);
+        encSpi.setKeyStorePassword(KEYSTORE_PASSWORD.toCharArray());
+
+        GridTestUtils.invoke(encSpi, "onBeforeStart");
+
+        encSpi.spiStart("default");
+
+        return encSpi;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
index caa292b..73293ce 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
@@ -1555,51 +1555,58 @@ public final class GridTestUtils {
      */
     @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
     @Nullable public static <T> T invoke(Object obj, String mtd, Object... params) throws Exception {
-        // We cannot resolve method by parameter classes due to some of parameters can be null.
-        // Search correct method among all methods collection.
-        for (Method m : obj.getClass().getDeclaredMethods()) {
-            // Filter methods by name.
-            if (!m.getName().equals(mtd))
-                continue;
-
-            if (!areCompatible(params, m.getParameterTypes()))
-                continue;
-
-            try {
-                synchronized (m) {
-                    // Backup accessible field state.
-                    boolean accessible = m.isAccessible();
+        Class<?> cls = obj.getClass();
+        
+        do {
+            // We cannot resolve method by parameter classes due to some of parameters can be null.
+            // Search correct method among all methods collection.
+            for (Method m : cls.getDeclaredMethods()) {
+                // Filter methods by name.
+                if (!m.getName().equals(mtd))
+                    continue;
 
-                    try {
-                        if (!accessible)
-                            m.setAccessible(true);
+                if (!areCompatible(params, m.getParameterTypes()))
+                    continue;
 
-                        return (T)m.invoke(obj, params);
-                    }
-                    finally {
-                        // Recover accessible field state.
-                        if (!accessible)
-                            m.setAccessible(false);
+                try {
+                    synchronized (m) {
+                        // Backup accessible field state.
+                        boolean accessible = m.isAccessible();
+
+                        try {
+                            if (!accessible)
+                                m.setAccessible(true);
+
+                            return (T)m.invoke(obj, params);
+                        }
+                        finally {
+                            // Recover accessible field state.
+                            if (!accessible)
+                                m.setAccessible(false);
+                        }
                     }
                 }
-            }
-            catch (IllegalAccessException e) {
-                throw new RuntimeException("Failed to access method" +
-                    " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
-            }
-            catch (InvocationTargetException e) {
-                Throwable cause = e.getCause();
+                catch (IllegalAccessException e) {
+                    throw new RuntimeException("Failed to access method" +
+                        " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
+                }
+                catch (InvocationTargetException e) {
+                    Throwable cause = e.getCause();
 
-                if (cause instanceof Error)
-                    throw (Error) cause;
+                    if (cause instanceof Error)
+                        throw (Error) cause;
 
-                if (cause instanceof Exception)
-                    throw (Exception) cause;
+                    if (cause instanceof Exception)
+                        throw (Exception) cause;
 
-                throw new RuntimeException("Failed to invoke method)" +
-                    " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
+                    throw new RuntimeException("Failed to invoke method)" +
+                        " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']', e);
+                }
             }
-        }
+
+            cls = cls.getSuperclass();
+        } while (cls != Object.class);
+
 
         throw new RuntimeException("Failed to find method" +
             " [obj=" + obj + ", mtd=" + mtd + ", params=" + Arrays.toString(params) + ']');

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
index ee0dfa4..13387de 100755
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
@@ -839,8 +839,8 @@ public abstract class GridAbstractTest extends TestCase {
      * @return Started grid.
      * @throws Exception If failed.
      */
-    protected Ignite startGrid(String igniteInstanceName) throws Exception {
-        return startGrid(igniteInstanceName, (GridSpringResourceContext)null);
+    protected IgniteEx startGrid(String igniteInstanceName) throws Exception {
+        return (IgniteEx)startGrid(igniteInstanceName, (GridSpringResourceContext)null);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
index 7ce6209..e7876f8 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
@@ -22,6 +22,13 @@ import junit.framework.TestSuite;
 import org.apache.ignite.failure.IoomFailureHandlerTest;
 import org.apache.ignite.failure.SystemWorkersTerminationTest;
 import org.apache.ignite.internal.ClusterBaselineNodesMetricsSelfTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheBigEntryTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheCreateTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheDestroyTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheGroupCreateTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheNodeJoinTest;
+import org.apache.ignite.internal.encryption.EncryptedCachePreconfiguredRestartTest;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
 import org.apache.ignite.internal.GridNodeMetricsLogPdsSelfTest;
 import org.apache.ignite.internal.processors.service.ServiceDeploymentOnActivationTest;
 import org.apache.ignite.internal.processors.service.ServiceDeploymentOutsideBaselineTest;
@@ -62,6 +69,14 @@ public class IgniteBasicWithPersistenceTestSuite extends TestSuite {
 
         suite.addTestSuite(GridNodeMetricsLogPdsSelfTest.class);
 
+        suite.addTestSuite(EncryptedCacheBigEntryTest.class);
+        suite.addTestSuite(EncryptedCacheCreateTest.class);
+        suite.addTestSuite(EncryptedCacheDestroyTest.class);
+        suite.addTestSuite(EncryptedCacheGroupCreateTest.class);
+        suite.addTestSuite(EncryptedCacheNodeJoinTest.class);
+        suite.addTestSuite(EncryptedCacheRestartTest.class);
+        suite.addTestSuite(EncryptedCachePreconfiguredRestartTest.class);
+
         return suite;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
index b8ea850..ab2306e 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteKernalSelfTestSuite.java
@@ -53,7 +53,6 @@ import org.apache.ignite.internal.processors.port.GridPortProcessorSelfTest;
 import org.apache.ignite.internal.processors.service.GridServiceClientNodeTest;
 import org.apache.ignite.internal.processors.service.GridServiceContinuousQueryRedeployTest;
 import org.apache.ignite.internal.processors.service.GridServiceDeploymentCompoundFutureSelfTest;
-import org.apache.ignite.internal.processors.service.GridServiceDeploymentExceptionPropagationTest;
 import org.apache.ignite.internal.processors.service.GridServicePackagePrivateSelfTest;
 import org.apache.ignite.internal.processors.service.GridServiceProcessorBatchDeploySelfTest;
 import org.apache.ignite.internal.processors.service.GridServiceProcessorMultiNodeConfigSelfTest;

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
index 5de61ae..d5ded38 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiTestSuite.java
@@ -20,6 +20,7 @@ package org.apache.ignite.testsuites;
 import junit.framework.TestSuite;
 import org.apache.ignite.internal.managers.GridManagerLocalMessageListenerSelfTest;
 import org.apache.ignite.internal.managers.GridNoopManagerSelfTest;
+import org.apache.ignite.spi.encryption.KeystoreEncryptionSpiSelfTest;
 
 /**
  * Grid SPI test suite.
@@ -62,6 +63,8 @@ public class IgniteSpiTestSuite extends TestSuite {
         // Local Message Listener tests.
         suite.addTestSuite(GridManagerLocalMessageListenerSelfTest.class);
 
+        suite.addTestSuite(KeystoreEncryptionSpiSelfTest.class);
+
         return suite;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/resources/other_tde_keystore.jks
----------------------------------------------------------------------
diff --git a/modules/core/src/test/resources/other_tde_keystore.jks b/modules/core/src/test/resources/other_tde_keystore.jks
new file mode 100644
index 0000000..6b1f51b
Binary files /dev/null and b/modules/core/src/test/resources/other_tde_keystore.jks differ

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/core/src/test/resources/tde.jks
----------------------------------------------------------------------
diff --git a/modules/core/src/test/resources/tde.jks b/modules/core/src/test/resources/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/core/src/test/resources/tde.jks differ

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index 8688c4fbd9..5c2865a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -72,7 +72,6 @@ import org.apache.ignite.internal.sql.command.SqlIndexColumn;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.plugin.security.SecurityPermission;
 import org.h2.command.Prepared;
 import org.h2.command.ddl.AlterTableAlterColumn;
@@ -358,7 +357,7 @@ public class DdlStatementsProcessor {
 
                     ctx.query().dynamicTableCreate(cmd.schemaName(), e, cmd.templateName(), cmd.cacheName(),
                         cmd.cacheGroup(), cmd.dataRegionName(), cmd.affinityKey(), cmd.atomicityMode(),
-                        cmd.writeSynchronizationMode(), cmd.backups(), cmd.ifNotExists());
+                        cmd.writeSynchronizationMode(), cmd.backups(), cmd.ifNotExists(), cmd.encrypted());
                 }
             }
             else if (stmt0 instanceof GridSqlDropTable) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
index de86d6a..0da77bb 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java
@@ -84,6 +84,9 @@ public class GridSqlCreateTable extends GridSqlStatement {
     /** Extra WITH-params. */
     private List<String> params;
 
+    /** Encrypted flag. */
+    private boolean encrypted;
+
     /**
      * @return Cache name upon which new cache configuration for this table must be based.
      */
@@ -336,6 +339,20 @@ public class GridSqlCreateTable extends GridSqlStatement {
         this.params = params;
     }
 
+    /**
+     * @return Encrypted flag.
+     */
+    public boolean encrypted() {
+        return encrypted;
+    }
+
+    /**
+     * @param encrypted Encrypted flag.
+     */
+    public void encrypted(boolean encrypted) {
+        this.encrypted = encrypted;
+    }
+
     /** {@inheritDoc} */
     @Override public String getSQL() {
         return null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index a653e7f..856951f 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -514,6 +514,9 @@ public class GridSqlQueryParser {
     public static final String PARAM_DATA_REGION = "DATA_REGION";
 
     /** */
+    private static final String PARAM_ENCRYPTED = "ENCRYPTED";
+
+    /** */
     private final IdentityHashMap<Object, Object> h2ObjToGridObj = new IdentityHashMap<>();
 
     /** */
@@ -1610,6 +1613,11 @@ public class GridSqlQueryParser {
 
                 break;
 
+            case PARAM_ENCRYPTED:
+                res.encrypted(F.isEmpty(val) || Boolean.parseBoolean(val));
+
+                break;
+
             default:
                 throw new IgniteSQLException("Unsupported parameter: " + name, IgniteQueryErrorCode.PARSING);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java
new file mode 100644
index 0000000..4e0e3c3
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/encryption/EncryptedSqlTableTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.encryption;
+
+import java.util.List;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/** */
+public class EncryptedSqlTableTest extends EncryptedCacheRestartTest {
+    /** {@inheritDoc} */
+    @Override protected void createEncryptedCache(IgniteEx grid0, @Nullable IgniteEx grid1, String cacheName,
+        String cacheGroup, boolean putData) {
+
+        executeSql(grid0, "CREATE TABLE encrypted(ID BIGINT, NAME VARCHAR(10), PRIMARY KEY (ID)) " +
+            "WITH \"ENCRYPTED=true\"");
+        executeSql(grid0, "CREATE INDEX enc0 ON encrypted(NAME)");
+
+        if (putData) {
+            for (int i=0; i<100; i++)
+                executeSql(grid0, "INSERT INTO encrypted(ID, NAME) VALUES(?, ?)", i, "" + i);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void checkData(IgniteEx grid0) {
+        for (int i=0; i<100; i++) {
+            List<List<?>> res = executeSql(grid0, "SELECT NAME FROM encrypted WHERE ID = ?", i);
+
+            assertEquals(1, res.size());
+            assertEquals("" + i, res.get(0).get(0));
+        }
+    }
+
+    /** */
+    private List<List<?>> executeSql(IgniteEx grid, String qry, Object...args) {
+        return grid.context().query().querySqlFields(
+            new SqlFieldsQuery(qry).setSchema("PUBLIC").setArgs(args), true).getAll();
+    }
+
+    /** {@inheritDoc} */
+    @NotNull @Override protected String cacheName() {
+        return "SQL_PUBLIC_ENCRYPTED";
+    }
+
+    /** {@inheritDoc} */
+    @Override protected String keystorePath() {
+        return IgniteUtils.resolveIgnitePath("modules/indexing/src/test/resources/tde.jks").getAbsolutePath();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index 6ed914c..c97d934 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -34,7 +34,6 @@ import java.util.Random;
 import java.util.UUID;
 import java.util.concurrent.Callable;
 import javax.cache.CacheException;
-import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.binary.BinaryObject;
@@ -44,7 +43,6 @@ import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
-import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.DataRegionConfiguration;
 import org.apache.ignite.configuration.DataStorageConfiguration;
@@ -881,7 +879,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
                 e.setValueType("City");
 
                 queryProcessor(client()).dynamicTableCreate("PUBLIC", e, CacheMode.PARTITIONED.name(), null, null, null,
-                    null, CacheAtomicityMode.ATOMIC, null, 10, false);
+                    null, CacheAtomicityMode.ATOMIC, null, 10, false, false);
 
                 return null;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index 7c8b2f8..7633d2a 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -104,6 +104,7 @@ import org.apache.ignite.internal.processors.cache.distributed.replicated.Ignite
 import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQueryEvtsDisabledSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQueryP2PDisabledSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQuerySelfTest;
+import org.apache.ignite.internal.processors.cache.encryption.EncryptedSqlTableTest;
 import org.apache.ignite.internal.processors.cache.index.BasicIndexTest;
 import org.apache.ignite.internal.processors.cache.index.DuplicateKeyValueClassesSelfTest;
 import org.apache.ignite.internal.processors.cache.index.DynamicIndexClientBasicSelfTest;
@@ -472,6 +473,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
         // User operation SQL
         suite.addTestSuite(SqlParserUserSelfTest.class);
         suite.addTestSuite(SqlUserCommandSelfTest.class);
+        suite.addTestSuite(EncryptedSqlTableTest.class);
 
         suite.addTestSuite(ThreadLocalObjectPoolSelfTest.class);
         suite.addTestSuite(H2StatementCacheSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/indexing/src/test/resources/tde.jks
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/resources/tde.jks b/modules/indexing/src/test/resources/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/indexing/src/test/resources/tde.jks differ

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.DotNetCore/tde.jks differ

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
index 1fd8e72..71d2ba0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/IgniteConfigurationParityTest.cs
@@ -64,7 +64,8 @@ namespace Apache.Ignite.Core.Tests.ApiParity
             "CacheStoreSessionListenerFactories",
             "PlatformConfiguration",
             "ExecutorConfiguration",
-            "CommunicationFailureResolver"
+            "CommunicationFailureResolver",
+            "EncryptionSpi"
         };
 
         /** Properties that are missing on .NET side. */
@@ -97,4 +98,4 @@ namespace Apache.Ignite.Core.Tests.ApiParity
                 KnownMappings);
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
index 2861c30..354a511 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
@@ -36,6 +36,7 @@ namespace Apache.Ignite.Core.Tests
     using Apache.Ignite.Core.Discovery.Tcp;
     using Apache.Ignite.Core.Discovery.Tcp.Multicast;
     using Apache.Ignite.Core.Discovery.Tcp.Static;
+    using Apache.Ignite.Core.Encryption.Keystore;
     using Apache.Ignite.Core.Events;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.PersistentStore;
@@ -81,6 +82,7 @@ namespace Apache.Ignite.Core.Tests
             CheckDefaultValueAttributes(new IgniteConfiguration());
             CheckDefaultValueAttributes(new BinaryConfiguration());
             CheckDefaultValueAttributes(new TcpDiscoverySpi());
+            CheckDefaultValueAttributes(new KeystoreEncryptionSpi());
             CheckDefaultValueAttributes(new CacheConfiguration());
             CheckDefaultValueAttributes(new TcpDiscoveryMulticastIpFinder());
             CheckDefaultValueAttributes(new TcpCommunicationSpi());
@@ -132,6 +134,14 @@ namespace Apache.Ignite.Core.Tests
                 Assert.AreEqual(disco.ThreadPriority, resDisco.ThreadPriority);
                 Assert.AreEqual(disco.TopologyHistorySize, resDisco.TopologyHistorySize);
 
+                var enc = (KeystoreEncryptionSpi) cfg.EncryptionSpi;
+                var resEnc = (KeystoreEncryptionSpi) resCfg.EncryptionSpi;
+                
+                Assert.AreEqual(enc.MasterKeyName, resEnc.MasterKeyName);
+                Assert.AreEqual(enc.KeySize, resEnc.KeySize);
+                Assert.AreEqual(enc.KeyStorePath, resEnc.KeyStorePath);
+                Assert.AreEqual(enc.KeyStorePassword, resEnc.KeyStorePassword);
+
                 var ip = (TcpDiscoveryStaticIpFinder) disco.IpFinder;
                 var resIp = (TcpDiscoveryStaticIpFinder) resDisco.IpFinder;
 
@@ -684,6 +694,13 @@ namespace Apache.Ignite.Core.Tests
                     ThreadPriority = 6,
                     TopologyHistorySize = 1234567
                 },
+                EncryptionSpi = new KeystoreEncryptionSpi()
+                {
+                    KeySize = 192,
+                    KeyStorePassword = "love_sex_god",
+                    KeyStorePath = "tde.jks",
+                    MasterKeyName = KeystoreEncryptionSpi.DefaultMasterKeyName
+                },
                 IgniteInstanceName = "gridName1",
                 IgniteHome = IgniteHome.Resolve(null),
                 IncludedEventTypes = EventType.DiscoveryAll,

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 57357da..f5897c8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -161,6 +161,10 @@
     <Compile Include="Discovery\Tcp\Multicast\Package-Info.cs" />
     <Compile Include="Discovery\Tcp\Package-Info.cs" />
     <Compile Include="Discovery\Tcp\Static\Package-Info.cs" />
+    <Compile Include="Encryption\Package-Info.cs" />
+    <Compile Include="Encryption\IEncryptionSpi.cs" />
+    <Compile Include="Encryption\Keystore\Package-Info.cs" />
+    <Compile Include="Encryption\Keystore\KeystoreEncryptionSpi.cs" />
     <Compile Include="Impl\Binary\BinaryArrayEqualityComparer.cs" />
     <Compile Include="Impl\Binary\BinaryProcessor.cs" />
     <Compile Include="Impl\Binary\BinaryReflectiveSerializerInternal.cs" />
@@ -600,4 +604,4 @@
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
\ No newline at end of file
+</Project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
index a8925ad..2e0e1a3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
@@ -161,6 +161,9 @@ namespace Apache.Ignite.Core.Cache.Configuration
         /// <summary> Default value for <see cref="QueryParallelism"/>. </summary>
         public const int DefaultQueryParallelism = 1;
 
+        /// <summary> Default value for <see cref="EncryptionEnabled"/>. </summary>
+        public const bool DefaultEncryptionEnabled = false;
+
         /// <summary>
         /// Gets or sets the cache name.
         /// </summary>
@@ -214,6 +217,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
             RebalanceBatchesPrefetchCount = DefaultRebalanceBatchesPrefetchCount;
             MaxQueryIteratorsCount = DefaultMaxQueryIteratorsCount;
             QueryParallelism = DefaultQueryParallelism;
+            EncryptionEnabled = DefaultEncryptionEnabled;
         }
 
         /// <summary>
@@ -329,6 +333,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
             QueryDetailMetricsSize = reader.ReadInt();
             QueryParallelism = reader.ReadInt();
             SqlSchema = reader.ReadString();
+            EncryptionEnabled = reader.ReadBoolean();
 
             QueryEntities = reader.ReadCollectionRaw(r => new QueryEntity(r, srvVer));
 
@@ -427,6 +432,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
             writer.WriteInt(QueryDetailMetricsSize);
             writer.WriteInt(QueryParallelism);
             writer.WriteString(SqlSchema);
+            writer.WriteBoolean(EncryptionEnabled);
 
             writer.WriteCollectionRaw(QueryEntities, srvVer);
 
@@ -919,5 +925,12 @@ namespace Apache.Ignite.Core.Cache.Configuration
         /// </summary>
         [DefaultValue(DefaultQueryParallelism)]
         public int QueryParallelism { get; set; }
+
+        /// <summary>
+        /// Gets or sets encryption flag.
+        /// Default is false.
+        /// </summary>
+        [DefaultValue(DefaultEncryptionEnabled)]
+        public bool EncryptionEnabled { get; set; }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs
new file mode 100644
index 0000000..c0ea475
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/IEncryptionSpi.cs
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Encryption
+{
+    using System.Diagnostics.CodeAnalysis;
+    using Apache.Ignite.Core.Encryption.Keystore;
+
+    /// <summary>
+    /// Encryption SPI.
+    /// <para />
+    /// Only predefined implementations are supported: 
+    /// <see cref="KeystoreEncryptionSpi"/>
+    /// </summary>
+    [SuppressMessage("Microsoft.Design", "CA1040:AvoidEmptyInterfaces")]
+    public interface IEncryptionSpi
+    {
+        // No-op.
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs
new file mode 100644
index 0000000..e1866f8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/KeystoreEncryptionSpi.cs
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Encryption.Keystore
+{
+    using System.ComponentModel;
+    using Apache.Ignite.Core.Binary;
+
+    /// <summary>
+    /// IEncryptionSPI implementation base on JDK provided cipher algorithm implementations.
+    /// </summary>
+    public class KeystoreEncryptionSpi : IEncryptionSpi
+    {
+        /// <summary>
+        /// Default master key name.
+        /// </summary>
+        public const string DefaultMasterKeyName = "ignite.master.key";
+
+        /// <summary>
+        /// Default encryption key size.
+        /// </summary>
+        public const int DefaultKeySize = 256;
+        
+        /// <summary>
+        /// Name of master key in key store.
+        /// </summary>
+        [DefaultValue(DefaultMasterKeyName)]
+        public string MasterKeyName { get; set; }
+        
+        /// <summary>
+        /// Size of encryption key.
+        /// </summary>
+        [DefaultValue(DefaultKeySize)]
+        public int KeySize { get; set; }
+        
+        /// <summary>
+        /// Path to key store.
+        /// </summary>
+        public string KeyStorePath { get; set; }
+
+        /// <summary>
+        /// Key store password.
+        /// </summary>
+        public string KeyStorePassword { get; set; }
+
+        /// <summary>
+        /// Empty constructor.
+        /// </summary>
+        public KeystoreEncryptionSpi()
+        {
+            MasterKeyName = DefaultMasterKeyName;
+            KeySize = DefaultKeySize;
+        }
+        
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeystoreEncryptionSpi"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public KeystoreEncryptionSpi(IBinaryRawReader reader)
+        {
+            MasterKeyName = reader.ReadString();
+            KeySize = reader.ReadInt();
+            KeyStorePath = reader.ReadString();
+
+            var keyStorePassword = reader.ReadCharArray();
+
+            KeyStorePassword = keyStorePassword == null ? null : new string(keyStorePassword);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs
new file mode 100644
index 0000000..8df8b34
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Keystore/Package-Info.cs
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Encryption API based on standart java keystore.
+/// </summary>
+namespace Apache.Ignite.Core.Encryption.Keystore
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs
new file mode 100644
index 0000000..37cafdb
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Encryption/Package-Info.cs
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Encryption API.
+/// </summary>
+namespace Apache.Ignite.Core.Encryption
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index 315b27d..fc6afb6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -39,6 +39,8 @@ namespace Apache.Ignite.Core
     using Apache.Ignite.Core.Deployment;
     using Apache.Ignite.Core.Discovery;
     using Apache.Ignite.Core.Discovery.Tcp;
+    using Apache.Ignite.Core.Encryption;
+    using Apache.Ignite.Core.Encryption.Keystore;
     using Apache.Ignite.Core.Events;
     using Apache.Ignite.Core.Failure;
     using Apache.Ignite.Core.Impl;
@@ -373,6 +375,26 @@ namespace Apache.Ignite.Core
             else
                 writer.WriteBoolean(false);
 
+            var enc = EncryptionSpi;
+
+            if (enc != null)
+            {
+                writer.WriteBoolean(true);
+
+                var keystoreEnc = enc as KeystoreEncryptionSpi;
+                
+                if (keystoreEnc == null)
+                    throw new InvalidOperationException("Unsupported encryption SPI: " + enc.GetType());
+
+                writer.WriteString(keystoreEnc.MasterKeyName);
+                writer.WriteInt(keystoreEnc.KeySize);
+                writer.WriteString(keystoreEnc.KeyStorePath);
+                writer.WriteCharArray(
+                    keystoreEnc.KeyStorePassword == null ? null : keystoreEnc.KeyStorePassword.ToCharArray());
+            }
+            else
+                writer.WriteBoolean(false);
+
             // Communication config
             var comm = CommunicationSpi;
 
@@ -727,6 +749,9 @@ namespace Apache.Ignite.Core
             // Discovery config
             DiscoverySpi = r.ReadBoolean() ? new TcpDiscoverySpi(r) : null;
 
+            EncryptionSpi = (srvVer.CompareTo(ClientSocket.Ver120) >= 0 && r.ReadBoolean()) ? 
+                new KeystoreEncryptionSpi(r) : null;
+
             // Communication config
             CommunicationSpi = r.ReadBoolean() ? new TcpCommunicationSpi(r) : null;
 
@@ -1055,6 +1080,12 @@ namespace Apache.Ignite.Core
         /// Null for default communication.
         /// </summary>
         public ICommunicationSpi CommunicationSpi { get; set; }
+        
+        /// <summary>
+        /// Gets or sets the encryption service provider.
+        /// Null for disabled encryption.
+        /// </summary>
+        public IEncryptionSpi EncryptionSpi { get; set; }
 
         /// <summary>
         /// Gets or sets a value indicating whether node should start in client mode.

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
index 4040610..0a55095 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -862,6 +862,11 @@
                                             <xs:documentation>Desired query parallelism within a single node.</xs:documentation>
                                         </xs:annotation>
                                     </xs:attribute>
+                                    <xs:attribute name="encryptionEnabled" type="xs:boolean">
+                                        <xs:annotation>
+                                            <xs:documentation>Flag indicating whether cache encryption enabled.</xs:documentation>
+                                        </xs:annotation>
+                                    </xs:attribute>
                                 </xs:complexType>
                             </xs:element>
                         </xs:sequence>
@@ -905,6 +910,38 @@
                         </xs:sequence>
                     </xs:complexType>
                 </xs:element>
+                <xs:element name="encryptionSpi" minOccurs="0">
+                    <xs:annotation>
+                        <xs:documentation>Encryption spi. Null for disabled encryption.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attribute name="masterKeyName" type="xs:string">
+                            <xs:annotation>
+                                <xs:documentation>Master key name</xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
+                        <xs:attribute name="keySize" type="xs:int">
+                            <xs:annotation>
+                                <xs:documentation>Encryption key size.</xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
+                        <xs:attribute name="keyStorePath" type="xs:string">
+                            <xs:annotation>
+                                <xs:documentation>Key store path.</xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
+                        <xs:attribute name="keyStorePassword" type="xs:string">
+                            <xs:annotation>
+                                <xs:documentation>Key store password.</xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
+                        <xs:attribute name="type" type="xs:string" use="required">
+                            <xs:annotation>
+                                <xs:documentation>Assembly-qualified type name.</xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
+                    </xs:complexType>
+                </xs:element>
                 <xs:element name="discoverySpi" minOccurs="0">
                     <xs:annotation>
                         <xs:documentation>Discovery service provider. Null for default discovery.</xs:documentation>
@@ -999,7 +1036,7 @@
                         <xs:attribute name="forceServerMode" type="xs:boolean">
                             <xs:annotation>
                                 <xs:documentation>
-                                    Whether TcpDiscoverySpi is started in server mode regardless of IgniteConfiguration.ClientMode setting.
+                                    Whether TcpDiscoveryspi is started in server mode regardless of IgniteConfiguration.ClientMode setting.
                                 </xs:documentation>
                             </xs:annotation>
                         </xs:attribute>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/base-enc-cfg.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/base-enc-cfg.xml b/modules/spring/src/test/config/enc/base-enc-cfg.xml
new file mode 100644
index 0000000..ad17584
--- /dev/null
+++ b/modules/spring/src/test/config/enc/base-enc-cfg.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="peerClassLoadingEnabled" value="true"/>
+        <property name="clientMode" ref="clientMode"/>
+
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="shared" value="false"/>
+                        <property name="addresses">
+                            <list>
+                                <value>127.0.0.1:47500..47509</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+            </bean>
+        </property>
+
+        <property name="dataStorageConfiguration">
+            <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
+                <property name="defaultDataRegionConfiguration">
+                    <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
+                        <property name="maxSize" value="#{10*1024*1024}"/>
+                        <property name="persistenceEnabled" value="true"/>
+                    </bean>
+                </property>
+                <property name="pageSize" value="#{4*1024}"/>
+                <property name="walMode" value="LOG_ONLY"/>
+            </bean>
+        </property>
+
+        <property name="encryptionSpi">
+            <bean class="org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionSpi">
+                <property name="keyStorePath" value="tde.jks"/>
+                <property name="keyStorePassword" value="love_sex_god"/>
+            </bean>
+        </property>
+
+        <property name="cacheConfiguration">
+            <list>
+                <ref bean="cache.cfg" />
+            </list>
+        </property>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-cache-client.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-cache-client.xml b/modules/spring/src/test/config/enc/enc-cache-client.xml
new file mode 100644
index 0000000..ba4068a
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-cache-client.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+        <property name="name" value="encrypted-client"/>
+        <property name="encryptionEnabled" value="true"/>
+    </bean>
+
+    <bean id="clientMode" class="java.lang.Boolean">
+        <constructor-arg value="true"/>
+    </bean>
+
+    <import resource="base-enc-cfg.xml"/>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-cache.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-cache.xml b/modules/spring/src/test/config/enc/enc-cache.xml
new file mode 100644
index 0000000..88b3ed0
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-cache.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+        <property name="name" value="encrypted"/>
+        <property name="encryptionEnabled" value="true"/>
+    </bean>
+
+    <bean id="clientMode" class="java.lang.Boolean">
+        <constructor-arg value="false"/>
+    </bean>
+
+    <import resource="base-enc-cfg.xml"/>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-group-2.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-group-2.xml b/modules/spring/src/test/config/enc/enc-group-2.xml
new file mode 100644
index 0000000..60f7031
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-group-2.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+        <property name="name" value="encrypted-2"/>
+        <property name="encryptionEnabled" value="true"/>
+        <property name="groupName" value="encrypted-group"/>
+    </bean>
+
+    <bean id="clientMode" class="java.lang.Boolean">
+        <constructor-arg value="false"/>
+    </bean>
+
+    <import resource="base-enc-cfg.xml"/>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/enc-group.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/enc-group.xml b/modules/spring/src/test/config/enc/enc-group.xml
new file mode 100644
index 0000000..33d4659
--- /dev/null
+++ b/modules/spring/src/test/config/enc/enc-group.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+        <property name="name" value="encrypted"/>
+        <property name="encryptionEnabled" value="true"/>
+        <property name="groupName" value="encrypted-group"/>
+    </bean>
+
+    <bean id="clientMode" class="java.lang.Boolean">
+        <constructor-arg value="false"/>
+    </bean>
+
+    <import resource="base-enc-cfg.xml"/>
+</beans>
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml b/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml
new file mode 100644
index 0000000..a49ddbd
--- /dev/null
+++ b/modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+        <property name="name" value="encrypted-2"/>
+        <property name="encryptionEnabled" value="false"/>
+        <property name="groupName" value="encrypted-group"/>
+    </bean>
+
+    <bean id="clientMode" class="java.lang.Boolean">
+        <constructor-arg value="false"/>
+    </bean>
+
+    <import resource="base-enc-cfg.xml"/>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/config/enc/not-encrypted-cache.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/config/enc/not-encrypted-cache.xml b/modules/spring/src/test/config/enc/not-encrypted-cache.xml
new file mode 100644
index 0000000..a9478f6
--- /dev/null
+++ b/modules/spring/src/test/config/enc/not-encrypted-cache.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="cache.cfg" class="org.apache.ignite.configuration.CacheConfiguration">
+        <property name="name" value="encrypted"/>
+        <property name="encryptionEnabled" value="false"/>
+    </bean>
+
+    <bean id="clientMode" class="java.lang.Boolean">
+        <constructor-arg value="false"/>
+    </bean>
+
+    <import resource="base-enc-cfg.xml"/>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java
new file mode 100644
index 0000000..fa6de21
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartClientTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.encryption;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgnitionEx;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.internal.util.typedef.T2;
+
+/** */
+public class SpringEncryptedCacheRestartClientTest extends EncryptedCacheRestartTest {
+    /** {@inheritDoc} */
+    @Override protected void createEncryptedCache(IgniteEx grid0, IgniteEx grid1, String cacheName, String cacheGroup) {
+        IgniteCache<Long, String> cache = grid0.cache(cacheName());
+
+        for (long i = 0; i < 100; i++)
+            cache.put(i, "" + i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected T2<IgniteEx, IgniteEx> startTestGrids(boolean clnPersDir) throws Exception {
+        if (clnPersDir)
+            cleanPersistenceDir();
+
+        IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-0");
+
+        IgniteEx g1 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-1");
+
+        IgniteEx client = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-cache-client.xml").getAbsolutePath(), "client");
+
+        g1.cluster().active(true);
+
+        awaitPartitionMapExchange();
+
+        return new T2<>(g1, client);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java
new file mode 100644
index 0000000..6488527
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/encryption/SpringEncryptedCacheRestartTest.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.encryption;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgnitionEx;
+import org.apache.ignite.internal.encryption.EncryptedCacheRestartTest;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.spi.encryption.keystore.KeystoreEncryptionKey;
+
+import static org.apache.ignite.testframework.GridTestUtils.assertThrowsWithCause;
+
+/** */
+public class SpringEncryptedCacheRestartTest extends EncryptedCacheRestartTest {
+    /** {@inheritDoc} */
+    @Override protected void createEncryptedCache(IgniteEx grid0, IgniteEx grid1, String cacheName, String cacheGroup) {
+        IgniteCache<Long, String> cache = grid0.cache(cacheName());
+
+        for (long i = 0; i < 100; i++)
+            cache.put(i, "" + i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected T2<IgniteEx, IgniteEx> startTestGrids(boolean clnPersDir) throws Exception {
+        if (clnPersDir)
+            cleanPersistenceDir();
+
+        IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-0");
+
+        IgniteEx g1 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-cache.xml").getAbsolutePath(), "grid-1");
+
+        g1.cluster().active(true);
+
+        awaitPartitionMapExchange();
+
+        return new T2<>(g0, g1);
+    }
+
+    /** @throws Exception If failed. */
+    public void testEncryptionKeysEqualsOnThirdNodeJoin() throws Exception {
+        T2<IgniteEx, IgniteEx> g = startTestGrids(true);
+
+        IgniteEx g2 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-group-2.xml").getAbsolutePath(), "grid-2");
+
+        Collection<String> cacheNames = Arrays.asList("encrypted", "encrypted-2");
+
+        for (String cacheName : cacheNames) {
+            IgniteInternalCache<Object, Object> enc = g.get1().cachex(cacheName);
+
+            assertNotNull(enc);
+
+            int grpId = CU.cacheGroupId(enc.name(), enc.configuration().getGroupName());
+
+            KeystoreEncryptionKey key0 = (KeystoreEncryptionKey)g.get1().context().encryption().groupKey(grpId);
+            KeystoreEncryptionKey key1 = (KeystoreEncryptionKey)g.get2().context().encryption().groupKey(grpId);
+            KeystoreEncryptionKey key2 = (KeystoreEncryptionKey)g2.context().encryption().groupKey(grpId);
+
+            assertNotNull(cacheName, key0);
+            assertNotNull(cacheName, key1);
+            assertNotNull(cacheName, key2);
+
+            assertNotNull(cacheName, key0.key());
+            assertNotNull(cacheName, key1.key());
+            assertNotNull(cacheName, key2.key());
+
+            assertEquals(cacheName, key0.key(), key1.key());
+            assertEquals(cacheName, key1.key(), key2.key());
+        }
+    }
+
+    /** @throws Exception If failed. */
+    public void testCreateEncryptedCacheGroup() throws Exception {
+        IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-group.xml").getAbsolutePath(), "grid-0");
+
+        IgniteEx g1 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-group-2.xml").getAbsolutePath(), "grid-1");
+
+        g1.cluster().active(true);
+
+        awaitPartitionMapExchange();
+
+        IgniteInternalCache<Object, Object> encrypted = g0.cachex("encrypted");
+
+        assertNotNull(encrypted);
+
+        IgniteInternalCache<Object, Object> encrypted2 = g0.cachex("encrypted-2");
+
+        assertNotNull(encrypted2);
+
+        KeystoreEncryptionKey key = (KeystoreEncryptionKey)g0.context().encryption().groupKey(
+            CU.cacheGroupId(encrypted.name(), encrypted.configuration().getGroupName()));
+
+        assertNotNull(key);
+        assertNotNull(key.key());
+
+        KeystoreEncryptionKey key2 = (KeystoreEncryptionKey)g0.context().encryption().groupKey(
+            CU.cacheGroupId(encrypted2.name(), encrypted2.configuration().getGroupName()));
+
+        assertNotNull(key2);
+        assertNotNull(key2.key());
+
+        assertEquals(key.key(), key2.key());
+    }
+
+    /** @throws Exception If failed. */
+    public void testCreateNotEncryptedCacheInEncryptedGroupFails() throws Exception {
+        IgniteEx g0 = (IgniteEx)IgnitionEx.start(
+            IgniteUtils.resolveIgnitePath(
+                "modules/spring/src/test/config/enc/enc-group.xml").getAbsolutePath(), "grid-0");
+
+        assertThrowsWithCause(() -> {
+            try {
+                IgnitionEx.start(IgniteUtils.resolveIgnitePath(
+                    "modules/spring/src/test/config/enc/not-encrypted-cache-in-group.xml").getAbsolutePath(), "grid-1");
+            }
+            catch (IgniteCheckedException e) {
+                throw new RuntimeException(e);
+            }
+        }, IgniteCheckedException.class);
+    }
+
+    /** @throws Exception If failed. */
+    public void testStartWithEncryptedOnDiskPlainInCfg() throws Exception {
+        doTestDiffCfgAndPersistentFlagVal(
+            "modules/spring/src/test/config/enc/enc-cache.xml",
+            "modules/spring/src/test/config/enc/not-encrypted-cache.xml");
+    }
+
+    /** @throws Exception If failed. */
+    public void testStartWithPlainOnDiskEncryptedInCfg() throws Exception {
+        doTestDiffCfgAndPersistentFlagVal(
+            "modules/spring/src/test/config/enc/not-encrypted-cache.xml",
+            "modules/spring/src/test/config/enc/enc-cache.xml");
+    }
+
+    /** */
+    private void doTestDiffCfgAndPersistentFlagVal(String cfg1, String cfg2) throws Exception {
+        cleanPersistenceDir();
+
+        IgniteEx g = (IgniteEx)IgnitionEx.start(IgniteUtils.resolveIgnitePath(cfg1).getAbsolutePath(), "grid-0");
+
+        g.cluster().active(true);
+
+        IgniteCache c = g.cache("encrypted");
+
+        assertNotNull(c);
+
+        stopAllGrids(false);
+
+        assertThrowsWithCause(() -> {
+            try {
+                IgnitionEx.start(IgniteUtils.resolveIgnitePath(cfg2).getAbsolutePath(), "grid-0");
+            }
+            catch (IgniteCheckedException e) {
+                throw new RuntimeException(e);
+            }
+        }, IgniteCheckedException.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
index 0e590a7..0943d51 100644
--- a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
+++ b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
@@ -23,6 +23,8 @@ import org.apache.ignite.cache.spring.GridSpringCacheManagerSelfTest;
 import org.apache.ignite.cache.spring.GridSpringCacheManagerSpringBeanSelfTest;
 import org.apache.ignite.cache.spring.SpringCacheManagerContextInjectionTest;
 import org.apache.ignite.cache.spring.SpringCacheTest;
+import org.apache.ignite.encryption.SpringEncryptedCacheRestartClientTest;
+import org.apache.ignite.encryption.SpringEncryptedCacheRestartTest;
 import org.apache.ignite.spring.injection.IgniteSpringBeanSpringResourceInjectionTest;
 import org.apache.ignite.internal.IgniteSpringBeanTest;
 import org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactorySelfTest;
@@ -93,6 +95,10 @@ public class IgniteSpringTestSuite extends TestSuite {
 
         suite.addTestSuite(SpringCacheTest.class);
 
+        suite.addTestSuite(SpringEncryptedCacheRestartTest.class);
+        suite.addTestSuite(SpringEncryptedCacheRestartClientTest.class);
+
+        //suite.addTestSuite(GridSpringCacheManagerMultiJvmSelfTest.class);
         suite.addTestSuite(GridSpringCacheManagerMultiJvmSelfTest.class);
 
         suite.addTestSuite(GridCommandLineLoaderTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/aabacfa0/modules/spring/src/test/resources/tde.jks
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/resources/tde.jks b/modules/spring/src/test/resources/tde.jks
new file mode 100644
index 0000000..1bf532c
Binary files /dev/null and b/modules/spring/src/test/resources/tde.jks differ


Mime
View raw message