表空间加密的功能在金融行业或者对数据比较敏感的单位需要用到,可以阻止通过在OS层面读取表空间文件。
oracle 10G中,可以通过DBMS_CRYPTO 和 DBMS_OBFUSCATION_TOOLKIT 工具包允许您构建自己的加密框架。然而,性能仍然是该特性的一个问题,索引范围扫描不能应用于加密列,这会对性能造成严重的负面影响。
这正是 Oracle Database 11g 中透明表空间加密的真正出色之处。当表空间声明已加密时,表空间(包括透明表空间、备份等)上的任何数据都已加密,而不仅仅是单独声明为已加密的表。但在进行索引扫描时,扫描发生在未对数据进行加密的内存中,因而不会对性能造成影响。
为了使用透明数据加密,首先指定一个wallet路径并且设置一个秘钥,步骤如下:
1. 在sqlnet.ora文件中指定一个wallet路径
2. 创建主秘钥
3. 开启wallet
4. 创建表空间
具体步骤如下:
1.准备wallet路径:
[oracle@qht131 admin]$ cat /u01/app/oracle/product/11203/network/admin/sqlnet.ora
SQLNET.INBOUND_CONNECT_TIMEOUT=0
ENCRYPTION_WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(directory=/u01/app/oracle/admin/wallet)))
[oracle@qht131 admin]$ mkdir -p /u01/app/oracle/admin/wallet
2.创建加密密钥
SQL> ALTER SYSTEM SET ENCRYPTION KEY IDENTIFIED BY "oracle";
System altered.
该语句同时创建钱夹和密钥。如果您现在检查该目录,会看到刚刚创建的钱夹文件 (ewallet.p12)。
[oracle@qht131 wallet]$ cd /u01/app/oracle/admin/wallet
[oracle@qht131 wallet]$ ls
ewallet.p12
该文件就是密码本,如果丢失了或者损坏了密码本,加密后的数据就无法解密了,所以注意保护好该文件。
v$encryption_wallet视图就有了这个钱夹以及状态的信息
SQL> select * from v$encryption_wallet;
WRL_TYPE
--------------------
WRL_PARAMETER
--------------------------------------------------------------------------------
STATUS
------------------
file
/u01/app/oracle/admin/wallet
OPEN
3.当数据库关闭时wallet也会随之关闭。在这一步手工开启wallet。(不过目前不需要手动打开,因为现在已在打开状态。)
ALTER SYSTEM SET ENCRYPTION WALLET OPEN IDENTIFIED BY "oracle";
4.创建表空间:
SQL> create tablespace secure1
2 datafile '/u01/oradata/orcl/secure1_01.dbf'
3 size 10M
4 encryption using 'AES128'
5 default storage (encrypt) ;
Tablespace created.
子句“encryption using ... default storage (encrypt)”将表空间标记为经过加密的。(注意:我们对此表空间使用了 AES 128 位加密算法。其他选择包括 Triple DES 168 位密钥算法、AES 192 位密钥算法和 AES 256 位密钥算法。)
5.创建表
SQL> create table secure_trans
2 tablespace secure1
3 as select * from l5m.access_detail;
Table created.
SQL> create table secure_res
2 tablespace secure1
3 as select * from l5m.access_detail;
Table created.
6.为了体现和比较出加密表空间和正常表空间的区别,这里建立一个普通 的表空间insecure1,以及相应的表insecure_trans,insecure_res。
SQL> create tablespace insecure1
2 datafile '/u01/oradata/orcl/insecure1_01.dbf'
3 size 10m;
Tablespace created.
SQL> create table insecure_trans
2 tablespace insecure1
3 as select * from l5m.access_detail;
Table created.
SQL> create table insecure_res
2 tablespace insecure1
3 as select * from l5m.access_detail;
Table created.
7.现在更新这些表中的一个文本字段,以便在数据文件中搜索该字段:
SQL> update secure_trans set COMPANY_NAME='Transaction Comments' where company_id=6000;
132 rows updated.
SQL> update insecure_trans set COMPANY_NAME='Transaction Comments' where company_id=6000;
132 rows updated.
SQL> commit;
Commit complete.
8.通过使表空间先脱机再联机,将内容强制写到磁盘上:
alter tablespace secure1 offline;
alter tablespace secure1 online;
alter tablespace insecure1 offline;
alter tablespace insecure1 online;
9.此时,缓存中的数据已经写到磁盘上。搜索该字段,看会发生什么?
[oracle@qht131 orcl]$ strings insecure1_01.dbf | grep Transaction
Transaction Comments
Transaction Comments,
Transaction Comments,
Transaction Comments,
Transaction Comments,
Transaction Comments,
Transaction Comments,
Transaction Comments,
Transaction Comments,
[oracle@qht131 orcl]$ strings secure1_01.dbf | grep Transaction
strings加密的数据文件不会返回任何结果,因为数据文件是加密的,无法以明文形式看到各列的值。
下面再看一下性能方面,加密和普通的表空间的数据是否有区别。
SQL> select t.USER_ID,sum(t.COMPANY_ID) from
2 secure_trans t, secure_res r
3 where t.USER_ID = r.USER_ID
4 group by t.USER_ID;
44 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 4166055186
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1833 | 71487 | 9 (23)| 00:00:01 |
| 1 | HASH GROUP BY | | 1833 | 71487 | 9 (23)| 00:00:01 |
|* 2 | HASH JOIN | | 1833 | 71487 | 8 (13)| 00:00:01 |
| 3 | TABLE ACCESS FULL| SECURE_RES | 284 | 3692 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| SECURE_TRANS | 284 | 7384 | 4 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."USER_ID"="R"."USER_ID")
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
0 physical reads
0 redo size
1535 bytes sent via SQL*Net to client
545 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
44 rows processed
SQL> select t.USER_ID,sum(t.COMPANY_ID) from
2 insecure_trans t, insecure_res r
3 where t.USER_ID = r.USER_ID
4 group by t.USER_ID;
44 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3576531316
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1833 | 71487 | 9 (23)| 00:00:01 |
| 1 | HASH GROUP BY | | 1833 | 71487 | 9 (23)| 00:00:01 |
|* 2 | HASH JOIN | | 1833 | 71487 | 8 (13)| 00:00:01 |
| 3 | TABLE ACCESS FULL| INSECURE_RES | 284 | 3692 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| INSECURE_TRANS | 284 | 7384 | 4 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."USER_ID"="R"."USER_ID")
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
0 physical reads
0 redo size
1535 bytes sent via SQL*Net to client
545 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
44 rows processed
现在,对 INSECURE_RES 和 INSECURE_TEST 运行相同的测试,它们的执行计划以及statistics是一致的。因此,表空间加密不会对性能产生影响。
DBA_TABLESPACES 视图有一个新列 ENCRYPTED,用于显示某个表空间是否已加密。此外,一个名为 V$ ENCRYPTED_TABLESPACES 的新视图用于显示针对该表空间启用的加密类型。
SQL> select tablespace_name,ENCRYPTED from DBA_TABLESPACES;
TABLESPACE_NAME ENC
------------------------------ ---
SYSTEM NO
SYSAUX NO
UNDOTBS1 NO
TEMP NO
USERS NO
SECURE1 YES
INSECURE1 NO
7 rows selected.
SQL> desc v$encrypted_tablespaces;
Name Null? Type
----------------------------------------- -------- ----------------------------
TS# NUMBER
ENCRYPTIONALG VARCHAR2(7)
ENCRYPTEDTS VARCHAR2(3)
ENCRYTPEDKEY RAW(32)
MASTERKEYID RAW(16)
BLOCKS_ENCRYPTED NUMBER
BLOCKS_DECRYPTED NUMBER
该视图可以和 V$TABLESPACE 视图的 TS# 列结合,以获得完整的信息。下面是该视图的外观:
SQL> desc v$tablespace;
Name Null? Type
----------------------------------------- -------- ----------------------------
TS# NUMBER
NAME VARCHAR2(30)
INCLUDED_IN_DATABASE_BACKUP VARCHAR2(3)
BIGFILE VARCHAR2(3)
FLASHBACK_ON VARCHAR2(3)
ENCRYPT_IN_BACKUP VARCHAR2(3)
注意,ENCRYPT_IN_BACKUP 列和透明表空间加密没有任何关系。相反,它是备份期间表空间的 RMAN 加密,是在 Oracle Database 10g 第 2 版中引入的。
SQL> select TS#,ENCRYPTIONALG from v$encrypted_tablespaces;
TS# ENCRYPT
---------- -------
6 AES128
SQL> SELECT b.NAME tablespace_name, a.encryptedts, a.encryptionalg
2 FROM v$encrypted_tablespaces a, v$tablespace b
3 WHERE a.ts# = b.ts#
4 /
TABLESPACE_NAME ENC ENCRYPT
------------------------------ --- -------
SECURE1 YES AES128