I am currently building a Java EE 7 application that will utilize an Oracle 12c database for persistent storage. Because some of the data is sensitive, I decided to enable Oracle’s Transparent Data Encryption (TDE) feature, so that I could encrypt particular columns to guard against disclosure of this sensitive data either through the theft of my computer, or the theft of my backup system. Enabling TDE also permits me to research various facets of Oracle security that I can use in instructing my students in my forthcoming advanced database application programming class.
TDE offers a no-code solution to the “clear text on disk” problem, where relational database data can be rendered vulnerable simply through access to the physical data file storing the data, rather than through access through the RDBMS in the usual manner, which would require authentication. Encrypting a column is done simply by adding the
ENCRYPT clause to a column definition, along with the precise specification of which encryption algorithm should be used (eg, AES-256). Here’s an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
CREATE TABLE ATHLETE( athleteID INTEGER NOT NULL PRIMARY KEY, /* Uses sequence */ lastName VARCHAR2(40) ENCRYPT USING 'AES256' NOT NULL, firstName VARCHAR2(40) ENCRYPT USING 'AES256' NOT NULL, gender CHAR(1) ENCRYPT USING 'AES256' NOT NULL, handedness CHAR(1), DOB DATE ENCRYPT USING 'AES256', streetAddress VARCHAR2(50) ENCRYPT USING 'AES256', city VARCHAR2(40) ENCRYPT USING 'AES256', state_province VARCHAR2(30) ENCRYPT USING 'AES256', postalCode VARCHAR2(7) ENCRYPT USING 'AES256', country VARCHAR2(30) ENCRYPT USING 'AES256', phone VARCHAR2(15) ENCRYPT USING 'AES256', mobile VARCHAR2(15) ENCRYPT USING 'AES256', email VARCHAR2(100) ENCRYPT USING 'AES256', notes VARCHAR2(400) ENCRYPT USING 'AES256' );
Before one can specify a CREATE TABLE statement with an encrypted column, a user with the SYSKM management role must create a keystore to store the cryptographic keys in encryption. The keystore is stored in a specific directory, typically a subdirectory under the Oracle network administration directory. As my Oracle 12c installation is on Windows 7 SP 1, and my system ID is ORA12C, my location for the keystore directory, which I called “encryption_keystore”, was:
For help in configuring TDE with my 12c installation, I referred to:
- Chapter 11, “Oracle Transparent Data Encryption”, in Oracle Database 12c Security;
- Configuring Transparent Data Encryption in the online Oracle 12c Database Advanced Security Guide; and
- a very helpful page from ORACLE-BASE that describes configuring TDE for Oracle 12c installations with pluggable databases.
The three references above are excellent, and explain in detail what has to be done to create a keystore and configure server encryption using the
ADMINISTER KEY MANAGEMENT statement. For my purposes, particularly because I’m running Oracle 12c on a laptop, I decided to implement auto-login keystore access so that I could avoid being prompted for the master encryption key each time the server started. As well, to simply things I decided to only implement a single keystore for my entire Oracle container, rather than implement separate keystores for every pluggable database.
The purpose of this post is to document a TDE configuration issue that sidetracked me for some time; hopefully by documenting this issue here I can save other developers, students, and Oracle database administrators some time when setting up their own installations.
The directory location of the TDE keystore, or “wallet” has to be placed into the sqlnet.ora file, which is by default located in the \NETWORK\ADMIN directory. After configuring the keystore using the checklists from the references above, my sqlnet.ora file then looked as follows:
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
# sqlnet.ora Network Configuration FILE: C:\oracle12c\product\12.1.0\dbhome_1\network\admin\sqlnet.ora # Generated BY Oracle configuration tools. # This FILE IS actually generated BY netca. But IF customers choose TO # install "Software Only", this FILE wont exist AND without the native # authentication, they will NOT be able TO CONNECT TO the DATABASE ON NT. SQLNET.AUTHENTICATION_SERVICES= (NTS) NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT) ENCRYPTION_WALLET_LOCATION= (SOURCE= (METHOD=FILE) (METHOD_DATA= DIRECTORY=c:\oracle12c\product\12.1.0\dbhome_1\NETWORK\ADMIN\ora12c\encryption_keystore\) ) )
The ENCRYPTION_WALLET_LOCATION settings were copied from the Oracle reference pages, substituting my Oracle installation directory and wallet directory for the example given in the documentation. Upon restarting Oracle, however, I could not connect to the server from the SQL Developer client; instead I got the error message that a server connection could not be established. I could properly connect to the database server using the command-line SQLPLUS client, which uses a shared-memory OCI connection to the server. So I could verify that my pluggable databases had been started, and I could create tables that included encrypted columns, so my encryption configuration had been successful.
Checking my list of services in Windows’ Control Panel, I found that, sure enough, the Oracle listener had failed to start. Restarting the listener service manually resulted in an immediate failure, but as a service the error message does not contain a cause. I then attempted to start the Oracle listener manually using the “lsnrctl” utility (ensure the command shell is started with “Run as Administrator”:
That confirmed the listener startup errors (TNS-12560 and TNS-00530); in digging through the listener logs, the error contained a bit more detail: “could not parse configuration parameters”. Clearly this is looking like my edits of sqlnet.ora were incorrect. Some Google searches led me to this very helpful issue on the Oracle Community Forums that documented the problem: the trailing backslash for the wallet directory was an issue for Windows installations. Additionally, it seemed that the case-sensitivity of directory name is equally important, including using “C:” rather than “c:”. While a lowercase drive letter appeared to fail, and an uppercase “C” worked, I could not reproduce this behaviour a second time. Finally, my sqlnet.ora file looks like this:
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
# sqlnet.ora Network Configuration FILE: C:\oracle12c\product\12.1.0\dbhome_1\network\admin\sqlnet.ora # Generated BY Oracle configuration tools. # This FILE IS actually generated BY netca. But IF customers choose TO # install "Software Only", this FILE wont exist AND without the native # authentication, they will NOT be able TO CONNECT TO the DATABASE ON NT. SQLNET.AUTHENTICATION_SERVICES= (NTS) NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT) ENCRYPTION_WALLET_LOCATION= (SOURCE= (METHOD=FILE) (METHOD_DATA= DIRECTORY=C:\oracle12c\product\12.1.0\dbhome_1\NETWORK\ADMIN\ora12c\encryption_keystore) ) )
and, with the listener now started, I could continue developing my application.