|Oracle9i Application Developer's Guide - Fundamentals
Release 2 (9.2)
Part Number A96590-01
This chapter provides a description of the data encryption package (
DBMS_OBFUSCATION_TOOLKIT) that allows you to encrypt data in a database. Data encryption topics are presented in the following sections:
The Internet poses new challenges in information security, especially for those organizations seeking to become e-businesses. Many of these security challenges can be addressed by the traditional arsenal of security mechanisms:
Encryption is an important component of several of the above solutions. For example, Secure Sockets Layer (SSL), an Internet-standard network encryption and authentication protocol, uses encryption to strongly authenticate users by means of X.509 digital certificates. SSL also uses encryption to ensure data confidentiality, and cryptographic checksums to ensure data integrity. Many of these uses of encryption are relatively transparent to a user or application. For example, many browsers support SSL, and users generally do not need to do anything special to enable SSL encryption.
Oracle has provided network encryption between database clients and the Oracle database since Oracle7. Oracle Advanced Security, an option to Oracle9i, provides encryption and cryptographic integrity check for any protocol supported by Oracle9i, including Net8, Java Database Connectivity (JDBC) (both "thick" and "thin" JDBC), and the Internet Intra-Orb Protocol (IIOP). Oracle Advanced Security also supports SSL for Net8, "thick" JDBC and IIOP connections.
While encryption is not a security cure-all, it is an important tool used to address specific security threats, and will become increasingly important with the growth of e-business, especially in the area of encryption of stored data. For example, while credit card numbers are typically protected in transit to a web site using SSL, the credit card number is often stored in the clear (un-encrypted), either on the file system, where it is vulnerable to anyone who can break into the host and gain root access, or in databases. While databases can be made quite secure through proper configuration, they can also be vulnerable to host break-ins if the host is mis-configured. There have been several well-publicized break-ins, in which a hacker obtained a large list of credit card numbers by breaking into a database.
Encryption of stored data thus represents a new challenge for e-businesses, and can be an important tool in dealing with specific types of security threats.
While there are many good reasons to encrypt data, there are many bad reasons to encrypt data. Encryption does not solve all security problems, and may even make some problems worse. The following section describes some of the misconceptions about encryption of stored data. It includes these topics:
Most organizations need to limit access to data to those who have a "need to know." For example, a human resources system may limit employees to reviewing only their own employment records, while managers of employees may see the employment records of those employees working for them. Human resources specialists may also need to see employee records for multiple employees.
This type of security policy-----limiting data access to those with a need to see it-----is typically addressed by access control mechanisms. The Oracle database has provided strong, independently-evaluated access control mechanisms for many years. Recently, Oracle9i has added the ability to enforce access control to an extremely fine level of granularity, through its Virtual Private Database capability.
Because human resources records are considered sensitive information, it is tempting to think that this information should all be encrypted "for better security." However, encryption cannot enforce the type of granular access control described above, and may actually hinder data access. In the human resources example, an employee, his manager, and the HR clerk all need to access the employee's record. If employee data is encrypted, then each person also has to be able to access the data in un-encrypted form. Therefore, the employee, the manager and the HR clerk would have to share the same encryption key to decrypt the data. Encryption would therefore not provide any additional security in the sense of better access control, and the encryption might actually hinder the proper functioning of the application. An additional issue is that it is very difficult to securely transmit and share encryption keys among multiple users of a system.
A basic principle behind encrypting stored data is that it must not interfere with access control. For example, a user who has
SELECT privilege on
EMP should not be limited by the encryption mechanism from seeing all the data he is otherwise allowed to see. Similarly, there is little benefit to encrypting part of a table with one key and part of a table with another key if users need to see all encrypted data in the table; it merely adds to the overhead of decrypting the data before users can read it. Provided that access controls are implemented well, there is little additional security provided within the database itself from encryption. Any user who has privilege to access data within the database has no more nor any less privilege as a result of encryption. Therefore, encryption should never be used to solve access control problems.
Some organizations are concerned that a malicious user can gain elevated (DBA) privilege through guessing a password. These organizations would like to encrypt stored data to protect against this threat. However, the correct solution to this problem is to protect the DBA account, and to change default passwords for other privileged accounts. The easiest way to break into a database is through an unchanged password for a privileged account (for example, SYS/CHANGE_ON_INSTALL).
Note that there are many other destructive things a malicious user can do to a database once he gains DBA privilege. Examples include corrupting or deleting data, exporting user data to the file system to mail the data back to himself so as to run a password cracker on it, etc. Encryption will not protect against these threats.
Some organizations are concerned that database administrators (DBAs), because they typically have all privileges, are able to see all data in the database. These organizations feel that the DBAs should merely administer the database, but should not be able to see the data that the database contains. Some organizations are also concerned about the concentration of privilege in one person, and would prefer to partition the DBA function, or enforce two-person access rules.
It is tempting to think that encrypting all data (or significant amounts of data) will solve the above problems, but there are better ways to protect against these threats. First of all, Oracle does support limited partitioning of
DBA privilege. Oracle9i provides native support for
SYSDBA has all privileges, but
SYSOPER has a limited privilege set (such as startup and shutdown of the database). Furthermore, an organization can create smaller roles encompassing a number of system privileges. A
JR_DBA role might not include all system privileges, but only those appropriate to a more junior database administrator (such as
CREATE USER, and so on). Oracle also enables auditing the actions taken by
SYS-privileged users) and storing that audit trail in a secure operating system location. Using this model, a separate auditor who has root on the OS can audit all actions by SYS, enabling the auditor to hold all DBAs accountable for their actions.
DBA function by its nature is a trusted position. Even organizations with the most sensitive data-----such as intelligence agencies-----do not typically partition the
DBA function. Instead, they vet their
DBAs strongly, because it is a position of trust. Periodic auditing can help to uncover inappropriate activities.
Encryption of stored data must not interfere with the administration of the database; otherwise, larger security issues can result. For example, if by encrypting data you corrupt the data, you've created a security problem: data is not meaningful and may not be recoverable.
Encryption can be used to mitigate the ability of a
DBA-----or other privileged user-----to see data in the database. However, it is not a substitute for vetting a
DBA properly, or for limiting the use of powerful system privileges. If an untrustworthy user has significant privilege, there are multiple threats he can pose to an organization, and these may be far more significant than viewing un-encrypted credit card numbers.
It is a pervasive tendency to think that if storing some data encrypted strengthens security, then encrypting everything makes all data secure.
As described above, encryption does not address access control issues well. Consider the implications of encrypting an entire production database. All data must be decrypted to be read, updated, or deleted, and the encryption must not interfere with normal access controls. Encryption is inherently a performance-intensive operation; encrypting all data will significantly affect performance. Availability is a key aspect of security and if, by encrypting data, you make data unavailable, or the performance adversely affects availability, then you have created a new security problem.
Encryption keys must be changed regularly as part of good security practice, which necessitates that the database be inaccessible while the data is being decrypted and re-encrypted with a new key or keys. This also adversely affects availability.
While encrypting all or most of the data in a production database is clearly a problem, there may be advantages to encrypting data stored off-line. For example, an organization may store backups for a period of six months to a year off-line, in a remote location. Of course, the first line of protection is to secure the data in a facility to which access is controlled--a physical measure. However, there may be a benefit to encrypting this data before it is stored. Since it is not being accessed on-line, performance need not be a consideration. While Oracle9i does not provide this facility, there are vendors who can provide such encryption services. Before embarking on large-scale encryption of backup data, organizations considering this approach should thoroughly test the process. It is essential that any data which is encrypted before off-line storage, can be decrypted and re-imported successfully.
DBMS_OBFUSCATION_TOOLKIT provides several means for addressing the security issues that have been discussed. This section includes these topics:
While there are many security threats that encryption cannot address well, it is clear that an additional measure of security can be achieved by selectively encrypting sensitive data before storage in the database. Examples of such data could include:
To address these needs, Oracle9i provides a PL/SQL package to encrypt and decrypt stored data. The package,
DBMS_OBFUSCATION_TOOLKIT, is provided in both Standard Edition and Enterprise Edition Oracle9i. This package currently supports bulk data encryption using the Data Encryption Standard (DES) algorithm, and includes procedures to encrypt (DESEncrypt) and decrypt (DESDecrypt) using DES. The DBMS_OBFUSCATION_TOOLKIT also includes functions to encrypt and decrypt using 2-key and 3-key DES, in outer cipher block chaining mode. They require keylengths of 128 and 192 bits, respectively.
The DBMS_OBFUSCATION_TOOLKIT includes a cryptographic checksumming capabilities (MD5), and the ability to generate a secure random number (GetKey). Secure random number generation is important part of cryptography; predictable keys are easily-guessed keys, and easily-guessed keys may lead to easy decryption of data. Most cryptanalysis is done by finding weak keys or poorly-stored keys, rather than through brute force analysis (cycling through all possible keys).
Key management is programmatic. That is, the application (or caller of the function) must supply the encryption key; and this means that the application developer must find a way of storing and retrieving keys securely. The relative strengths and weaknesses of various key management techniques are discussed below. The
DBMS_OBFUSCATION_TOOLKIT package, which can handle both string and raw data, requires the submission of a 64-bit key. The DES algorithm itself has an effective key length of 56-bits.
The DBMS_OBFUSCATION_TOOLKIT is granted to PUBLIC by default. Oracle strongly recommends that this grant be revoked. In general, there is no reason why users should be able to encrypt stored data outside the context of an application.
Oracle9i Supplied PL/SQL Packages and Types Reference for documentation of the
Even in cases where encryption can provide additional security, it is not without its technical challenges. These challenges are described in the following section, which includes:
Special difficulties arise in handling encrypted data which is indexed. For example, suppose a company uses a national identity number (such as the U.S. Social Security number (SSN)) as the employee number for its employees. The company considers employee numbers to be very sensitive data and therefore wants to encrypt data in the
EMPLOYEE_NUMBER column of the
EMPLOYEES table. Because
EMPLOYEE_NUMBER contains unique values, the database designers want to have an index on it for better performance.
However, if the
DBMS_OBFUSCATION_TOOLKIT (or another mechanism) is used to encrypt data in a column, then an index on that column will also contain encrypted values. However, although the index can be used for equality checking (for example,
`SELECT * FROM emp WHERE employee_number = `123245'), if the index on that column contains encrypted values, then the index is essentially unusable for any other purpose. Oracle therefore recommends that developers not encrypt indexed data.
One way of solving this problem would be for the company seeking to encrypt national identity numbers to create an alternate, uniquely identifying number for each of its employees. The company could subsequently create an index on these alternate employee numbers and retain them in clear text. The corresponding national identity numbers could be placed in a separate column without indexing, and the values in it could be encrypted by an application that would also handle decrypting appropriately. In this manner, the national identity number could be obtained when necessary but would not be used as a unique number to identify employees.
Given the privacy issues associated with overuse of national identity numbers (for example, identity theft), the fact that some allegedly unique national identity numbers have duplicates (as with U.S. Social Security numbers), and the ease with which a sequence can generate a unique number, there are many good reasons to avoid using national identity numbers as unique IDs.
To address the issue of secure cryptographic key generation, Oracle9i adds support for a secure random number generation, the GetKey procedure of the DBMS_OBFUSCATION_TOOLKIT. The GetKey procedure calls the secure random number generator (RNG) that has previously been certified against the Federal Information Processing Standard (FIPS)-140 as part of the Oracle Advanced Security FIPS-140 evaluation. Developers should not, under any circumstances use the DBMS_RANDOM package. The DBMS_RANDOM package generates pseudo-random numbers; as RFC-1750 states, "The use of pseudo-random processes to generate secret quantities can result in pseudo-security."
If the key is to be passed by the application to the database, then it must be encrypted. Otherwise, a snooper could grab the key as it is being transmitted. Use of network encryption, such as that provided by Oracle Advanced Security, will protect all data in transit from modification or interception, including cryptographic keys.
Key storage is one of the most important, yet difficult, aspects of encryption. To recover data encrypted with a symmetric key, the key must be accessible to the application or user seeking to decrypt the data. The key needs to be easy enough to retrieve that users can access encrypted data, without significant performance degradation. The key needs to be secure enough not to be easily recoverable by someone who is maliciously trying to access encrypted data which he is not supposed to see.
The three basic options available to a developer are:
Storing the keys in the database cannot always provide "bullet-proof" security if you are trying to protect against the DBA accessing encrypted data. This is because an all-privileged DBA could access tables containing encryption keys. However, it can often provide quite good security against the casual snooper or against someone compromising the database file on the operating system.
As a trivial example, suppose you create a table (
EMP) that contains employee data. You want to encrypt each employee's Social Security number (one of the columns). You could encrypt each employee's SSN using a key which is stored in a separate column. However, anyone with
SELECT access on the entire table could retrieve the encryption key and decrypt the matching SSN.
While this encryption scheme seems easily defeatable, with a little more effort you can create a solution that is much harder to break. For example, you could encrypt the SSN using a technique that performs some additional data transformation on the
employee_number before using it to encrypt the SSN. This technique might be something as simple, for example, as XORing the
employee_number with the birthdate of the employee.
As additional protection, a PL/SQL package body performing encryption can be "wrapped," (using the WRAP utility) which obfuscates the code. A developer could wrap a package body called
KEYMANAGE as follows:
A developer can subsequently have a function in the package call the
DBMS_OBFUSCATION_TOOLKIT with the key contained in the wrapped package.
While wrapping is not unbreakable, it makes it harder for a snooper to get the key. Because literals are still readable within the package file, the key could be split up in the package and then have the procedure to re-assemble it prior to use. Even in cases where a different key is supplied for each encrypted data value, so that the value of the key is not embedded within a package, wrapping the package that performs key management (that is, data transformation or padding) is recommended.
Oracle9i Supplied PL/SQL Packages and Types Reference for additional information about the WRAP utility
An alternative would be to have a separate table in which to store the encryption key and to envelope the call to the keys table with a procedure. The key table can be joined to the data table using a primary key to foreign key relationship; for example,
EMPLOYEE_NUMBER is the primary key in the
EMPLOYEES table which stores employee information, and the encrypted SSN.
EMPLOYEE_NUMBER is a foreign key to the
SSN_KEYS table which stores the encryption keys for each employee's SSN. The key stored in the
SSN_KEYS table can also be transformed before use (i.e. through XORing), so the key itself is not stored un-encrypted. The procedure itself should be wrapped, to hide the way in which keys are transformed before use.
The strengths of this approach are:
SELECTaccess to both the data table and the keys table does not guarantee that the user with this access can decrypt the data, because the key is transformed before use.
The weakness in this approach is that a user who has
SELECT access to both the key table and the data table, who can derive the key transformation algorithm, can break the encryption scheme.
The above approach is not bullet-proof, but it is good enough to protect against easy retrieval of sensitive information (such as credit card numbers) stored in clear text.
Storing keys in the operating system (in a flat file) is another option. Oracle9i allows you to make callouts from PL/SQL, which you could use to retrieve encryption keys. However, if you store keys in the operating system and make callouts to it, then your data is only as secure as the protection on the operating system. If your primary security concern driving you to encrypt data stored in the database is that the database can be broken into from the operating system, then storing the keys in the operating system arguably makes it easier for a hacker to retrieve encrypted data than storing the keys in the database itself.
Having the user supply the key assumes the user will be responsible with the key. Considering that 40% of help desk calls are from users who have forgotten their passwords, you can see the risks of having users manage encryption keys. In all likelihood, users will either forget an encryption key, or write the key down, which then creates a security weakness. If a user forgets an encryption key or leaves the company, then your data is unrecoverable.
If you do elect to have user-supplied or user-managed keys, then you need to make sure you are using network encryption so the key is not passed from client to server in the clear. You also must develop key archive mechanisms, which is also a difficult security problem. Key archives or "backdoors" create the security weaknesses that encryption is attempting to address in the first place.
Prudent security practice dictates that you periodically change encryption keys. For stored data, this requires periodically un-encrypting the data, and re-encrypting it with another well-chosen key. This would likely have to be done while the data is not being accessed, which creates another challenge. This is especially true for a Web-based application encrypting credit card numbers, since you do not want to bring the entire application down while you switch encryption keys.
Certain datatypes require more work to encrypt. For example, Oracle supports storage of binary large objects (BLOBs), which lets users store very large objects (e.g. gigabytes) in the database. A BLOB can be either stored internally as a column, or stored in an external file. To use the DBMS_OBFUSCATION_TOOLKIT, the user would have to split the data into 32767 character chunks (the maximum that PL/SQL allows) and then would have to encrypt the chunk and append it to the BLOB. To decrypt, the same procedure would have to be followed in reverse.
Following is a sample PL/SQL program to encrypt data. It shows test string data encryption and decryption. The interface for encrypting raw data is similar.
DECLARE input_string VARCHAR2(16) := 'tigertigertigert'; key_string VARCHAR2(8) := 'scottsco'; encrypted_string VARCHAR2(2048); decrypted_string VARCHAR2(2048); error_in_input_buffer_length EXCEPTION; PRAGMA EXCEPTION_INIT(error_in_input_buffer_length, -28232); INPUT_BUFFER_LENGTH_ERR_MSG VARCHAR2(100) := '*** DES INPUT BUFFER NOT A MULTIPLE OF 8 BYTES ***'; BEGIN dbms_output.put_line('> ========= BEGIN TEST ========='); dbms_output.put_line('> Input String : ' || input_string); BEGIN dbms_obfuscation_toolkit. input_string => input_string, key_string => key_string, encrypted_string => encrypted_string ); dbms_output.put_line('> encrypted string : ' || encrypted_string); dbms_obfuscation_toolkit.DESDecrypt(input_string => encrypted_string, key => raw_key, decrypted_string => decrypted_string); dbms_output.put_line('> Decrypted output : ' || decrypted_string); dbms_output.put_line('> '); if input_string = decrypted_string THEN dbms_output.put_line('> DES Encryption and Decryption successful'); END if; EXCEPTION WHEN error_in_input_buffer_length THEN dbms_output.put_line('> ' || INPUT_BUFFER_LENGTH_ERR_MSG); END;