在Oracle10g之前,Oracle虽然提供了类似帐号认证,授权以及审计等机制来保证数据库中的数据安全性,但是这些机制都是Oracle运行状态下提供的。
对于最终保存在数据文件中的数据,基本上等于是明文保存的,虽然不同的数据类型在存储到数据文件中的格式有区别,但实际上这些存储格式已经广为人知,也有一些工具能够直接从数据文件中读取数据,比如官方的DUL和网友d.c.b.a开发的AUL等。
一、什么是TDE
10gR2引入的透明数据加密(TDE)特性,答应在不影响应用的情况下,加密最终存储到数据文件中的数据,以防止未经授权的直接读取数据文件获得数据的行为。为防止未经授权的解密访问,TDE将加密密钥存储在数据库外部.
TDE答应对列中的数据存储进行加密处理,并且不需要由最终用户或者应用来治理或者使用密钥来获得解密数据。
TDE特性属于Advanced Security组件。
目前,TDE还不支持以下特性:
B*Tree索引之外的其他索引类型
索引范围扫描
大对象如BLOB和CLOB
imp/eXP工具(但是支持impdp/expdp)
使用其他直接读取数据文件的工具如DUL/AUL
在不能使用TDE的时候,可以考虑使用DBMS_CRYPTO包替代,该包能实现数据的加密后存放,但不能对应用透明,应用在查询加密数据前必须显式解密。
需要注重的是,加密一个已经存在数据的表中的列,会导致全表更新,对于大表进行该操作前需严格的规划和测试。
二、TDE的工作机制
TDE是一种基于密钥的访问控制方式。数据以某种密钥加密存储,在访问时,假如没有解密密钥,则无法获得需要的数据。访问时的解密是自动进行的,对于应用程序完全透明。
当一个表中的一个或者多个列被加密时,需要为这个表分配一个密钥(一个表只需要一个密钥)。系统中所有的密钥在经过服务器中的一个主密钥加密后存储在数据字典中,也就是说,密钥本身也是加密存储的。
而服务器主密钥则存储在数据库外部,使用外部安全机制来保证主密钥的安全控制。这个外部安全机制就是oracle提供的wallet机制。
三、如何使用TDE
要使用透明数据加密特性,用户需要有alter system系统权限,并且拥有有效的oracle wallet密码。假如还没有wallet存在,则下面的SQL语句创建一个,其密码就是指定的passWord:
alter system set encryption key identitified by password
执行该语句之前,必须保证$ORACLE_HOME/admin/$ORACLE_SID下已经有名叫wallet的目录,否则将出现错误:
NING@ning>alter system set encryption key identified by test;
alter system set encryption key identified by test
*
ERROR at line 1:
ORA-28368: cannot auto-create wallet
以上路径是默认的wallet存放路径,也可以通过在sqlnet.ora文件中设置如下属性更改wallet的路径:
ENCRYPTION_WALLET_LOCATION=
(SOURCE=(METHOD=FILE)(METHOD_DATA=
(DirectorY=D:wallet)))
该语句执行后,会打开已经存在的wallet或者新生成一个wallet并打开然后创建主密钥执行成功后就可以创建包含加密列的table了
SYS@ning>create table test(id int, name varchar2(100) encrypt);
create table test(id int, name varchar2(100) encrypt)
*
ERROR at line 1:
ORA-28336: cannot encrypt SYS owned objects
可以看到,sys的对象不能使用加密列
SYS@ning>conn ning/ning
Connected.
NING@ning>create table test(id int, name varchar2(100) encrypt);
Table created.
这样,就创建了一个table,要害字encrypt表示其第二个列为加密列。
NING@ning>insert into test values(1,'a');
1 row created.
NING@ning>select * from test;
ID NAME
---------- ----------------------------------------
1 a 对于应用来说,加密列和普通列没有什么区别。dump出数据的实际存储看看
NING@ning>select dbms_rowid.rowid_relative_fno(rowid) fno,
2 dbms_rowid.rowid_block_number(rowid) block#
3 from test;
FNO BLOCK#
---------- ----------
5 34
NING@ning>alter system dump datafile 5 block 34;
System altered.
找到对应的trace文件:
data_block_dump,data header at 0x7e25064
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x07e25064
bdba: 0x01400022
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f5d
avsp=0x1f49
tosp=0x1f49
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f5d
block_row_dump:
tab 0, row 0, @0x1f5d
tl: 59 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [52]
27 8f d5 a5 79 8b cc 69 d1 3f f7 0e ea f7 30 d5 76 28 80 5f ce b1 1c 7d e8
34 10 6a 97 1b 41 e6 9f 48 58 bd 16 b9 ed 2f ef 81 52 35 cf 89 2e 72 12 82
fe 74
end_of_block_dump
可以发现col 1的数据不像没有加密过的数据那样保存了'a'的ASCII值,而是加密后的一长串
的值。我们可以看一个没有加密的同样的表的dump结果:
data_block_dump,data header at 0x7e25064
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x07e25064
bdba: 0x010000ef
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f90
avsp=0x1f7b
tosp=0x1f7b
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f90
block_row_dump:
tab 0, row 0, @0x1f90
tl: 8 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 61
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 239 maxblk 239
col 1的长度由普通表的1字节变成了加密表中的52字节,那么对于加密表,可能需要更多的存储空间,这样,在安全性和性能之间,就需要做一个权衡了。
对于已经存在的普通表,也可以将其中的某些列加密:
alter table table_name modiry (column_name column_type encrypt);
也可以将已经加密的列修改成不加密的状态:
alter table table_name modiry (column_name column_type decrypt);
除了encrypt,加密列还有另外一个属性salt,默认情况下是salt,可以修改成no salt
alter table table_name modiry (column_name column_type encrypt no salt);
只有no salt的加密列上才能创建索引
NING@ning>create index ix_test on test(name);
create index ix_test on test(name)
*
ERROR at line 1:
ORA-28338: cannot encrypt indexed column(s) with salt
NING@ning>alter table test modify(name varchar2(100) encrypt no salt);
Table altered.
NING@ning>create index ix_test on test(name);
Index created. 四、治理TDE
TDE运行期间,必须保证wallet处于open状态,假如wallet被关闭,则加密的数据列将无法访问
NING@ning>alter system set wallet close;
System altered.
NING@ning>select * from test;
select * from test
*
ERROR at line 1:
ORA-28365: wallet is not open
NING@ning>alter system set wallet open;
alter system set wallet open
*
ERROR at line 1:
ORA-28356: invalid open wallet syntax
NING@ning>alter system set wallet open identified by test1;
alter system set wallet open identified by test1
*
ERROR at line 1:
ORA-28353: failed to open wallet
NING@ning>alter system set wallet open identified by test;
System altered.
NING@ning>alter system set wallet open identified by test;
alter system set wallet open identified by test
*
ERROR at line 1:
ORA-28354: wallet already open
NING@ning>select * from test;
ID NAME
---------- ----------------------------------------
1 a
默认情况下,数据库关闭后wallet也会关闭,但是数据库重启启动后wallet不会自动open,需要手动open后才可以访问加密数据。
可以在Oracle wallet manager图形治理工具中设置wallet随数据库启动后自动启动(Auto Login Wallet)
注重wallet目录下的文件不能丢失,否则将导致加密的数据无法访问
NING@ning>select * from test;
select * from test
*
ERROR at line 1:
ORA-28362: master key not found
假如我们需要重设主密钥,那么就要先将加密数据解密存储,重新生成主密钥,再将已经解密
的数据重新加密。
对于加密的列,我们可以重新修改加密使用的算法:
NING@ning>alter table test rekey using 'AES192';
Table altered.
NING@ning>alter table test rekey using '3DES168';
Table altered.
五、相关视图
v$wallet
dba_encrypted_columns
all_encrypted_columns
user_encrypted_columns
参考文章:
Oracle? Database Advanced Security Administrator's Guide