Transparent Data Encryption以下简称TDE。
称为透明是因为加密工作在SQL层以下,由数据库引擎自动进行。
TDE是第三代加密,10gR2时引入。之前两代为DBMS_OBFUSCATION_TOOLKIT和DBMS_CRYPTO。
TDE最大的好处是不用改应用。
cryptography - 密码学
加密的目的是保护在不安全媒介上传输的敏感信息。
数据库安全与网络安全很不同。不过在透明上是相同的,即网络使用SSL和TLS。
加密将明文转换为不可辨识的形式。解密反之。研究此两过程称为密码学。
参考书籍《Applied Cryptography: Protocols, Algorithms, and Source Code in C》
自己写加解密算法是不明智的,应选择标准的,经验证的算法。
加密数据需要算法和加密key,加密的强调取决于两者组合。算法使用加密key加密数据。
由于算法是公开的,因此唯一需要保密的是加密key。
两类加密算法:对称和非对称(PKE或Public Key Encryption)。 对称算法包括DES,3DES,AES,TLS等,由于效率高,通常用于加密大批量数据。TLS是网络加密的标准。
PKE中的两个key称为公钥和私钥。私钥加密的数据可以用公钥解密,反之亦然。PKE解决了密钥发布的问题。
私钥也解决了认证的问题。
在对称加密中,PKE可用来加密加密key。
为效率计,数据库加密也使用对称加密,不够需要解决密钥管理的问题。
加密的第一需求来自合规性,如PCI DSS。第二需求来自生命周期管理,如备份,复制等。
防止DBA看到敏感数据需要DBV。
在TDE之前,磁盘上的数据是明码存放。
如果有OS权限,以下命令可以看到明码数据:
strings *.dbf | grep pattern
更换磁盘是必须完全擦除数据,如shred。
文件系统加密是blanket approach(整体的方法),即加密所有,但比较昂贵(耗资源)。
应用加密如DBMS_CRYPTO则需要改应用。
TDE是声明式的,支持所有原生数据库功能。
TDE直接,简单。
以下数据加密key称为DEK,加密DEK的密钥称为MEK(master key或master encryption key)。
在12c中,所有PDB共享一个key store,但每一个PDB可以有自己的MEK和DEK。
实际上,在19c中,PDB可以指定自己的key store,这成为isolated mode,而传统的方式称为united mode, 详见https://docs.oracle.com/en/database/oracle/oracle-database/19/asoag/managing-keystores-encryption-keys-in-isolated-mode.html#GUID-1637E45A-36BA-4BC8-B9E3-581515A9AA1C。
本文只讨论unitied mode。
MEK存放在keystore中,有3种保护方法:
TDE可以于HSM(hardware security modules)结合。
在创建key store前,必须先建立wallet目录,如果是RAC建议创建在共享的ASM中:
$ mkdir $ORACLE_BASE/admin/ORCLCDB/wallet
然后指定wallet目录,编辑文件$ORACLE_HOME/network/admin/sqlnet.ora
:
ENRYPTION_WALLET_LOCATION =(SOURCE=(METHOD=file) (METHOD_DATA=(DIRECTORY=/opt/oracle/admin/ORCLCDB/wallet)))
最后重启数据库。
12c中有专门的SYSKM权限,PDB中可使用ADMINISTER KEY MANAGEMENT权限。
connect / as sysdba
alter session set container=sales;
grant create session to sec_mgr identified by welcome1;
create role sec_mgr_role;
GRANT administer key management TO sec_mgr_role;
GRANT SELECT ON gv_$encryption_wallet TO sec_mgr_role;
GRANT SELECT ON gv_$encryption_keys TO sec_mgr_role;
GRANT SELECT ON gv_$encrypted_tablespaces TO sec_mgr_role;
grant sec_mgr_role to sec_mgr;
首先要在CDB中设置:
connect / as syskm
-- 口令保护的key store
ADMINISTER KEY MANAGEMENT
CREATE KEYSTORE '/opt/oracle/admin/ORCLCDB/wallet'
IDENTIFIED BY welcome1;
然后在目录下可看到新文件,p12后缀是因其遵循PKCS #12标准:
$ ll /opt/oracle/admin/ORCLCDB/wallet
total 4
-rw-------. 1 oracle oinstall 2555 Aug 26 23:13 ewallet.p12
以下命令创建自动登录的key store,也就是不需要口令,这是不安全的,生产环境不建议使用:
ADMINISTER KEY MANAGEMENT
CREATE LOCAL AUTO_LOGIN KEYSTORE
FROM KEYSTORE '/opt/oracle/admin/ORCLCDB/wallet'
IDENTIFIED BY welcome1;
我们可以看到多了sso文件:
$ ll /opt/oracle/admin/ORCLCDB/wallet
total 8
-rw-------. 1 oracle oinstall 2600 Aug 26 23:17 cwallet.sso
-rw-------. 1 oracle oinstall 2555 Aug 26 23:13 ewallet.p12
目前的状态是:
column wrl_parameter format a35
column wallet_type format a20
column status format a19
SELECT wrl_parameter, wallet_type, status
FROM sys.gv_$encryption_wallet;
WRL_PARAMETER WALLET_TYPE STATUS
----------------------------------- -------------------- -------------------
/opt/oracle/admin/ORCLCDB/wallet LOCAL_AUTOLOGIN OPEN_NO_MASTER_KEY
在PDB中查询结果:
WRL_PARAMETER WALLET_TYPE STATUS
----------------------------------- -------------------- -------------------
LOCAL_AUTOLOGIN OPEN_NO_MASTER_KEY
escrow - 代管,托管。
注意, Keystore一旦创建就不应该删除,因此也没有删除命令
如何将自动登录的key store更改为口令保护的key store? 可参考How to convert Local Autologin/Autologin Keystore to Password based Keystore (Doc ID 2061244.1)
:
SQL> ADMINISTER KEY MANAGEMENT SET KEYSTORE CLOSE;
keystore altered.
SQL> SELECT wrl_parameter, wallet_type, status FROM sys.gv_$encryption_wallet;
WRL_PARAMETER WALLET_TYPE STATUS
----------------------------------- -------------------- -------------------
/opt/oracle/admin/ORCLCDB/wallet UNKNOWN CLOSED
UNKNOWN CLOSED
UNKNOWN CLOSED
UNKNOWN CLOSED
SQL> ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY welcome1;
keystore altered.
SQL> SELECT wrl_parameter, wallet_type, status FROM sys.gv_$encryption_wallet;
WRL_PARAMETER WALLET_TYPE STATUS
----------------------------------- -------------------- -------------------
/opt/oracle/admin/ORCLCDB/wallet PASSWORD OPEN_NO_MASTER_KEY
UNKNOWN CLOSED
UNKNOWN CLOSED
UNKNOWN CLOSED
好了,现在可以用以下命令来打开和关闭key store:
ADMINISTER KEY MANAGEMENT SET KEYSTORE CLOSE IDENTIFIED BY welcome1 CONTAINER = ALL;
ADMINISTER KEY MANAGEMENT SET KEYSTORE OPEN IDENTIFIED BY welcome1 CONTAINER = ALL;
下面开始创建MEK。首先必须设置CDB中的MEK, 否则直接在PDB中创建会报错:
SQL> administer key management use key 'AcR7hDRNxk/fv05JQML4YLcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' identified by "welcome1" with backup;
administer key management use key 'AcR7hDRNxk/fv05JQML4YLcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' identified by "welcome1" with backup
*
ERROR at line 1:
ORA-46671: master key not set in root container
CDB中的过程如下:
connect / as sysdba
ADMINISTER KEY MANAGEMENT
CREATE KEY
USING TAG 'root'
IDENTIFIED BY welcome1
WITH BACKUP
;
SQL> SELECT tag,key_id FROM v$encryption_keys;
TAG KEY_ID
---------- ------------------------------------------------------------------------------
root AQKj4ziKK0/3vz9xxCSOOxcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
administer key management use key 'AQKj4ziKK0/3vz9xxCSOOxcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' identified by "welcome1" with backup;
以上的CREATE和USE可以直接用SET一步替代:
administer key management set key identified by "welcome1" with backup;
此时, CDB和PDB$SEED的key stor状态为OPEN, 表示其中有MEK了:
SQL> SELECT con_id, wrl_parameter, wallet_type, status FROM sys.gv_$encryption_wallet;
CON_ID WRL_PARAMETER WALLET_TYPE STATUS
---------- ----------------------------------- -------------------- -------------------
1 /opt/oracle/admin/ORCLCDB/wallet PASSWORD OPEN
2 PASSWORD OPEN
3 PASSWORD OPEN_NO_MASTER_KEY
4 PASSWORD OPEN_NO_MASTER_KEY
接下来在某PDB中创建2个MEK:
alter session set container=sales;
ADMINISTER KEY MANAGEMENT
CREATE KEY
USING TAG 'sales1'
IDENTIFIED BY welcome1
WITH BACKUP USING 'root_create'
;
ADMINISTER KEY MANAGEMENT
CREATE KEY
USING TAG 'sales2'
IDENTIFIED BY welcome1
WITH BACKUP USING 'sales_create'
;
SELECT tag,creator,key_use
,to_char(creation_time,'DD-MON-YYYY HH24:MI:SS') creation_time
FROM sys.gv_$encryption_keys;
TAG CREATOR KEY_USE CREATION_TIME
---------- ---------- ---------- -----------------------------
sales1 SYS TDE IN PDB 27-AUG-2020 02:58:27
sales2 SYS TDE IN PDB 27-AUG-2020 03:06:27
root SYS TDE IN PDB 27-AUG-2020 03:29:15
以上语句中的WITH BACKUP
会备份key store。
我们在pdb中创建了两个MEK,现在需要激活一个:
SQL> SELECT tag,key_id FROM v$encryption_keys;
TAG KEY_ID
---------- ------------------------------------------------------------------------------
root AQKj4ziKK0/3vz9xxCSOOxcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
sales AcR7hDRNxk/fv05JQML4YLcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
root AZbgQL5oLU80vwZ6ZxGzp0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
SQL> SELECT wrl_parameter, wallet_type, status FROM sys.gv_$encryption_wallet;
WRL_PARAMETER WALLET_TYPE STATUS
----------------------------------- -------------------- -------------------
PASSWORD OPEN_NO_MASTER_KEY
SQL> administer key management use key 'AcR7hDRNxk/fv05JQML4YLcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' identified by "welcome1" with backup;
keystore altered.
SQL> SELECT wrl_parameter, wallet_type, status FROM sys.gv_$encryption_wallet;
WRL_PARAMETER WALLET_TYPE STATUS
----------------------------------- -------------------- -------------------
PASSWORD OPEN
administer key management use key 'AcR7hDRNxk/fv05JQML4YLcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' identified by "welcome1" with backup;
通过con_id, 我们可以知道每个PDB使用的MEK:
SQL> SELECT con_id, key_id FROM v$encryption_keys;
CON_ID KEY_ID
---------- ------------------------------------------------------------------------------
1 AQKj4ziKK0/3vz9xxCSOOxcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
4 AcR7hDRNxk/fv05JQML4YLcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
0 AZbgQL5oLU80vwZ6ZxGzp0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
也可以通过最近激活时间来判断:
SQL> show con_id
CON_ID
------------------------------
4
SELECT KEY_ID
FROM V$ENCRYPTION_KEYS
WHERE ACTIVATION_TIME = (SELECT MAX(ACTIVATION_TIME)
FROM V$ENCRYPTION_KEYS
5 WHERE ACTIVATING_DBID = (SELECT DBID FROM V$DATABASE));
KEY_ID
------------------------------------------------------------------------------
AcR7hDRNxk/fv05JQML4YLcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
由于所有PDB共享key store,而MEK存于key store,因此你创建的MEK可以为所有PDB使用。
列加密的最简形式:
create table foo(a int, b varchar(2) encrypt);
复杂一点的:
create table bar(a int, b varchar(2) encrypt using 'AES192' 'SHA-1' SALT);
其中AES192为加密算法。SHA-1为MAC(message authentication code)算法,需要额外的20字节。SALT会在数据后附加16随机字节,这样相同的数据可加密结果不同。
COL OWNER format a10
COL TABLE_NAME format a15
COL COLUMN_NAME format a15
COL ENCRYPTION_ALG format a18
COL SALT format a5
SELECT owner, table_name, column_name
, encryption_alg, salt
FROM dba_encrypted_columns;
OWNER TABLE_NAME COLUMN_NAME ENCRYPTION_ALG SALT
---------- --------------- --------------- ------------------ -----
HR FOO B AES 192 bits key YES
每个表使用不同的DEK,而且是对称key。然后DEK使用MEK加密,这种两级方式使得MEK的rekey非常简单。
已有表的加密:
create table foo(a int, b varchar(2));
alter table foo modify (b encrypt);
由于加密会增加字节,可能会导致性能问题。因此建议对表做reorg。
手工的方法是通过impdp和expdp做导出导入。
自动的方法是通过online redefinition。可参考这里
列加密工作在SQL层:
TDE column encryption is performed at the SQL layer. Oracle Database utilities that bypass the SQL layer cannot use TDE column encryption services.
列加密的限制参见Restrictions on Using TDE Column Encryption
推荐表空间加密,它没有任何限制。
CREATE TABLESPACE sales_encrypt
DATAFILE 'sales_encrypt.dbf' SIZE 50M
ENCRYPTION USING 'AES256'
DEFAULT STORAGE (ENCRYPT);
Tablespace created.
SELECT ts.name, et.encryptedts, et.encryptionalg
FROM v$tablespace ts, v$encrypted_tablespaces et
WHERE ts.ts# = et.ts#;
NAME ENC ENCRYPT
------------------------------ --- -------
SALES_ENCRYPT YES AES256
然后可以将已有的表迁移到加密表空间:
SQL> create table t1(a int);
Table created.
SQL> alter table t1 move tablespace sales_encrypt;
Table altered.
加密已有的表空间:
SQL> CREATE TABLESPACE noencrypt datafile 'noencrypt.dbf' size 10M;
Tablespace created.
SQL> ALTER TABLESPACE noencrypt ENCRYPTION ONLINE USING 'AES192' ENCRYPT;
Tablespace altered.
可参考这里
当数据需要移动时,TDE需要和其它工具配合使用,如OGG,Data Pump, ADG,详见Oracle Database Advanced Security Guide。
性能视情况而定,总之建议用表空间加密。如果用列加密,需要注意不要用在逐渐,主外键约束等。
另外可考虑硬件加速,参见:How To Benefit From Hardware Acceleration for Tablespace Encryption? (Doc ID 1365021.1)。
Oracle数据库支持FIPS 140-2,设置参见How To Setup Federal Information Processing Standard (FIPS) standard for 140-2 Using FIPS.ORA On Single Instance and On RAC ( Real Application Cluster) (Doc ID 2250070.1)。
SQL> show parameter fips;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
DBFIPS_140 boolean FALSE
可用于网络数据,静态数据的加密,以及DBMS_CRYPTO package。