You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2007/05/08 12:43:52 UTC
svn commit: r536156 - in
/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests:
suites/ tests/store/
Author: kristwaa
Date: Tue May 8 03:43:50 2007
New Revision: 536156
URL: http://svn.apache.org/viewvc?view=rev&rev=536156
Log:
DERBY-1001: Rewrite 'store/encryptionKey.sql' to a JUnit test.
Patch file: derby-1001-2a.diff
Added:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyAESTest.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyBlowfishTest.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyDESTest.java (with props)
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyTest.java (with props)
Modified:
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionAll.runall
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey.sql
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey_app.properties
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionAll.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionAll.runall?view=diff&rev=536156&r1=536155&r2=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionAll.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/encryptionAll.runall Tue May 8 03:43:50 2007
@@ -1,6 +1,5 @@
store/aes.sql
store/encryptParams.sql
-store/encryptionKey.sql
store/encryptDatabaseTest1.sql
store/encryptDatabaseTest2.sql
store/encryptDatabaseTest3.sql
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyAESTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyAESTest.java?view=auto&rev=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyAESTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyAESTest.java Tue May 8 03:43:50 2007
@@ -0,0 +1,48 @@
+/*
+ *
+ * Derby - Class org.apache.derbyTesting.functionTests.tests.store.EncryptionKeyAESTest
+ *
+ * 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.derbyTesting.functionTests.tests.store;
+
+import org.apache.derbyTesting.junit.*;
+import junit.framework.*;
+
+/**
+ * Test basic functionality on a database encrypted with the AES algorithm.
+ *
+ * @see EncryptionKeyTest
+ */
+public class EncryptionKeyAESTest
+ extends EncryptionKeyTest {
+
+ public EncryptionKeyAESTest(String name) {
+ super(name,
+ "AES/CBC/NoPadding",
+ "616263646666768661626364666676AF",
+ "919293949999798991929394999979CA",
+ "616263646666768999616263646666768",
+ "X1X2X3X4XXXX7X8XX1X2X3X4XXXX7X8X");
+ }
+
+ public static Test suite() {
+ // This test runs only in embedded due to the use of external files.
+ TestSuite suite = new TestSuite(EncryptionKeyAESTest.class,
+ "EncryptionKey AES suite");
+ return new SupportFilesSetup(suite);
+ }
+} // End class EncryptionKeyAESTest
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyAESTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyBlowfishTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyBlowfishTest.java?view=auto&rev=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyBlowfishTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyBlowfishTest.java Tue May 8 03:43:50 2007
@@ -0,0 +1,49 @@
+/*
+ *
+ * Derby - Class org.apache.derbyTesting.functionTests.tests.store.EncryptionKeyBlowfishTest
+ *
+ * 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.derbyTesting.functionTests.tests.store;
+
+import org.apache.derbyTesting.junit.*;
+import junit.framework.*;
+
+/**
+ * Test basic functionality on a database encrypted with the Blowfish
+ * algorithm.
+ *
+ * @see EncryptionKeyTest
+ */
+public class EncryptionKeyBlowfishTest
+ extends EncryptionKeyTest {
+
+ public EncryptionKeyBlowfishTest(String name) {
+ super(name,
+ "Blowfish/OFB/NoPadding",
+ "6162636466667686",
+ "9192939499997989",
+ "6162636466667689979",
+ "X1X2X3X4XXXX7X8X");
+ }
+
+ public static Test suite() {
+ // This test runs only in embedded due to the use of external files.
+ Test suite =
+ TestConfiguration.embeddedSuite(EncryptionKeyBlowfishTest.class);
+ return new SupportFilesSetup(suite);
+ }
+} // End class EncryptionKeyBlowfishTest
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyBlowfishTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyDESTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyDESTest.java?view=auto&rev=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyDESTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyDESTest.java Tue May 8 03:43:50 2007
@@ -0,0 +1,48 @@
+/*
+ *
+ * Derby - Class org.apache.derbyTesting.functionTests.tests.store.EncryptionKeyDESTest
+ *
+ * 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.derbyTesting.functionTests.tests.store;
+
+import org.apache.derbyTesting.junit.*;
+import junit.framework.*;
+
+/**
+ * Test basic functionality on a database encrypted with the DES algorithm.
+ *
+ * @see EncryptionKeyTest
+ */
+public class EncryptionKeyDESTest
+ extends EncryptionKeyTest {
+
+ public EncryptionKeyDESTest(String name) {
+ super(name,
+ "DES/CBC/NoPadding",
+ "6162636466667686",
+ "9192939499997989",
+ "6162636466667689979",
+ "X1X2X3X4XXXX7X8X");
+ }
+
+ public static Test suite() {
+ // This test runs only in embedded due to the use of external files.
+ Test suite =
+ TestConfiguration.embeddedSuite(EncryptionKeyDESTest.class);
+ return new SupportFilesSetup(suite);
+ }
+} // End class EncryptionKeyDESTest
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyDESTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyTest.java?view=auto&rev=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyTest.java Tue May 8 03:43:50 2007
@@ -0,0 +1,703 @@
+/*
+ *
+ * Derby - Class org.apache.derbyTesting.functionTests.tests.store.EncryptionKeyTest
+ *
+ * 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.derbyTesting.functionTests.tests.store;
+
+import java.io.File;
+
+import java.sql.Connection;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+
+import javax.sql.DataSource;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.JDBCDataSource;
+import org.apache.derbyTesting.junit.SupportFilesSetup;
+
+/**
+ * Tests various connection sequences to encrypted databases.
+ * Four kinds of external keys are used:
+ * <ol><li>the correct key
+ * <li>an incorrect key
+ * <li>a key with odd length (in hex representation)
+ * <li>a key containing invalid characters
+ * </ol>
+ * <p>
+ * The algorithms used for en-/decryption is determined by the subclasses,
+ * where a single algorithm and a set of keys are associated with each
+ * subclass.
+ * <p>
+ * Databases are created in the <tt>EXTINOUT</tt> directory. Backups are made
+ * to <tt>EXTINOUT/backups</tt> and restored databases are put into
+ * <tt>EXTINOUT/restored</tt> <b>if and only if</b> the databases need to be
+ * both written and read. Otherwise backups are placed in <tt>EXTOUT</tt>.
+ * Testsuites generated from this class must be wrapped in a
+ * <code>SupportFileSetup</code> decorator.
+ */
+ //@NotThreadSafe
+public abstract class EncryptionKeyTest
+ extends BaseJDBCTestCase {
+
+ /** Correct key constant. */
+ protected static final int CORRECT_KEY = 0;
+ /** Wrong key constant. */
+ protected static final int WRONG_KEY = 1;
+ /** Odd length key constant. */
+ protected static final int ODD_LENGTH_KEY = 2;
+ /** Invalid char key constant. */
+ protected static final int INVALID_CHAR_KEY = 3;
+
+ /** Table holding the test data. */
+ private static final String TABLE = "encryptionkeytestdata";
+ /** Test data inserted into database and used for verification. */
+ private static final int[] DATA = {9,4,2,34,6543,3,123,434,5436,-123,0,123};
+
+ /** The algorithm used by the fixture. */
+ private final String algorithm;
+
+ /** The correct key. */
+ private final String keyCorrect;
+ /** An incorrect key. */
+ private final String keyWrong;
+ /** A key with odd length. */
+ private final String keyOddLength;
+ /** A key with an invalid char in it. */
+ private final String keyInvalidChar;
+
+ /**
+ * Variable to hold the various connections.
+ * No guarantee is made about the state of this connection, but it is
+ * closed at tear-down.
+ */
+ private Connection con = null;
+
+ /**
+ * Configures a new setup by specifying the encryption properties.
+ *
+ * @param name name of the fixture
+ * @param algorithm encryption algorithm to use
+ * @param correctKey the correct encryption key
+ * @param wrongKey an incorrect encryption key
+ * @param oddLengthKey a key of odd length
+ * @param invalidCharKey a key with invalid characters
+ */
+ public EncryptionKeyTest(String name,
+ String algorithm,
+ String correctKey,
+ String wrongKey,
+ String oddLengthKey,
+ String invalidCharKey) {
+ super(name);
+ this.algorithm = algorithm;
+ this.keyCorrect = correctKey;
+ this.keyWrong = wrongKey;
+ this.keyOddLength = oddLengthKey;
+ this.keyInvalidChar = invalidCharKey;
+ }
+
+ /**
+ * Clean up the connection maintained by this test.
+ */
+ protected void tearDown()
+ throws java.lang.Exception {
+ if (con != null && !con.isClosed()) {
+ con.rollback();
+ con.close();
+ con = null;
+ }
+ super.tearDown();
+ }
+
+ /**
+ * Test a sequence of connections and connection attempts.
+ * Sequence: Create database, connect to database using correct key,
+ * try to connect using incorrect key, connect using correct key.
+ */
+ public void testConnectionSequence1()
+ throws SQLException {
+ String dbName = "encryptedDB_ConnectionSequence1";
+ // Create database.
+ con = createAndPopulateDB(dbName);
+ validateDBContents(con);
+ // Shutdown the database.
+ con.close();
+ shutdown(dbName);
+ // Connect using correct key.
+ con = getConnection(dbName, CORRECT_KEY);
+ validateDBContents(con);
+ con.close();
+ // Shutdown the database.
+ shutdown(dbName);
+ // Try to connect using wrong key.
+ try {
+ getConnection(dbName, WRONG_KEY);
+ fail("Booting with an incorrect encryption key should fail.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ040", sqle);
+ assertSQLState("XBCXK", getLastSQLException(sqle));
+ }
+ // Connect using correct key.
+ con = getConnection(dbName, CORRECT_KEY);
+ validateDBContents(con);
+ con.close();
+ // Shutdown the database.
+ shutdown(dbName);
+ }
+
+ /**
+ * Test a sequence of connections and connection attempts.
+ * Sequence: Create database, connect to database using odd length key,
+ * try to connect using incorrect key, connect using correct key.
+ */
+ public void testConnectionSequence2()
+ throws SQLException {
+ String dbName = "encryptedDB_ConnectionSequence2";
+ // Create database.
+ con = createAndPopulateDB(dbName);
+ validateDBContents(con);
+ // Shutdown the database.
+ con.close();
+ shutdown(dbName);
+ // Connect using odd length key.
+ try {
+ con = getConnection(dbName, ODD_LENGTH_KEY);
+ fail("Connected with an odd length key.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ040", sqle);
+ SQLException lastSQLE = getLastSQLException(sqle);
+ String sqlState = lastSQLE.getSQLState();
+ // The state of this exception varies with the security provider
+ // the test is run with.
+ // Briefly stated, the deciding factor is whether the error is
+ // caught by checks in the Derby code, or by the checks in the
+ // security provider. For instance, the (current Sun JCE) DES
+ // key implementation does not verify the key length, whereas the
+ // AES key implementation does. For other providers, the situation
+ // might be different.
+ // XBCX0 : A general crypto exception, wraps the exception from the
+ // security provider.
+ // XBCXM : A specific Derby exception for external keys of invalid
+ // lengths.
+ if (!sqlState.equals("XBCX0") && !sqlState.equals("XBCXM")) {
+ throw lastSQLE;
+ }
+ }
+ confirmNonBootedDB(dbName);
+ // Try to connect using wrong key.
+ try {
+ getConnection(dbName, WRONG_KEY);
+ fail("Booting with an incorrect encryption key should fail.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ040", sqle);
+ assertSQLState("XBCXK", getLastSQLException(sqle));
+ }
+ // Connect using correct key.
+ con = getConnection(dbName, CORRECT_KEY);
+ validateDBContents(con);
+ con.close();
+ // Shutdown the database.
+ shutdown(dbName);
+ }
+
+ /**
+ * Backup an encrypted database.
+ */
+ public void testBackupEncryptedDatabase()
+ throws SQLException {
+ String dbName = "encryptionKeyDBToBackup";
+ // Create the database.
+ con = createAndPopulateDB(dbName);
+ validateDBContents(con);
+ CallableStatement cs = con.prepareCall(
+ "CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE(?)");
+ cs.setString(1, SupportFilesSetup.EXTOUT);
+ // Perform backup.
+ cs.execute();
+ cs.close();
+ con.close();
+ shutdown(dbName);
+ // Connect to original database after backup.
+ con = getConnection(dbName, CORRECT_KEY);
+ validateDBContents(con);
+ con.close();
+ shutdown(dbName);
+ }
+
+ /**
+ * Create a new database from a backup image.
+ */
+ public void testCreateDbFromBackup()
+ throws SQLException {
+ // No ordering imposed by JUnit, so we create our own db and backup.
+ // Setup paths and names.
+ final String dbName = "encryptionKeyDBToCreateFrom";
+ final String backupDbLocation =
+ SupportFilesSetup.getReadWrite(
+ new File("backups", "encryptionKeyDBToCreateFrom").getPath()
+ ).getPath();
+ // Create the database.
+ con = createAndPopulateDB(dbName);
+ validateDBContents(con);
+ CallableStatement cs = con.prepareCall(
+ "CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE(?)");
+ cs.setString(1,
+ new File(SupportFilesSetup.EXTINOUT, "backups").getPath());
+ // Perform backup.
+ cs.execute();
+ cs.close();
+ con.close();
+ shutdown(dbName);
+ // Create a new database from backup.
+ String dbNameRestored = dbName + "Restored";
+ con = getPrivilegedConnection(dbNameRestored, CORRECT_KEY,
+ "createFrom=" + backupDbLocation);
+ validateDBContents(con);
+ con.close();
+ shutdown(dbNameRestored, "restored");
+ // Try to create a new database from backup with the wrong key.
+ dbNameRestored = dbName + "RestoreAttemptedWrongKey";
+ try {
+ con = getPrivilegedConnection(dbNameRestored, WRONG_KEY,
+ "createFrom=" + backupDbLocation);
+ fail("Created database from encrypted backup with wrong key.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ040", sqle);
+ assertSQLState("XBCXK", getLastSQLException(sqle));
+ }
+ assertTrue(con.isClosed());
+ // Try to create a new database from backup with an invalid key.
+ dbNameRestored = dbName + "RestoreAttemptedInvalidKey";
+ try {
+ con = getPrivilegedConnection(dbNameRestored, INVALID_CHAR_KEY,
+ "createFrom=" + backupDbLocation);
+ fail("Created database from encrypted backup with an invalid key.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ040", sqle);
+ assertSQLState("XBCXN", getLastSQLException(sqle));
+ }
+ assertTrue(con.isClosed());
+ // Try to create a new database from backup with an odd length key.
+ dbNameRestored = dbName + "RestoreAttemptedOddLengthKey";
+ try {
+ con = getPrivilegedConnection(dbNameRestored, ODD_LENGTH_KEY,
+ "createFrom=" + backupDbLocation);
+ fail("Created db from encrypted backup with an odd length key.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ040", sqle);
+ SQLException lastSQLE = getLastSQLException(sqle);
+ String sqlState = lastSQLE.getSQLState();
+ // The state of this exception varies with the security provider
+ // the test is run with.
+ // Briefly stated, the deciding factor is whether the error is
+ // caught by checks in the Derby code, or by the checks in the
+ // security provider. For instance, the (current Sun JCE) DES
+ // key implementation does not verify the key length, whereas the
+ // AES key implementation does. For other providers, the situation
+ // might be different.
+ // XBCX0 : A general crypto exception, wraps the exception from the
+ // security provider.
+ // XBCXM : A specific Derby exception for external keys of invalid
+ // lengths.
+ if (!sqlState.equals("XBCX0") && !sqlState.equals("XBCXM")) {
+ throw lastSQLE;
+ }
+ }
+ assertTrue(con.isClosed());
+ // Create a new database from backup again.
+ dbNameRestored = dbName + "RestoredOnceMore";
+ con = getPrivilegedConnection(dbNameRestored, CORRECT_KEY,
+ "createFrom=" + backupDbLocation);
+ validateDBContents(con);
+ con.close();
+ shutdown(dbNameRestored, "restored");
+ }
+
+ /**
+ * Recover the database using <tt>restoreFrom</tt>.
+ */
+ public void testRestoreFrom()
+ throws SQLException {
+ // No ordering imposed by JUnit, so we create our own db and backup.
+ String dbName = "encryptionKeyDBToRestoreFrom";
+ String dbNameRestored = dbName + "Restored";
+ createBackupRestore(dbName, dbNameRestored);
+ shutdown(dbNameRestored, "restored");
+ }
+
+ /**
+ * Try to recover database with an invalid key.
+ * <p>
+ * It should be noted that the existing database, which has been previously
+ * recovered from the same backup image, is deleted/overwritten even though
+ * Derby is unable to boot the backup image.
+ */
+ public void testInvalidRestoreFrom()
+ throws SQLException {
+ // No ordering imposed by JUnit, so we create our own db and backup.
+ String dbName = "encryptionKeyDBToInvalidRestoreFrom";
+ String dbNameRestored = dbName + "Restored";
+ createBackupRestore(dbName, dbNameRestored);
+ shutdown(dbNameRestored, "restored");
+ // Check that the database is not booted.
+ confirmNonBootedDB("restored/" + dbNameRestored);
+ // Validate the existing database.
+ con = getConnection("restored/" + dbNameRestored, CORRECT_KEY);
+ validateDBContents(con);
+ con.close();
+ shutdown(dbNameRestored, "restored");
+ // Confirm that trying a restore with an invalid key will overwrite
+ // the existing database we are trying to restore to/into. This is
+ // expected behavior currently, but should maybe change?
+ try {
+ con = getPrivilegedConnection(dbNameRestored, INVALID_CHAR_KEY,
+ ";restoreFrom=" + obtainDbName(dbName, null));
+ fail("Restored database with an invalid key.");
+ } catch (SQLException sqle) {
+ assertSQLState("XBCXN", sqle);
+ }
+ // The database should no longer exist.
+ try {
+ // The "" is a hack to avoid using "create=true".
+ con = getConnection("restored/" + dbNameRestored, CORRECT_KEY, "");
+ fail("Expected connection to fail due to non-existent database.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ004", sqle);
+ }
+ }
+
+ /**
+ * Try to create database with a key of odd length.
+ */
+ public void testCreateWithOddEncryptionKeyLength()
+ throws SQLException {
+ try {
+ getConnection("encryptedDB_oddKeyLength", ODD_LENGTH_KEY);
+ fail("Database creation with odd key length should fail.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ041", sqle);
+ SQLException lastSQLE = getLastSQLException(sqle);
+ String sqlState = lastSQLE.getSQLState();
+ // The state of this exception varies with the security provider
+ // the test is run with. In general, it depends on whether it is
+ // Derby code or the security provider code that detects the
+ // problem with the encryption key.
+ if (!sqlState.equals("XBCXM") && !sqlState.equals("XJ001")) {
+ throw lastSQLE;
+ }
+ }
+ }
+
+ /**
+ * Try to create database with a key containing one or more invalid chars.
+ */
+ public void testCreateWithInvalidEncryptionKey() {
+ try {
+ getConnection("encryptedDB_invkeyChar", INVALID_CHAR_KEY);
+ fail("Database creation with invalid key should fail.");
+ } catch (SQLException sqle) {
+ assertSQLState("XJ041", sqle);
+ assertSQLState("XBCXN", getLastSQLException(sqle));
+ }
+ }
+
+ /* ********************************************************************* *
+ * H E L P E R M E T H O D S *
+ * ********************************************************************* */
+
+ /**
+ * Obtain absolute path for the specified database name.
+ * <p>
+ * This absolute path is the name of the database (specified) prefixed with
+ * the absolute path to the EXTINOUT directory. The latter is determined by
+ * consulting <code>SupportFilesSetup</code>.
+ *
+ * @param dbName name of the database
+ * @param subdirectory directory to prefix the database name with (can be
+ * <code>null</code>). Note that the database name will be prefixed
+ * with the path to the EXTINOUT directory even if this parameter is
+ * <code>null</code>.
+ * @return A string with the absolute path to the database.
+ * @see SupportFilesSetup
+ */
+ private String obtainDbName(String dbName, String subdirectory) {
+ File tmp = new File(dbName);
+ if (subdirectory != null) {
+ tmp = new File(subdirectory, dbName);
+ }
+ final File db = tmp;
+ return (String)AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ return new File(SupportFilesSetup.EXTINOUT,
+ db.getPath()).getAbsolutePath();
+ }
+ }
+ );
+ }
+
+ /**
+ * Create encrypted database, validate it, backup, restore and validate
+ * recovered database.
+ * <p>
+ * The source db is shutdown, the recovered db is left booted.
+ *
+ * @param sourceDb the original database to create
+ * @param targetDb the database to recover to
+ */
+ private void createBackupRestore(String sourceDb, String targetDb)
+ throws SQLException {
+ // Create the database.
+ con = createAndPopulateDB(sourceDb);
+ validateDBContents(con);
+ CallableStatement cs = con.prepareCall(
+ "CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE(?)");
+ cs.setString(1,
+ new File(SupportFilesSetup.EXTINOUT, "backups").getPath());
+ // Perform backup.
+ cs.execute();
+ con.close();
+ shutdown(sourceDb);
+ confirmNonBootedDB(sourceDb);
+ // Use the restoreFrom attribute.
+ con = getPrivilegedConnection(targetDb, CORRECT_KEY,
+ ";restoreFrom=" + obtainDbName(sourceDb, "backups"));
+ validateDBContents(con);
+ con.close();
+ }
+
+ /**
+ * Confirm that the specified encrypted database has not been booted.
+ *
+ * @param dbName name of an encrypted database
+ * @throws junit.framework.AssertionFailedError if the database has been
+ * booted (connection may or may not be established)
+ */
+ private void confirmNonBootedDB(String dbName) {
+ DataSource ds = JDBCDataSource.getDataSource(obtainDbName(dbName, null));
+ try {
+ ds.getConnection();
+ } catch (SQLException sqle) {
+ assertSQLState("Database booted? <state:" + sqle.getSQLState() +
+ ", msg:" + sqle.getMessage() + ">", "XJ040", sqle);
+ }
+ }
+
+ /**
+ * Try to establish a connection to the named database with the
+ * specified type of key.
+ *
+ * @param dbName name of the database
+ * @param keyMode what kind of key to use (correct, wrong, invalid, odd)
+ * @return A connection to the database.
+ * @throws SQLException if connection fails
+ */
+ private Connection getConnection(String dbName, int keyMode)
+ throws SQLException {
+ return getConnection(dbName, keyMode, null);
+ }
+
+ /**
+ * Try to establish a connection to the named database with the
+ * specified type of key and recovery mode.
+ * <p>
+ * The connection is made in a privileged block of code to allow Derby to
+ * read the database backup used for recovery.
+ *
+ * @param dbName name of the database
+ * @param keyMode what kind of key to use (correct, wrong, invalid, odd)
+ * @param recoveryAttribute attribute to recover a database from a backup,
+ * for instance <code>createFrom</code> or <code>restoreFrom</code>.
+ * Both the attribute and its value is expected.
+ * @return A connection to the database.
+ * @throws SQLException if connection fails
+ */
+ private Connection getPrivilegedConnection(final String dbName,
+ final int keyMode,
+ final String recoveryAttribute)
+ throws SQLException {
+ try {
+ return (Connection)AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ public Object run()
+ throws SQLException {
+ return getConnection(dbName, keyMode,
+ recoveryAttribute);
+ }
+ });
+ } catch (PrivilegedActionException pae) {
+ throw (SQLException)pae.getException();
+ }
+ }
+
+ /**
+ * Create a new connection to the specified database, using the given
+ * connection attributes.
+ *
+ * @param dbName name of the database
+ * @param keyMode what kind of key to use (correct, wrong, invalid, odd)
+ * @param recoveryAttribute attribute to recover a database from a backup,
+ * for instance <code>createFrom</code> or <code>restoreFrom</code>.
+ * Both the attribute and its value is expected.
+ * @return A connection to the database.
+ * @throws SQLException if connection fails
+ */
+ private Connection getConnection(String dbName,
+ int keyMode,
+ String recoveryAttribute)
+ throws SQLException {
+ DataSource ds = JDBCDataSource.getDataSource(
+ obtainDbName(dbName,
+ recoveryAttribute == null ? null : "restored"));
+ StringBuffer str = new StringBuffer(75);
+ if (recoveryAttribute == null) {
+ // Enable data encryption is this database is being created.
+ JDBCDataSource.setBeanProperty(ds, "CreateDatabase", "create");
+ str.append("dataEncryption=true;");
+ } else {
+ str.append(recoveryAttribute);
+ str.append(";");
+ }
+ // Add the encryption algorithm.
+ str.append("encryptionAlgorithm=");
+ str.append(algorithm);
+ str.append(";");
+ // Add the key.
+ str.append("encryptionKey=");
+ switch (keyMode) {
+ case CORRECT_KEY:
+ str.append(keyCorrect);
+ break;
+ case WRONG_KEY:
+ str.append(keyWrong);
+ break;
+ case ODD_LENGTH_KEY:
+ str.append(keyOddLength);
+ break;
+ case INVALID_CHAR_KEY:
+ str.append(keyInvalidChar);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid key mode specified: " + keyMode);
+ }
+ str.append(";");
+ JDBCDataSource.setBeanProperty(
+ ds, "connectionAttributes", str.toString());
+ return ds.getConnection();
+ }
+
+ /**
+ * Shutdown the specified database.
+ *
+ * @param databaseName the name of the database
+ */
+ protected void shutdown(String databaseName)
+ throws SQLException {
+ shutdown(databaseName, null);
+ }
+
+ /**
+ * Shutdown the database, specified by the database name and prefix.
+ *
+ * @param databaseName the name of the database
+ * @param dir sub-directory prefix for the database
+ */
+ protected void shutdown(String databaseName, String dir)
+ throws SQLException {
+ DataSource ds = JDBCDataSource.getDataSource(
+ obtainDbName(databaseName, dir));
+ JDBCDataSource.shutdownDatabase(ds);
+ }
+
+ /**
+ * Create a new database and populate it.
+ * <p>
+ * The method fails with an exception if the database already exists.
+ * This is because it is the creation process that is to be tested.
+ *
+ * @param dbName name of the database to create
+ * @return A connection the to the newly created database.
+ * @throws SQLException if the database already exist, or
+ * a general error happens during database interaction
+ */
+ protected Connection createAndPopulateDB(String dbName)
+ throws SQLException {
+ Connection con = getConnection(dbName, CORRECT_KEY);
+ SQLWarning warning = con.getWarnings();
+ // If the database already exists, fail the test.
+ if (warning != null) {
+ if ("01J01".equals(warning.getSQLState())) {
+ fail("Refusing to continue, database already exists <" +
+ warning.getMessage() + ">");
+ }
+ }
+ Statement stmt = con.createStatement();
+ stmt.executeUpdate("CREATE TABLE " + TABLE + " (id int NOT NULL, " +
+ "val int NOT NULL, PRIMARY KEY(id))");
+ stmt.close();
+ PreparedStatement ps = con.prepareStatement("INSERT INTO " + TABLE +
+ " (id, val) VALUES (?,?)");
+ for (int i=0; i < DATA.length; i++) {
+ ps.setInt(1, i);
+ ps.setInt(2, DATA[i]);
+ ps.executeUpdate();
+ }
+ ps.close();
+ return con;
+ }
+
+ /**
+ * Validate the data in the database against the data model.
+ *
+ * @param con the database to validate the contents of
+ * @throws junit.framework.AssertionFailedError if there is a mismatch
+ * between the data in the database and the model
+ */
+ protected void validateDBContents(Connection con)
+ throws SQLException {
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery("SELECT id, val FROM " + TABLE +
+ " ORDER BY id");
+ int id, val;
+ while (rs.next()) {
+ id = rs.getInt(1);
+ val = rs.getInt(2);
+ if (id >= DATA.length) {
+ fail("Id in database out of bounds for data model; " +
+ id + " >= " + DATA.length);
+ }
+ if (val != DATA[id]) {
+ fail("Mismatch between db and model for id " + id + ";" +
+ val + " != " + DATA[id]);
+ }
+ }
+ rs.close();
+ stmt.close();
+ }
+} // End EncryptionKeyTest
Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/EncryptionKeyTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java?view=diff&rev=536156&r1=536155&r2=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java Tue May 8 03:43:50 2007
@@ -22,6 +22,8 @@
package org.apache.derbyTesting.functionTests.tests.store;
import org.apache.derbyTesting.junit.BaseTestCase;
+import org.apache.derbyTesting.junit.JDBC;
+
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -50,7 +52,16 @@
TestSuite suite = new TestSuite("store");
suite.addTest(BootAllTest.suite());
+
+ // Encryption only supported for Derby in J2SE/J2EE environments.
+ // J2ME (JSR169) does not support encryption.
+ if (JDBC.vmSupportsJDBC3()) {
+ // Add tests of basic functionality on encrypted databases.
+ suite.addTest(EncryptionKeyAESTest.suite());
+ suite.addTest(EncryptionKeyBlowfishTest.suite());
+ suite.addTest(EncryptionKeyDESTest.suite());
+ }
return suite;
}
-}
\ No newline at end of file
+}
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey.sql
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey.sql?view=diff&rev=536156&r1=536155&r2=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey.sql (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey.sql Tue May 8 03:43:50 2007
@@ -1,112 +0,0 @@
---
--- 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.
---
-------------------------------------------------------------------------------------
--- This test file contains test cases for testing encryptionKey property in the connection
--- url
---
--- Case 1: use external encryption key and create
--- connect using correct key
--- connect using wrong key ( different length, different key)
--- connect again using correct key
--- Case 2: backup database
--- connect to original db after backup
--- Case 3: createFrom backedup database
--- with wrong key
--- with right key
--- with wrong key
--- with right key
--- test restoreFrom
--- Case 4: use invalid key when trying to create
--- key length not even
--- key contains invalid character(s)
---
-------------------------------------------------------------------------------------
--- case1: give external encryptionKey instead of bootpassword
-connect 'jdbc:derby:encdbcbc_key;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-
-create table t1(i1 int);
-insert into t1 values(1);
-select * from t1;
-commit;
-connect 'jdbc:derby:encdbcbc_key;shutdown=true';
-
--- case 1.1 - right key
-
-connect 'jdbc:derby:encdbcbc_key;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-select * from t1;
-
-connect 'jdbc:derby:encdbcbc_key;shutdown=true';
--- (-ve case) connect without the encryptionKey
--- connect with encryptionKey and keylength ( will ignore the keylength value)
-
--- wrong length
-connect 'jdbc:derby:encdbcbc_key;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6163646566676868';
--- wrong key
-connect 'jdbc:derby:encdbcbc_key;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6862636465666768';
-select * from t1;
-
--- correct key
-connect 'jdbc:derby:encdbcbc_key;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-select * from t1;
-
--- case 2 backup
-CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE('extinout/bkup1');
-connect 'jdbc:derby:encdbcbc_key;shutdown=true';
-
--- connect to original db after backup
-
-connect 'jdbc:derby:encdbcbc_key;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-select * from t1;
-
--- case 3 :create db from backup using correct key
-connect 'jdbc:derby:encdbcbc_key2;createFrom=extinout/bkup1/encdbcbc_key;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-select * from t1;
-connect 'jdbc:derby:encdbcbc_key2;shutdown=true';
-
--- create db from backup using wrong key
-connect 'jdbc:derby:encdbcbc_key3;createFrom=extinout/bkup1/encdbcbc_key;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6122636465666768';
-select * from t1;
-
-connect 'jdbc:derby:encdbcbc_key3;shutdown=true';
-
--- create db from backup using correct key
-connect 'jdbc:derby:encdbcbc_12;createFrom=extinout/bkup1/encdbcbc_key;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-select * from t1;
-
-connect 'jdbc:derby:encdbcbc_key12;shutdown=true';
-
-connect 'jdbc:derby:encdb;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-create table t1(i1 int ,c2 char(20));
-insert into t1 values(1,'a');
-select * from t1;
-
-call SYSCS_UTIL.SYSCS_BACKUP_DATABASE('extinout/mybackup2');
-
-connect 'jdbc:derby:encdb;shutdown=true';
-disconnect;
-
-connect 'jdbc:derby:encdb;restoreFrom=extinout/mybackup2/encdb;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=6162636465666768';
-select * from t1;
-disconnect;
-
--- case 4 : invalid keys
--- key length not even
-connect 'jdbc:derby:encddbdb_invkey;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=123456789';
-
--- key contains illegal character(s)
-connect 'jdbc:derby:encddbdb_invkey;create=true;dataEncryption=true;encryptionAlgorithm=DES/CBC/NoPadding;encryptionKey=61626364656667XY';
-
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey_app.properties
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey_app.properties?view=diff&rev=536156&r1=536155&r2=536156
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey_app.properties (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/encryptionKey_app.properties Tue May 8 03:43:50 2007
@@ -1,9 +0,0 @@
-#database=jdbc:derby:wombat;create=true;dataEncryption=true;bootPassword=Thursday
-
-#
-derby.optimizer.noTimeout=true
-
-ij.showNoConnectionsAtStart=true
-ij.showNoCountForSelect=true
-runwithjdk13=false
-useextdirs=true