91
Oracle 9i/10g/11g 透明数据加密 (Transparent Data Encryption) 赵元杰 整理 北京群环域科技有限公司 2012.2

3.oracle 11g 透明数据加密(91 页)

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: 3.oracle 11g 透明数据加密(91 页)

Oracle 9i/10g/11g

透明数据加密 (Transparent Data Encryption)

赵元杰 整理

北京群环域科技有限公司

2012.2

Page 2: 3.oracle 11g 透明数据加密(91 页)

2/91

内容提要

♠ Oracle 9i 数据加密技术

♠ Oracle10g TDE 技术

♠ 使用Oracle10g TDE 加密表

♠ 使用Oracle10g TDE 内置包

♠ Oracle11g TDE 技术

♠ 附录:样例

♠ 参考资源

Page 3: 3.oracle 11g 透明数据加密(91 页)

3/91

RDBMS 数据加密

♠ 数据加密 : ♠ 加密是一种编码数据的方法,使入侵者难以理解数据内容,在授权

用户使用时,解码数据,使其返回原始格式。一些商业DBMS包含加密模块,还有一些能提供程序,使用户编写自己的加密例程

♠ 数据加密过程 : ♠ 编码数据(称为明文)的加密密钥

♠ 将明文更改为编码文本(称为密文)的加密算法

♠ 解码密文的解码密钥

♠ 将密文转换回原始明文的解密算法

Page 4: 3.oracle 11g 透明数据加密(91 页)

4/91

数据加密技术

♠ 数据加密过程 :

♠ 一般的数据加密过程如下:

明 文

明 文

发送者

接收者

加密密钥

加密算法

解密算法解密密钥

密文

密文

Page 5: 3.oracle 11g 透明数据加密(91 页)

5/91

数据加密技术

♠ 对称加密技术: ♠ 该技术为加密和解密使用相同加密密钥。密钥必须保密,以防范潜

在入侵者。

♠ 该技术依赖于安全通信,以便在数据提供者和授权用户之间交换密钥。若密钥确实安全,则要将密钥作为消息本身的一部分。这么做效率不高,大多数密钥较短。数据加密标准(Data Encryption

standard, 简写DES)是该技术的一个例子

♠ 非对称加密 技术: ♠ 该技术为加密和解密使用不同密钥。一种是公开的公钥,另一种是

只有授权用户知道的私钥。

♠ 加密算法也可以公开。公钥加密(RSA)是一种非对称加密方法。

Page 6: 3.oracle 11g 透明数据加密(91 页)

6/91

数据加密技术-DES

♠ DES数据加密过程 :

♠ DES数据加密过程如下:

明 文

明 文

发送者

接收者

DES

DES

密文

密文

密钥:54269471832

密钥:54269471832

Page 7: 3.oracle 11g 透明数据加密(91 页)

7/91

数据加密技术-DES

♠ DES数据加密原理 : ♠ DES将明文划分为块,每个块64位。用64位密钥来加密各个块。密

钥虽64位长,但有效位仅56位,其余8位用作奇偶校验位。即使56

位密钥,也可能有256种可能的不同密钥

♠ DES数据加密过程 : ♠ 使用密钥为各个块应用初始置换。

♠ 按16个连续复杂替代步骤操作转换或置换块。

♠ 最后应用另一种置换算法,与初始置换相反。

♠ DES数据解密过程 : ♠ 解密算法与加密算法相同,但步骤执行顺序正好相反。

Page 8: 3.oracle 11g 透明数据加密(91 页)

8/91

数据加密技术-RSA

♠ RSA 的由来 :

♠ RSA 是信息安全中一个非常著名的公钥加密算法

♠ 1977 年被发明, 以该算法的三位发明人Ron Rivest、Adi Shamir、LenAdleman 的名字命名

♠ RSA 与产品 :

♠ 该算法是目前IT 系统中应用最为广泛的非对称算法。

♠ 而RSA 亦是美国一家著名的信息安全公司的名字,目前是EMC 旗下的一个分支

Page 9: 3.oracle 11g 透明数据加密(91 页)

9/91

Oracle 9i 数据加密技术

♠ Oracle 9i 支持数据加密 :

♠ 使用DBMS_OBFUSCATION_TOOLKIT内置包

♠ DBMS_OBFUSCATION_TOOLKIT包主要包括: ♠ DESGETKEY -- 产生密钥,用于DES算法

♠ DES3GETKEY -- 产生密钥,用于Triple DES算法

♠ DESENCRYPT -- 用DES算法加密数据

♠ DESDECRYPT -- 用DES算法解密数据

♠ DES3ENCRYPT -- 用Triple DES算法加密数据

♠ DES3DECRYPT -- 用DES算法解密数据

♠ MD5 -- 用MD5算法加密数据

Page 10: 3.oracle 11g 透明数据加密(91 页)

10/91

Oracle 9i 数据加密技术

♠ DBMS_OBFUSCATION_TOOLKIT.MD5加密: ♠ DBMS_OBFUSCATION_TOOLKIT.MD5是MD5编码的数据包函

♠ DBMS_OBFUSCATION_TOOLKIT.MD5返回的字串,是RAW类型,要正确显示,需要经过Utl_Raw.Cast_To_Raw转换

♠ 1、直接调用

declare

v2 varchar2(32);

begin

v2 := Utl_Raw.Cast_To_Raw(sys.dbms_obfuscation_toolkit.md5(input_string =>

'111'));

dbms_output.put_line(v2);

end;

declare

v2 varchar2(32);

begin

v2 := Utl_Raw.Cast_To_Raw(sys.dbms_obfuscation_toolkit.md5(input_string =>

'111'));

dbms_output.put_line(v2);

end;

Page 11: 3.oracle 11g 透明数据加密(91 页)

11/91

Oracle 9i 数据加密技术

♠ DBMS_OBFUSCATION_TOOLKIT.MD5加密: ♠ 注意:可以在存储过程中直接调用,如果要嵌套调用md5时,记

得每次调用后都用Utl_Raw.Cast_To_Raw进行转换,否则最后出来的结果是错误的。

♠ 2、构造函数后,再调用

♠ 调用md5函数示例:select md5(1) from dual

CREATE OR REPLACE FUNCTION MD5(

passwd IN VARCHAR2)

RETURN VARCHAR2

IS

retval varchar2(32);

BEGIN

retval := utl_raw.cast_to_raw(DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING =>

passwd)) ;

RETURN retval;

END;

CREATE OR REPLACE FUNCTION MD5(

passwd IN VARCHAR2)

RETURN VARCHAR2

IS

retval varchar2(32);

BEGIN

retval := utl_raw.cast_to_raw(DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING =>

passwd)) ;

RETURN retval;

END;

Page 12: 3.oracle 11g 透明数据加密(91 页)

12/91

内容提要

♠ Oracle 9i 数据加密技术

♠ Oracle10g 加密包

♠ Oracle10g TDE 加密技术

♠ Oracle10g TDE 内置包

♠ Oracle11g TDE 技术

♠ 附录:样例

♠ 参考资源

Page 13: 3.oracle 11g 透明数据加密(91 页)

13/91

10g 加密工具包

♠ Oracle10g 具有一个简单的加密/解密接口

♠ DBMS_CRYPTO 程序包

♠ DES、3DES、AES 加密

♠ MD5 校验 和 编程密钥管理

♠ 10g 的增强用户接口

♠ 加密 blob 数据类型

♠ 应用程序必须提供密钥生成、管理和恢复功能

♠ 加密密钥必须存储在某处

♠ 可以存储在数据库文件中、操作系统中、磁盘上等等

Page 14: 3.oracle 11g 透明数据加密(91 页)

14/91

Oracle 10g数据加密技术

♠ Oracle 10g支持数据加密 :

♠ 加密存储过程

raw_input RAW(128);

raw_key RAW(128);

encrypted_raw RAW(2048);

-- convert input to raw

encrypted_raw := dbms_crypto.Encrypt(

src => raw_input,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

raw_input RAW(128);

raw_key RAW(128);

encrypted_raw RAW(2048);

-- convert input to raw

encrypted_raw := dbms_crypto.Encrypt(

src => raw_input,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

Page 15: 3.oracle 11g 透明数据加密(91 页)

15/91

Oracle 10g数据加密技术

♠ Oracle 10g支持数据加密 :

♠ 解密存储过程

raw_key RAW(128);

encrypted_raw RAW(2048);

decrypted_raw RAW(2048);

decrypted_raw := dbms_crypto.Decrypt(

src => encrypted_raw,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

raw_key RAW(128);

encrypted_raw RAW(2048);

decrypted_raw RAW(2048);

decrypted_raw := dbms_crypto.Decrypt(

src => encrypted_raw,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

Page 16: 3.oracle 11g 透明数据加密(91 页)

16/91

内容提要

♠ Oracle 9i 数据加密技术

♠ Oracle10g 加密包

♠ Oracle10g TDE 加密技术

♠ Oracle10g TDE 内置包

♠ Oracle11g TDE 技术

♠ 附录:样例

♠ 参考资源

Page 17: 3.oracle 11g 透明数据加密(91 页)

17/91

数据安全与数据加密

♠ 数据安全存在漏洞:

♠ 数据库的备份磁带 可被带出数据中心

♠ 带走的磁带数据可轻松被恢复和浏览

♠ 如何保护你的数据库以防止这种漏洞

♠ 解决数据安全早期方法:

♠ 数据库中将敏感数据加密,再将加密密钥存储在一个不同的地方,这样即使数据被盗也是没有用的

♠ 数据加密与密钥的矛盾 :

应用程序访问加密密钥的方便性、防止密钥被盗的安全性

Page 18: 3.oracle 11g 透明数据加密(91 页)

18/91

10g 数据加密

♠ 10g R2 透明数据加密(Transparent Data Encryption,TDE ):

♠ 不写一行代码,只需要声明你需要加密某列

♠ 当用户插入数据的时候,数据库透明的加密数据然后存储加密后的数据。

♠ 当用户读取数据时,数据库自动进行解密。不需要应用程序修改代码,因此叫做:透明数据加密

♠ 使用10g R2数据库和TDE

♠ 定义需要加密的列,Oracle 将为包含加密列的表创建一个私密安全加密密钥,然后采用你指定的加密算法加密指定列的明文数据

♠ 保护表的加密密钥(以下称“表密钥”)就显得非常重要了。Oracle 10g通过一个master密钥来对表密钥进行加密。master密钥保存在一个叫做“钱夹(wallet)”的安全的地方,钱夹可以是数据库服务器上的一个文件,加密的表密钥保存在数据字典中。

Page 19: 3.oracle 11g 透明数据加密(91 页)

10g 透明数据加密

SQL request

Table key applied

Decrypted data

Page 20: 3.oracle 11g 透明数据加密(91 页)

20/91

10g R2数据加密

♠ 10g R2数据加密工作原理: ♠ 当用户插入数据到需要加密的列中的时候,Oracle 10g从钱夹中获

取master密钥,用master密钥解密数据字典中的表密钥,然后用解密后的表密钥加密输入数据,再将加密后的数据保存在数据库中

♠ TDE工作原理如下图:

Page 21: 3.oracle 11g 透明数据加密(91 页)

21/91

10g R2数据加密

♠ 10g R2 TDE加密与存储 :

♠ 加密表的部分或者所有列

♠ 无论是单个列或多个列加密,Oracle只会生成一个表级的加密密钥,然后用这个密钥加密所有的加密列

♠ 由于数据是加密存储的,所有后续的组建(如备份和归档日志,都是加密的格式) 都是自动加密

♠ 10g R2 TDE查询与解密 :

♠ 当查询一个加密列时,Oracle 将加密的表密钥从数据字典中取出,再取出master密钥,然后解密表密钥,再用解密后的表密钥来解密磁盘上加密的数据,最后返回明文给用户

Page 22: 3.oracle 11g 透明数据加密(91 页)

22/91

10g R2数据加密

♠ 10g R2 TDE 工作流程:

♠ TDE对表数据加密与解密:

Page 23: 3.oracle 11g 透明数据加密(91 页)

23/91

10g R2数据加密

♠ 10g R2 TDE的好处 :

♠ 通过这种加密数据的方式,即使保存在磁盘上的数据被盗,由于master密钥并没有被盗,没有master密钥的情况下,数据无法被获取

♠ 即使“钱夹(wallet)”被盗,如果没有钱夹密码(注:TDE涉及3个密码,一个是钱夹密码,用来启动钱夹;一个是master密钥,用来加解密表密钥;一个是表密钥,用来加解密数据,钱夹密码是用户手工输入的,master

密钥和表密钥是系统管理的),master密钥还是无法获取。

Page 24: 3.oracle 11g 透明数据加密(91 页)

24/91

内容提要

♠ Oracle 9i 数据加密技术

♠ Oracle10g TDE 技术

♠ 使用Oracle10g TDE 加密表

♠ 使用Oracle10g TDE 内置包

♠ Oracle11g TDE 技术

♠ 附录:样例

♠ 参考资源

Page 25: 3.oracle 11g 透明数据加密(91 页)

25/91

创建主键( Master Key)

sqlnet.ora

Wallet location

Master key

Key table

Page 26: 3.oracle 11g 透明数据加密(91 页)

26/91

创建Wallet过程

♠ 创建钱夹(Wallet)过程 :

♠ 1.确认Oracle 软件目录和Wallet可访问目录

♠ 2.在sqlnet.ora文件中加入

♠ 3. lsnrctl start

♠ 4. sqlplus /as sysdba

♠ 5. SQL> ALTER SYSTEM SET ENCRYPTION KEY

IDENTIFIED BY "welcome1";

$ORACLE_HOME/network/admin/sqlnet.ora:

ENCRYPTION_WALLET_LOCATION=

(SOURCE=(METHOD=FILE)(METHOD_DATA=

(DIRECTORY=/u01/app/oracle/product/10.2.0/db_1/wallet)))

$ORACLE_HOME/network/admin/sqlnet.ora:

ENCRYPTION_WALLET_LOCATION=

(SOURCE=(METHOD=FILE)(METHOD_DATA=

(DIRECTORY=/u01/app/oracle/product/10.2.0/db_1/wallet)))

Page 27: 3.oracle 11g 透明数据加密(91 页)

27/91

使用10g R2 TDE

♠ 使用 TDE步骤 :

♠ 由于默认安装下,TDE没有被启用,所以首次使用要进行必要的准备工作

♠ 第一次使用TDE时:

1)指定“钱夹”的位置

2)设置钱夹密码

3)打开钱夹

Page 28: 3.oracle 11g 透明数据加密(91 页)

28/91

使用10g R2 TDE-准备

♠ 1.指定钱夹位置 :

♠ 默认下,钱夹创建于$ORACLE_BASE/admin/$ORACLE_SID/wallet

目录下

♠ 如果$ORACLE_BASE是/u01/app/oracle且$ORACLE_SID是SWBT4,则钱夹将存储在/u01/app/oracle/admin/SWBT4/wallet目录下

♠ 在sqlnet.ora文件增加加密参数 :

钱夹放在/orawall目录下 ,则

#在sqlnet.ora文件

ENCRYPTION_WALLET_LOCATION =

(SOURCE=

(METHOD=file)

(METHOD_DATA=

(DIRECTORY=/orawall)))

#在sqlnet.ora文件

ENCRYPTION_WALLET_LOCATION =

(SOURCE=

(METHOD=file)

(METHOD_DATA=

(DIRECTORY=/orawall)))

Page 29: 3.oracle 11g 透明数据加密(91 页)

29/91

使用10g R2 TDE-准备

♠ 2.创建钱夹 :

♠ 必须创建钱夹,而且必须设定访问密码。为了能够完成此操作,通过如下的操作给一个用户赋予特权(privilege):

♠ 这条命令完成如下功能:

在步骤1中指定的目录下创建了一个钱夹

设定了钱夹的密码为“remnant”

打开了用于TDE存储和获取master密钥的钱夹

♠ 钱夹密码是大小写敏感的且必须用双引号括起来。密码“remnant”在任何动态性能视图或者日志中都不会显示为明文

alter system set encryption key

authenticated by "remnant";

alter system set encryption key

authenticated by "remnant";

Page 30: 3.oracle 11g 透明数据加密(91 页)

30/91

使用10g R2 TDE-准备

♠ 3.打开钱夹 :

♠ 由于钱夹只需要创建一次,因此上面的两个步骤只需要执行一次。钱夹必须显式的在数据库启动后打开。当你创建钱夹的同时钱夹也被打开了。当创建钱夹且设定密码后,每次打开数据库的时候,你都必须使用密码按照如下方式打开钱夹 :

♠ 如果钱夹被关闭,你还是可以访问没有加密的列,但不能够访问加密的列

♠ 可以通过如下方式关闭钱夹:

为了TDE能够正常工作,钱夹必须被打开 ,不用时才关闭

alter system set encryption wallet

open authenticated by "remnant";

alter system set encryption wallet

open authenticated by "remnant";

alter system set encryption wallet close; alter system set encryption wallet close;

Page 31: 3.oracle 11g 透明数据加密(91 页)

31/91

使用10g R2 TDE-加密列

♠ 指定列加密 :

♠ 希望对表的列加密,使用谓词“ENCRYPT 即可:

CREATE TABLE或ALTER TABLE均可用

-- 创建表时指定列加密语法

CREATE TABLE table_name ( column_name column_type

ENCRYPT,....);

--修改表时指定列加密语法

ALTER TABLE table_name MODIFY ( column_name

column_type ENCRYPT,...);

-- 创建表时指定列加密语法

CREATE TABLE table_name ( column_name column_type

ENCRYPT,....);

--修改表时指定列加密语法

ALTER TABLE table_name MODIFY ( column_name

column_type ENCRYPT,...);

Page 32: 3.oracle 11g 透明数据加密(91 页)

32/91

使用10g R2 TDE-加密列

♠ 指定列加密 :

♠ 希望对表的列加密,使用谓词“ENCRYPT 即可:

CREATE TABLE时指定列加密

--创建表时指定列加密语法

CREATE TABLE employee (

first_name VARCHAR2(128),

last_name VARCHAR2(128),

empID NUMBER,

salary NUMBER(6) ENCRYPT

);

--创建表时指定列加密语法

CREATE TABLE employee (

first_name VARCHAR2(128),

last_name VARCHAR2(128),

empID NUMBER,

salary NUMBER(6) ENCRYPT

);

Page 33: 3.oracle 11g 透明数据加密(91 页)

33/91

使用10g R2 TDE-加密列

♠ 指定列加密

♠ 对外部表的加密方法:

--创建表时指定列加密语法

Example 3–7 Creating a New External Table with a Password-Generated Column

Key

CREATE TABLE emp_ext (

first_name,

last_name,

empID,

salary,

ssn ENCRYPT IDENTIFIED BY "xIcf3T9u"

) ORGANIZATION EXTERNAL

(

TYPE ORACLE_DATAPUMP

DEFAULT DIRECTORY "D_DIR"

LOCATION(’emp_ext.dat’)

)

REJECT LIMIT UNLIMITED

as select * from employee;

--创建表时指定列加密语法

Example 3–7 Creating a New External Table with a Password-Generated Column

Key

CREATE TABLE emp_ext (

first_name,

last_name,

empID,

salary,

ssn ENCRYPT IDENTIFIED BY "xIcf3T9u"

) ORGANIZATION EXTERNAL

(

TYPE ORACLE_DATAPUMP

DEFAULT DIRECTORY "D_DIR"

LOCATION(’emp_ext.dat’)

)

REJECT LIMIT UNLIMITED

as select * from employee;

Page 34: 3.oracle 11g 透明数据加密(91 页)

34/91

使用10g R2 TDE-加密列

♠ 关于SALT(加盐) :

♠ 如果原始的明文数据有很多重复的数据时,有时很容易能够猜出加密数据的原始值

♠ 将“salt”加入到数据中使得即使原始值相同的数据加密后具有不同的加密值

♠ TDE缺省情况下应用了“salt”技术

♠ 在列上使用salt加密后,则该列不能创建作用索引,否则提示:ORA-28338: cannot encrypt indexed column(s) with salt

Page 35: 3.oracle 11g 透明数据加密(91 页)

35/91

使用10g R2 TDE-加密列

♠ 指定列加密 :

♠ 对表的列加密不指定SALT,以便创建索引:

--创建表时指定列加密为 NO SALT

CREATE TABLE employee (

first_name VARCHAR2(128),

last_name VARCHAR2(128),

empID NUMBER ENCRYPT NO SALT,

salary NUMBER(6) ENCRYPT USING ’3DES168’

);

CREATE INDEX employee_idx on employee (empID);

--创建表时指定列加密为 NO SALT

CREATE TABLE employee (

first_name VARCHAR2(128),

last_name VARCHAR2(128),

empID NUMBER ENCRYPT NO SALT,

salary NUMBER(6) ENCRYPT USING ’3DES168’

);

CREATE INDEX employee_idx on employee (empID);

Page 36: 3.oracle 11g 透明数据加密(91 页)

36/91

使用10g R2 TDE-加密列

♠ 指定列加密 :

♠ 对表的列加密指定SALT

--修改表时指定列加密带SALT

--Example 3–3 Adding Salt to an Encrypted Column

ALTER TABLE employee MODIFY (first_name ENCRYPT SALT);

--Example 3–4 Removing Salt from an Encrypted Column

ALTER TABLE employee MODIFY (first_name ENCRYPT NO SALT);

--修改表时指定列加密带SALT

--Example 3–3 Adding Salt to an Encrypted Column

ALTER TABLE employee MODIFY (first_name ENCRYPT SALT);

--Example 3–4 Removing Salt from an Encrypted Column

ALTER TABLE employee MODIFY (first_name ENCRYPT NO SALT);

Page 37: 3.oracle 11g 透明数据加密(91 页)

37/91

使用10g R2 TDE-加密列

♠ 指定列加密 :

♠ 指定表的列加密算法3DES168

--创建表时指定列加密带NO SALT

--

CREATE TABLE employee (

first_name VARCHAR2(128),

last_name VARCHAR2(128),

empID NUMBER ENCRYPT NO SALT,

salary NUMBER(6) ENCRYPT USING ’3DES168’

);

--创建表时指定列加密带NO SALT

--

CREATE TABLE employee (

first_name VARCHAR2(128),

last_name VARCHAR2(128),

empID NUMBER ENCRYPT NO SALT,

salary NUMBER(6) ENCRYPT USING ’3DES168’

);

Page 38: 3.oracle 11g 透明数据加密(91 页)

38/91

使用10g R2 TDE-加密列

♠ 指定列加密不加盐以便创建索引 :

♠ 指定表的列为 NO SALT

--创建表时指定列加密带NO SALT

--

Alter table credit_rating modify

(person_id encrypt no salt);

--

Create index person_id_idx on credit_rating (PERSON_ID);

--

Select score from credit_rating where

PERSON_ID='235901';

--创建表时指定列加密带NO SALT

--

Alter table credit_rating modify

(person_id encrypt no salt);

--

Create index person_id_idx on credit_rating (PERSON_ID);

--

Select score from credit_rating where

PERSON_ID='235901';

数据用法保持原来模样

在加密的列上创建索引

加密的列为NO Salt

Page 39: 3.oracle 11g 透明数据加密(91 页)

39/91

使用10g R2 TDE-加密列

♠ 指定列加密10g默认情况 :

♠ 默认下表的列为 AES 192 bit:

--创建表时指定列加密

alter table credit_rating modify (person_id encrypt);

--建议指定明确的加密算法,如:

create table employee (

first_name varchar2(64),

last_name varchar2(64),

empID NUMBER encrypt using 'AES256',

salary NUMBER(6) encrypt using 'AES256');

--

--创建表时指定列加密

alter table credit_rating modify (person_id encrypt);

--建议指定明确的加密算法,如:

create table employee (

first_name varchar2(64),

last_name varchar2(64),

empID NUMBER encrypt using 'AES256',

salary NUMBER(6) encrypt using 'AES256');

--

在加密的列上指定算法

默认列加密AES 192 Bit

Page 40: 3.oracle 11g 透明数据加密(91 页)

40/91

使用10g R2 TDE-加密列

♠ 修改表加密算法 :

♠ 指定表的加密算法:

--指定表列加密-还要用原来的加密算法:

ALTER TABLE employee REKEY;

--指定表的加密算法改为AES256:

ALTER TABLE employee REKEY USING 'AES256';

--指定表的加密为 AES128:

ALTER TABLE employee ENCRYPT USING 'AES128';

--指定表列加密-还要用原来的加密算法:

ALTER TABLE employee REKEY;

--指定表的加密算法改为AES256:

ALTER TABLE employee REKEY USING 'AES256';

--指定表的加密为 AES128:

ALTER TABLE employee ENCRYPT USING 'AES128';

Page 41: 3.oracle 11g 透明数据加密(91 页)

41/91

使用10g R2 TDE-性能考虑

♠ 列加密与性能的平衡

♠ 由于加解密消耗CPU,因此你必须考虑性能的影响。

♠ 当访问表中不加密的列时,性能和不使用TDE的表没有任何差别

♠ 当在访问加密列的时候,会有小的性能负担,包括查询加密列和插入加密列,因此你也许想有选择的加密列

♠ 如果你不再需要对一个列加密,你可以通过如下方式关闭加密功能:

--修改表时指定列为不加密-decrypt

alter table account modify (ssn decrypt);

--修改表时指定列为不加密-decrypt

alter table account modify (ssn decrypt);

Page 42: 3.oracle 11g 透明数据加密(91 页)

42/91

使用10g R2 TDE-维护密钥

♠ 管理表的密钥

♠ 怀疑某人可能已经破解了加密的表密钥,简单的为表创建一个新的密钥

♠ 也可选择另外一个算法进行加密,例如使用 ’3DES168’ :

--修改表密钥

ALTER TABLE employee REKEY;

--修改表使用另外的密钥:

ALTER TABLE employee REKEY USING ’3DES168’;

--修改表密钥

ALTER TABLE employee REKEY;

--修改表使用另外的密钥:

ALTER TABLE employee REKEY USING ’3DES168’;

Page 43: 3.oracle 11g 透明数据加密(91 页)

43/91

使用10g R2 TDE-维护钱夹

♠ 管理钱夹(Wallet)

♠ 怀疑某人得到了钱夹的密码,可以通过Oracle Wallet

Manager修改钱夹密码

♠ 在命令行中输入OWM即可调用如下GUI工具。从顶上的菜单选择Wallet -> Open并且选择你指定的钱夹的位置,然后给出钱夹密码,选择Wallet -> Change

Password修改钱夹密码。

♠ 需要说明的是修改钱夹的密码不会修改master密钥 :

Page 44: 3.oracle 11g 透明数据加密(91 页)

44/91

使用10g R2 TDE-维护钱夹

♠ 管理钱夹 ♠ GUI工具-10g Wallet Manager 界面 :

Page 45: 3.oracle 11g 透明数据加密(91 页)

45/91

使用10g R2 TDE-导出TDE

♠ TDE 密钥可与实用程序一起使用

♠ 默认情况下,如果使用EXPDP工具导出一个拥有加密列的表,在导出文件(dump file)中列是明文的,即使列定义为加密也是如此。如下命令导出ACCOUNTS表(包括加密的列),将会返回一个警告:

♠ 这只是一个警告,不是错误,数据还是会被导出

$ expdp arup/arup tables=accounts

ORA-39173: Encrypted data has been stored

unencrypted in dump file set.

$ expdp arup/arup tables=accounts

ORA-39173: Encrypted data has been stored

unencrypted in dump file set.

Page 46: 3.oracle 11g 透明数据加密(91 页)

46/91

使用10g R2 TDE-导出TDE

♠ TDE 密钥可与实用程序一起使用 ♠ 为了在数据导出文件中保护你的加密的列数据,你可以在导出表的

时候通过密码保护机制来保护导出文件

♠ 这个密码通过在EXPDP命令中的ENCRYPTION_PASSWORD参数指定,且只会应用到本次导出,这个不是“钱夹”的密码

♠ 下面清单1中的密码并不会显示为“pooh”,而是通过*号来隐藏

$ expdp arup/arup ENCRYPTION_PASSWORD=pooh tables=accounts

Export: Release 10.2.0.0.0 - Beta on Friday, 01 July, 2005 16:14:06

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.0.0 - Beta

With the Partitioning, OLAP and Data Mining options

Starting "ARUP"."SYS_EXPORT_TABLE_01": arup/********

ENCRYPTION_PASSWORD=********* tables=accounts

Estimate in progress using BLOCKS method...

Processing ...

$ expdp arup/arup ENCRYPTION_PASSWORD=pooh tables=accounts

Export: Release 10.2.0.0.0 - Beta on Friday, 01 July, 2005 16:14:06

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.0.0 - Beta

With the Partitioning, OLAP and Data Mining options

Starting "ARUP"."SYS_EXPORT_TABLE_01": arup/********

ENCRYPTION_PASSWORD=********* tables=accounts

Estimate in progress using BLOCKS method...

Processing ...

Page 47: 3.oracle 11g 透明数据加密(91 页)

47/91

使用10g R2 TDE-导出TDE

♠ TDE 密钥可与实用程序一起使用

♠ 当你导入加密的dump文件时,你也必须提供同样的密码,代码清单2显示了如何操作:

$ impdp arup/arup ENCRYPTION_PASSWORD=pooh tables=accounts

table_exists_action=replace

Import: Release 10.2.0.0.0 - Beta on Friday, 01 July, 2005 16:04:20

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.0.0 - Beta

With the Partitioning, OLAP and Data Mining options

Master table "ARUP"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded

Starting "ARUP"."SYS_IMPORT_TABLE_01": arup/********

ENCRYPTION_PASSWORD=********* table_exists_action=replace

Processing ...

$ impdp arup/arup ENCRYPTION_PASSWORD=pooh tables=accounts

table_exists_action=replace

Import: Release 10.2.0.0.0 - Beta on Friday, 01 July, 2005 16:04:20

Copyright (c) 2003, 2005, Oracle. All rights reserved.

Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.0.0 - Beta

With the Partitioning, OLAP and Data Mining options

Master table "ARUP"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded

Starting "ARUP"."SYS_IMPORT_TABLE_01": arup/********

ENCRYPTION_PASSWORD=********* table_exists_action=replace

Processing ...

Page 48: 3.oracle 11g 透明数据加密(91 页)

48/91

使用10g R2 TDE-数据卫士环境

♠ TDE 在Data Guard环境自动应用到备用库中

♠ 10g/11g 自动通过日志实现对备用库的加密:

Page 49: 3.oracle 11g 透明数据加密(91 页)

49/91

使用10g R2 TDE-限制

♠ TDE 支持的数据类型: ♠ varchar2

♠ nvarchar2

♠ number

♠ date

♠ binary_float (*)

♠ binary_double (*)

♠ timestamp

♠ raw

♠ char

♠ nchar

♠ TDE 不支持的功能: ♠ Materialized View logs

♠ Streams

♠ Sync and async CDC

♠ Direct path insert

♠ Transportable Tablespaces

♠ LOBs

Page 50: 3.oracle 11g 透明数据加密(91 页)

50/91

内容提要

♠ Oracle 9i 数据加密技术

♠ Oracle10g TDE 技术

♠ 使用Oracle10g TDE 加密表

♠ 使用Oracle10g TDE 内置包

♠ Oracle11g TDE 技术

♠ 附录:样例

♠ 参考资源

Page 51: 3.oracle 11g 透明数据加密(91 页)

51/91

使用DBMS_CRYPTO

♠ DBMS_CRYPTO包

♠ 产生随机数键值

♠ 加密和解密列值

♠ 使用DBMS_CRYPTO包

♠ 加密表的列值

♠ 解密表的列值

♠ 支持9i版本的DBMS_OBFUSCATION_TOOLKIT

DBMS_CRYPTO

OKYMSEISPDTGA

MyCreditCardNum

CUST.CREDITCARD

Page 52: 3.oracle 11g 透明数据加密(91 页)

52/91

使用DBMS_CRYPTO

♠ DBMS_CRYPTO与DBMS_OBFUSCATION_TOOLKIT包

♠ Oracle 10g/11g 推荐使用DBMS_CRYPTO

♠ 这两个包支持加密的差异

功能 DBMS_CRYPTO DBMS_OBFUSCATION_TO

OLKIT

密码算法 DES, 3DES, AES, RC4,

3DES_2KEY

DES, 3DES

数据库类型 RAW, CLOB, BLOB RAW, VARCHAR2

块密码链模式 CBC, CFB, ECB, OFB CBC

密码Hash算法 MD5, SHA-1, MD4 MD5

键值Hash算法(MAC) HMAC_MD5, HMAC_SH1 不支持

Page 53: 3.oracle 11g 透明数据加密(91 页)

53/91

两加密包功能比较

包的特点 DBMS_CRYPTO

DBMS_OBFUSCATION_

TOOLKIT

加密算法 DES, 3DES, AES, RC4,

3DES_2KEY

DES, 3DES

填充形式(Padding forms) PKCS5, zeroes 无支持项

密码分组链接模式 (

Block cipher chaining

modes)

CBC, CFB, ECB, OFB CBC

加密散列算法

(Cryptographic hash

algorithms)

MD5, SHA-1, MD4 MD5

密钥散列 (MAC) 算法 HMAC_MD5,

HMAC_SH1

无支持项

加密伪随机数生成器 RAW, NUMBER,

BINARY_INTEGER RAW, VARCHAR2

数据库类型 RAW, CLOB, BLOB RAW, VARCHAR2

Page 54: 3.oracle 11g 透明数据加密(91 页)

54/91

加密的挑战

♠ 译码的索引数据问题

♠ 密钥的管理问题

♠ 密钥的传输问题

♠ 密钥的存储问题

♠ 改变密钥问题

♠ 二进制对象问题 (BLOBS)

Page 55: 3.oracle 11g 透明数据加密(91 页)

55/91

使用DBMS_CRYPTO包

♠ 产生随机数加密

♠ 1.产生随机数- 用RANDOMBYTES产生键值

♠ 2.用dbms_crypto.encrypt加密:

raw_key := dbms_crypto.randombytes (number_bytes => 24); raw_key := dbms_crypto.randombytes (number_bytes => 24);

encrypted_raw := dbms_crypto.encrypt (

src => raw_input,

typ => DBMS_CRYPTO.DES3_CBC_PKCS5

key => raw_key );

encrypted_raw := dbms_crypto.encrypt (

src => raw_input,

typ => DBMS_CRYPTO.DES3_CBC_PKCS5

key => raw_key );

Page 56: 3.oracle 11g 透明数据加密(91 页)

56/91

使用DBMS_CRYPTO

♠ 产生随机数加密

♠ 1.用dbms_crypto.Encrypt函数加密

♠ 2.用DBMS_CRYPTO.Decrypt函数解密 :

encrypted_raw := dbms_crypto.Encrypt (

src => raw_input,

typ => dbms_crypto.DES3_CBC_PKCS5,

key => raw_key);

encrypted_raw := dbms_crypto.Encrypt (

src => raw_input,

typ => dbms_crypto.DES3_CBC_PKCS5,

key => raw_key);

decrypted_raw := dbms_crypto.Decrypt (

encrypted_raw,

dbms_crypto.DES3_CBC_PKCS5,

raw_key);

decrypted_raw := dbms_crypto.Decrypt (

encrypted_raw,

dbms_crypto.DES3_CBC_PKCS5,

raw_key);

Page 57: 3.oracle 11g 透明数据加密(91 页)

57/91

使用DBMS_CRYPTO-样例0

♠ 确认DBMS_CRYPTO包已经安装

♠ 一般10g /11g RDBMS创建成功后都安装完毕,如:

SQL> select object_name from dba_objects

where object_name like 'DBMS_CRYPTO%'

OBJECT_NAME

-------------------------------------------------------------

DBMS_CRYPTO

DBMS_CRYPTO_FFI

DBMS_CRYPTO_FFI

DBMS_CRYPTO

DBMS_CRYPTO_TOOLKIT_TYPES

DBMS_CRYPTO_TOOLKIT

DBMS_CRYPTO_TOOLKIT_FFI

DBMS_CRYPTO_TOOLKIT_FFI

DBMS_CRYPTO_TOOLKIT

DBMS_CRYPTO

DBMS_CRYPTO_TOOLKIT

已选择11行。

SQL> select object_name from dba_objects

where object_name like 'DBMS_CRYPTO%'

OBJECT_NAME

-------------------------------------------------------------

DBMS_CRYPTO

DBMS_CRYPTO_FFI

DBMS_CRYPTO_FFI

DBMS_CRYPTO

DBMS_CRYPTO_TOOLKIT_TYPES

DBMS_CRYPTO_TOOLKIT

DBMS_CRYPTO_TOOLKIT_FFI

DBMS_CRYPTO_TOOLKIT_FFI

DBMS_CRYPTO_TOOLKIT

DBMS_CRYPTO

DBMS_CRYPTO_TOOLKIT

已选择11行。

Page 58: 3.oracle 11g 透明数据加密(91 页)

58/91

使用DBMS_CRYPTO-样例0

♠ 使用DBMS_CRYPTO包

♠ 在匿名块中使用,如:

set serveroutput on

DECLARE

input_string VARCHAR2(16) := 'CreditCardNumber';

raw_input RAW(128) := UTL_I18N.STRING_TO_RAW(input_string,'AL32UTF8');

raw_key RAW(256);

encrypted_raw RAW(2048);

encrypted_string VARCHAR2(2048);

decrypted_raw RAW(2048);

decrypted_string VARCHAR2(2048);

BEGIN

dbms_output.put_line('> ========= Get Key Bytes =========');

raw_key := dbms_crypto.randombytes(24);

dbms_output.put_line('> Key String length: ' || UTL_RAW.LENGTH(raw_key));

dbms_output.put_line('> Key String: ' || UTL_RAW.CAST_TO_VARCHAR2(raw_key));

dbms_output.put_line('> Input String: ' || input_string);

dbms_output.put_line('> ========= BEGIN TEST Encrypt =========');

encrypted_raw := dbms_crypto.Encrypt(src => raw_input, typ => DBMS_CRYPTO.DES3_CBC_PKCS5, key => raw_key);

dbms_output.put_line('> Encrypted hex value : ' || rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

dbms_output.put_line('> Encrypted varchar2 value: ' || UTL_RAW.CAST_TO_VARCHAR2(encrypted_raw));

decrypted_raw := dbms_crypto.Decrypt(src => encrypted_raw, typ => DBMS_CRYPTO.DES3_CBC_PKCS5, key => raw_key);

decrypted_string := UTL_I18N.RAW_TO_CHAR(decrypted_raw,'AL32UTF8');

dbms_output.put_line('> Decrypted string output : ' ||decrypted_string);

if input_string = decrypted_string THEN

dbms_output.put_line('> String DES Encyption and Decryption successful');

END if;

END;

/

set serveroutput on

DECLARE

input_string VARCHAR2(16) := 'CreditCardNumber';

raw_input RAW(128) := UTL_I18N.STRING_TO_RAW(input_string,'AL32UTF8');

raw_key RAW(256);

encrypted_raw RAW(2048);

encrypted_string VARCHAR2(2048);

decrypted_raw RAW(2048);

decrypted_string VARCHAR2(2048);

BEGIN

dbms_output.put_line('> ========= Get Key Bytes =========');

raw_key := dbms_crypto.randombytes(24);

dbms_output.put_line('> Key String length: ' || UTL_RAW.LENGTH(raw_key));

dbms_output.put_line('> Key String: ' || UTL_RAW.CAST_TO_VARCHAR2(raw_key));

dbms_output.put_line('> Input String: ' || input_string);

dbms_output.put_line('> ========= BEGIN TEST Encrypt =========');

encrypted_raw := dbms_crypto.Encrypt(src => raw_input, typ => DBMS_CRYPTO.DES3_CBC_PKCS5, key => raw_key);

dbms_output.put_line('> Encrypted hex value : ' || rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

dbms_output.put_line('> Encrypted varchar2 value: ' || UTL_RAW.CAST_TO_VARCHAR2(encrypted_raw));

decrypted_raw := dbms_crypto.Decrypt(src => encrypted_raw, typ => DBMS_CRYPTO.DES3_CBC_PKCS5, key => raw_key);

decrypted_string := UTL_I18N.RAW_TO_CHAR(decrypted_raw,'AL32UTF8');

dbms_output.put_line('> Decrypted string output : ' ||decrypted_string);

if input_string = decrypted_string THEN

dbms_output.put_line('> String DES Encyption and Decryption successful');

END if;

END;

/

Page 59: 3.oracle 11g 透明数据加密(91 页)

59/91

使用DBMS_CRYPTO-样例0

♠ 使用DBMS_CRYPTO包

♠ 在匿名块中使用,如:

> ========= Get Key Bytes =========

> Key String length: 24

> Key String: �鶩菭韖S�WF�F=輬,?趫

> Input String: CreditCardNumber

> ========= BEGIN TEST Encrypt =========

> Encrypted hex value :

3039464437313839443944303331413935394331443533314236383037453431374342

35424439353331444135354137

> Encrypted varchar2 value: 齫壻?℡琳1秬~A|到?赨

> Decrypted string output : CreditCardNumber

> String DES Encyption and Decryption successful

PL/SQL 过程已成功完成。

> ========= Get Key Bytes =========

> Key String length: 24

> Key String: �鶩菭韖S�WF�F=輬,?趫

> Input String: CreditCardNumber

> ========= BEGIN TEST Encrypt =========

> Encrypted hex value :

3039464437313839443944303331413935394331443533314236383037453431374342

35424439353331444135354137

> Encrypted varchar2 value: 齫壻?℡琳1秬~A|到?赨

> Decrypted string output : CreditCardNumber

> String DES Encyption and Decryption successful

PL/SQL 过程已成功完成。

Page 60: 3.oracle 11g 透明数据加密(91 页)

60/91

使用DBMS_CRYPTO-样例1

♠ 在函数使用DBMS_CRYPTO包

♠ 1.编辑一个函数代码如下,并以crypt.sql文件存储

create or replace function des_crypt

(pv_text in varchar) return raw is

lv_key raw(128);

lv_text raw(2000);

begin

lv_text:=sys.utl_i18n.string_to_raw(

pv_text,'AL32UTF8');

lv_key :=sys.utl_i18n.string_to_raw(

sys.dbms_crypto.randombytes (16),'AL32UTF8');

return(sys.dbms_crypto.encrypt(

lv_text,sys.dbms_crypto.DES3_CBC_PKCS5,lv_key));

end des_crypt;

/

create or replace function des_crypt

(pv_text in varchar) return raw is

lv_key raw(128);

lv_text raw(2000);

begin

lv_text:=sys.utl_i18n.string_to_raw(

pv_text,'AL32UTF8');

lv_key :=sys.utl_i18n.string_to_raw(

sys.dbms_crypto.randombytes (16),'AL32UTF8');

return(sys.dbms_crypto.encrypt(

lv_text,sys.dbms_crypto.DES3_CBC_PKCS5,lv_key));

end des_crypt;

/

Page 61: 3.oracle 11g 透明数据加密(91 页)

61/91

使用DBMS_CRYPTO-样例1

♠ 在函数使用DBMS_CRYPTO包

♠ 2.在SQL>下运行crypt.sql脚本

♠ 看到Crypted text被加密成乱码如下:

SQL> @crypt

Function created.

SQL> set serveroutput on size 1000000

SQL> exec dbms_output.put_line('Crypted text:

'||des_crypt('test crypt'));

Crypted text:

8640FE54ED48429423E5EABB01AA3334

SQL> @crypt

Function created.

SQL> set serveroutput on size 1000000

SQL> exec dbms_output.put_line('Crypted text:

'||des_crypt('test crypt'));

Crypted text:

8640FE54ED48429423E5EABB01AA3334

Page 62: 3.oracle 11g 透明数据加密(91 页)

62/91

使用DBMS_CRYPTO-样例2

♠ 创建样例表 cust_payment_info

♠ 创建表与插入数据:

CREATE TABLE cust_payment_info

(first_name VARCHAR2(11),

last_name VARCHAR2(10),

order_number NUMBER(5),

credit_card_number VARCHAR2(16) ENCRYPT NO SALT,

active_card VARCHAR2(3));

CREATE TABLE cust_payment_info

(first_name VARCHAR2(11),

last_name VARCHAR2(10),

order_number NUMBER(5),

credit_card_number VARCHAR2(16) ENCRYPT NO SALT,

active_card VARCHAR2(3));

INSERT INTO cust_payment_info VALUES

('Jon', 'Oldfield', 10001, '5446959708812985','YES');

INSERT INTO cust_payment_info VALUES

('Chris', 'White', 10002, '5122358046082560','YES');

INSERT INTO cust_payment_info VALUES

('Alan', 'Squire', 10003, '5595968943757920','YES');

INSERT INTO cust_payment_info VALUES

('Mike', 'Anderson', 10004, '4929889576357400','YES');

INSERT INTO cust_payment_info VALUES

('Annie', 'Schmidt', 10005, '4556988708236902','YES');

INSERT INTO cust_payment_info VALUES

('Elliott', 'Meyer', 10006, '374366599711820','YES');

INSERT INTO cust_payment_info VALUES

('Celine', 'Smith', 10007, '4716898533036','YES');

INSERT INTO cust_payment_info VALUES

('Steve', 'Haslam', 10008, '340975900376858','YES');

INSERT INTO cust_payment_info VALUES

('Albert', 'Einstein', 10009, '310654305412389','YES');

INSERT INTO cust_payment_info VALUES

('Jon', 'Oldfield', 10001, '5446959708812985','YES');

INSERT INTO cust_payment_info VALUES

('Chris', 'White', 10002, '5122358046082560','YES');

INSERT INTO cust_payment_info VALUES

('Alan', 'Squire', 10003, '5595968943757920','YES');

INSERT INTO cust_payment_info VALUES

('Mike', 'Anderson', 10004, '4929889576357400','YES');

INSERT INTO cust_payment_info VALUES

('Annie', 'Schmidt', 10005, '4556988708236902','YES');

INSERT INTO cust_payment_info VALUES

('Elliott', 'Meyer', 10006, '374366599711820','YES');

INSERT INTO cust_payment_info VALUES

('Celine', 'Smith', 10007, '4716898533036','YES');

INSERT INTO cust_payment_info VALUES

('Steve', 'Haslam', 10008, '340975900376858','YES');

INSERT INTO cust_payment_info VALUES

('Albert', 'Einstein', 10009, '310654305412389','YES');

Page 63: 3.oracle 11g 透明数据加密(91 页)

63/91

加密相关数据字典

♠ 加密有关数据字典有: ♠ DBA_ENCRYPTED_COLUMNS

♠ USER_ENCRYPTED_COLUMNS

♠ ALL_ENCRYPTED_COLUMNS

♠ V$RMAN_ENCRYPTION_ALGORITHMS

♠ V$ENCRYPTED_TABLESPACES

♠ V$ENCRYPTION_WALLET

Page 64: 3.oracle 11g 透明数据加密(91 页)

64/91

加密相关数据字典

♠ DBA_ENCRYPTED_COLUMNS ♠ ENCRYPTION_ALG VARCHAR2(29—加密算法,分别是:

♠ AES 128 bits key

♠ AES 192 bits key

♠ AES 256 bits key

♠ ENCRYPTION_ALG VARCHAR2(29—加密算法,分别是:

♠ AES 128 bits key

♠ SALT VARCHAR2(3)—是否加盐

♠ INTEGRITY_ALG VARCHAR2(12)—整数算法:SHA-1与NOMAC

Page 65: 3.oracle 11g 透明数据加密(91 页)

65/91

加密相关数据字典

♠ DBA_ENCRYPTED_COLUMNS

♠ 查询加密列的信息:

SQL> select table_name, column_name, encryption_alg

2 from dba_encrypted_columns

3 /

TABLE_NAME COLUMN_NAME ENCRYPTION_ALG

------------------------------ ------------------ -----------------------------

CONTRACTS_SEC ORIG_FILE AES 128 bits key

SQL> select table_name, column_name, encryption_alg

2 from dba_encrypted_columns

3 /

TABLE_NAME COLUMN_NAME ENCRYPTION_ALG

------------------------------ ------------------ -----------------------------

CONTRACTS_SEC ORIG_FILE AES 128 bits key

Page 66: 3.oracle 11g 透明数据加密(91 页)

66/91

加密相关数据字典

♠ V$ENCRYPTED_TABLESPACES-11g ♠ TS# NUMBER

♠ ENCRYPTIONALG VARCHAR2(7):

♠ NONE

♠ 3DES168

♠ AES128

♠ AES192

♠ AES256

♠ ENCRYPTEDTS VARCHAR2(3)

SQL> desc v$encrypted_tablespaces

Name Null?Type

----------------------------------------- -------- ------------

TS# NUMBER

ENCRYPTIONALG VARCHAR2(7)

ENCRYPTEDTS VARCHAR2(3)

SQL> select * from v$encrypted_tablespaces;

TS# ENCRYPT ENC

---------- ------- ---

5 AES128 YES

SQL> desc v$encrypted_tablespaces

Name Null?Type

----------------------------------------- -------- ------------

TS# NUMBER

ENCRYPTIONALG VARCHAR2(7)

ENCRYPTEDTS VARCHAR2(3)

SQL> select * from v$encrypted_tablespaces;

TS# ENCRYPT ENC

---------- ------- ---

5 AES128 YES

Page 67: 3.oracle 11g 透明数据加密(91 页)

67/91

加密相关数据字典

♠ V$WALLET ♠ CERT_ID VARCHAR2(52)

♠ DN VARCHAR2(255)

♠ SERIAL_NUM VARCHAR2(40)

♠ ISSUER VARCHAR2(255)

♠ KEYSIZE NUMBER

♠ STATUS VARCHAR2(16)

♠ UNUSED

♠ IN USE

♠ USED

SQL> SQL>

Page 68: 3.oracle 11g 透明数据加密(91 页)

68/91

加密相关数据字典

♠ V$ENCRYPTION_WALLET ♠ WRL_TYPE VARCHAR2(20)

♠ WRL_PARAMETER VARCHAR2(4000)

♠ STATUS VARCHAR2(9)

♠ OPEN

♠ CLOSED

♠ UNDEFINED

♠ OPEN_NO_MASTER_KEY

SQL> SQL>

Page 69: 3.oracle 11g 透明数据加密(91 页)

69/91

内容提要

♠ Oracle 9i 数据加密技术

♠ Oracle10g TDE 技术

♠ 使用Oracle10g TDE 加密表

♠ 使用Oracle10g TDE 内置包

♠ Oracle11g TDE 技术

♠ 附录:样例

♠ 参考资源

Page 70: 3.oracle 11g 透明数据加密(91 页)

70/91

Oracle 系统加密回顾

♠ 数据加密选项…

♠ DBMS_OBFUSCATION_TOOLKIT

♠ 8i-9iR2

♠ 今后不再使用

♠ 本次前面做了简要介绍,但是不推荐

♠ 建议开发人员直接了解下面的新包

♠ DBMS_CRYPTO

♠ 10gR1 及更高版本

♠ 不是必须使用 (because of the next two bullets)

♠ 前面已经简要介绍,下面只介绍差异的部分

♠ 列级的加密 ♠ 10gR2及更高版本(ASO)

♠ 表空间加密 ♠ 11gR1及更高版本(ASO)

Page 71: 3.oracle 11g 透明数据加密(91 页)

71/91

列加密的限制

♠现在还存在限制

♠如果使用索引,则不能使用 ‘salt’

♠外部键不可使用

♠ exp/imp 问题 (清除文本)

♠ 11g-datapump 可处理加密问题.

Page 72: 3.oracle 11g 透明数据加密(91 页)

72/91

表空间级加密

♠ 磁盘存储加密

♠ 数据缓存在SGA中不加密

♠ 撤销数据加密

♠ 日期数据加密

♠ 数据在块中以明文存储与离开磁盘解密

♠ 索引是以明文存在的

♠ 范围扫描 – 解答

♠ 外部键 –解答

Page 73: 3.oracle 11g 透明数据加密(91 页)

73/91

表空间级加密

♠ 11g 版本支持表空间数据加密

♠例1:指定加密算法为AES128:

create tablespace secure1

datafile '/db1/1.dbf' size 1M

encryption using 'AES128'

default storage (encrypt)

--

SQL> desc v$encrypted_tablespaces

Name Null? Type

----------------- -------- -----------

TS# NUMBER

ENCRYPTIONALG VARCHAR2(7)

ENCRYPTEDTS VARCHAR2(3)

Page 74: 3.oracle 11g 透明数据加密(91 页)

74/91

表空间级加密

♠ 11g 版本支持表空间数据加密

♠例2:指定加密算法为AES256:

CREATE TABLESPACE securespace

DATAFILE 'c:\temp\secure02.dbf' SIZE 25M

ENCRYPTION USING 'AES256'

DEFAULT STORAGE(ENCRYPT);

SQL> SELECT ta.table_name, ts.tablespace_name, ts.encrypted

2 FROM user_tables ta, user_tablespaces ts

3 WHERE ta.tablespace_name = ts.tablespace_name

4 ORDER BY 2, 1;

TABLE_NAME TABLESPACE_NAME ENC

------------------------------ ------------------------------ ---

T1 SECURESPACE YES

T2 SECURESPACE2 YES

AIRPLANES UWDATA NO

SERVERS UWDATA NO

SERV_INST UWDATA NO

Page 75: 3.oracle 11g 透明数据加密(91 页)

75/91

数据加密与性能

♠数据加密对性能有些影响

♠不同版本加密影响程度不同:

Page 76: 3.oracle 11g 透明数据加密(91 页)

76/91

安全文件-加密

♠ 11g 版本支持文件级的数据安全-加密

♠例1:指定文件安全-加密:

SQL> SELECT name, value

2 FROM gv$parameter

3 WHERE name LIKE '%secure%';

NAME VALUE

------------------------------ ---------

db_securefile PERMITTED

optimizer_secure_view_merging TRUE

CREATE TABLE sec_tab2 (

rid NUMBER(5),

bcol BLOB)

LOB (bcol)

STORE AS SECUREFILE bcol2 (

TABLESPACE securefiletbs

RETENTION MIN 3600 COMPRESS ENCRYPT CACHE READS)

TABLESPACE uwdata;

Page 77: 3.oracle 11g 透明数据加密(91 页)

77/91

数据的屏蔽-data mask

♠ 11g 版本新推出数据屏蔽

♠关键的数据采用屏蔽,方法如:

Page 78: 3.oracle 11g 透明数据加密(91 页)

78/91

数据的屏蔽-data mask

♠ 11g :EM-定义数据屏蔽:

♠定义数据屏蔽:

Page 79: 3.oracle 11g 透明数据加密(91 页)

79/91

数据的屏蔽-data mask

♠ 11g :EM-定义数据屏蔽:

♠定义数据屏蔽:

Page 80: 3.oracle 11g 透明数据加密(91 页)

80/91

数据的屏蔽-data mask

♠ 11g :EM-定义数据屏蔽:

♠数据屏蔽主要步骤:

Page 81: 3.oracle 11g 透明数据加密(91 页)

81/91

数据的屏蔽-data mask

♠ 11g :EM-定义数据屏蔽:

♠数据屏蔽主要步骤:

Page 82: 3.oracle 11g 透明数据加密(91 页)

82/91

内容提要

♠ Oracle 9i 数据加密技术

♠ Oracle10g TDE 技术

♠ 使用Oracle10g TDE 加密表

♠ 使用Oracle10g TDE 内置包

♠ Oracle11g TDE 技术

♠ 附录:样例

♠ 参考资源

Page 83: 3.oracle 11g 透明数据加密(91 页)

83/91

EXP 与 加密

♠ 11g : EXP 带数据加密:

♠使用时提示:

exp enc_test/manager file=test.dmp tables=test_enc

...

EXP-00111: Table TEST_ENC resides in an Encrypted

Tablespace ENC_TEST and will not be exported

...

exp enc_test/manager file=test.dmp tables=test_enc

...

EXP-00111: Table TEST_ENC resides in an Encrypted

Tablespace ENC_TEST and will not be exported

...

Page 84: 3.oracle 11g 透明数据加密(91 页)

84/91

11g 本地加密设置

♠ 11g 本地加密:

♠Orapki 实用程序:

orapki wallet create -wallet <wallet_location> \

-auto_login_local

orapki wallet create -wallet <wallet_location> \

-auto_login_local

Page 85: 3.oracle 11g 透明数据加密(91 页)

85/91

附录1:DBMS_OBFUSCATION_TOOLKIT样例

♠ 9i 用DBMS_OBFUSCATION_TOOLKIT包:

♠ 9i 用DBMS_OBFUSCATION_TOOLKIT包实现数据加密

♠ 加密的PL/SQL 方法如下(B14258.pdf): DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input IN RAW,

key IN RAW,

decrypted_data OUT RAW,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv IN RAW DEFAULT NULL);

DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input_string IN VARCHAR2,

key_string IN VARCHAR2,

decrypted_string OUT VARCHAR2,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv_string IN VARCHAR2 DEFAUTL NULL);

DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input IN RAW,

key IN RAW,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv IN RAW DEFAULT NULL)

RETURN RAW;

DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input_string IN VARCHAR2,

key_string IN VARCHAR2,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv_string IN VARCHAR2 DEFAULT NULL)

RETURN VARCHAR2;

DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input IN RAW,

key IN RAW,

decrypted_data OUT RAW,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv IN RAW DEFAULT NULL);

DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input_string IN VARCHAR2,

key_string IN VARCHAR2,

decrypted_string OUT VARCHAR2,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv_string IN VARCHAR2 DEFAUTL NULL);

DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input IN RAW,

key IN RAW,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv IN RAW DEFAULT NULL)

RETURN RAW;

DBMS_OBFUSCATION_TOOLKIT.DES3DECRYPT(

input_string IN VARCHAR2,

key_string IN VARCHAR2,

which IN PLS_INTEGER DEFAULT TwoKeyMode

iv_string IN VARCHAR2 DEFAULT NULL)

RETURN VARCHAR2;

Page 86: 3.oracle 11g 透明数据加密(91 页)

86/91

附录2:DBMS_CRYPTO包的使用

♠ 10g/11g用dbms_crypto实现加密解密:

♠ PL/SQL 方法- CRYPT_PKG来实现数据的加密解密: CREATE OR REPLACE PACKAGE crypt_pkg IS

typ PLS_INTEGER :=DBMS_CRYPTO.ENCRYPT_AES256

+DBMS_CRYPTO.CHAIN_CBC

+DBMS_CRYPTO.PAD_PKCS5;

key CONSTANT RAW(32) :='AB45456E59EFD93F63'||

'01F47DEE4BAF39A0234573400579DC5801A8AC2382BF6E';

FUNCTION encry(input RAW) RETURN RAW;

FUNCTION decry(encry_str RAW) RETURN RAW;

END;

/

CREATE OR REPLACE PACKAGE BODY crypt_pkg IS

FUNCTION encry(input RAW) RETURN RAW IS

BEGIN

RETURN dbms_crypto.encrypt(input,typ,key);

END;

FUNCTION decry(encry_str RAW ) RETURN RAW IS

BEGIN

RETURN dbms_crypto.decrypt(encry_str,typ,key);

END;

END;

/

CREATE OR REPLACE PACKAGE crypt_pkg IS

typ PLS_INTEGER :=DBMS_CRYPTO.ENCRYPT_AES256

+DBMS_CRYPTO.CHAIN_CBC

+DBMS_CRYPTO.PAD_PKCS5;

key CONSTANT RAW(32) :='AB45456E59EFD93F63'||

'01F47DEE4BAF39A0234573400579DC5801A8AC2382BF6E';

FUNCTION encry(input RAW) RETURN RAW;

FUNCTION decry(encry_str RAW) RETURN RAW;

END;

/

CREATE OR REPLACE PACKAGE BODY crypt_pkg IS

FUNCTION encry(input RAW) RETURN RAW IS

BEGIN

RETURN dbms_crypto.encrypt(input,typ,key);

END;

FUNCTION decry(encry_str RAW ) RETURN RAW IS

BEGIN

RETURN dbms_crypto.decrypt(encry_str,typ,key);

END;

END;

/

select crypt_pkg.encry(utl_i18n.string_to_raw('hello serapy ! ')) 加密

FROM dual;

加密

--------------------------------------------------------------------------------

E004CD9F40933241D66B39FC281526AF

select

utl_i18n.raw_to_char(crypt_pkg.decry(‘E004CD9F40933241D66B39FC281

526AF’)) 解密

FROM dual;

解密

--------------------------------------------------------------------------------

hello serapy !

SQL> spool off;

select crypt_pkg.encry(utl_i18n.string_to_raw('hello serapy ! ')) 加密

FROM dual;

加密

--------------------------------------------------------------------------------

E004CD9F40933241D66B39FC281526AF

select

utl_i18n.raw_to_char(crypt_pkg.decry(‘E004CD9F40933241D66B39FC281

526AF’)) 解密

FROM dual;

解密

--------------------------------------------------------------------------------

hello serapy !

SQL> spool off;

Page 87: 3.oracle 11g 透明数据加密(91 页)

87/91

附录3:DBMS_CRYPTO包样例

♠ 用dbms_crypto-11g:

♠ PL/SQL 方法 : DECLARE

input_string VARCHAR2(16) := 'tigertigertigert';

raw_input RAW(128) :=

UTL_RAW.CAST_TO_RAW(CONVERT(input_string,'AL32UTF8','US7ASCII'));

key_string VARCHAR2(8) := 'scottsco';

raw_key RAW(128) :=

UTL_RAW.CAST_TO_RAW(CONVERT(key_string,'AL32UTF8','US7ASCII'));

encrypted_raw RAW(2048);

encrypted_string VARCHAR2(2048);

decrypted_raw RAW(2048);

decrypted_string VARCHAR2(2048);

-- Begin testing Encryption:

BEGIN

dbms_output.put_line('> Input String : ' ||

CONVERT(UTL_RAW.CAST_TO_VARCHAR2(raw_input),'US7ASCII','AL32UTF8'));

dbms_output.put_line('> ========= BEGIN TEST Encrypt =========');

encrypted_raw := dbms_crypto.Encrypt(

src => raw_input,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

dbms_output.put_line('> Encrypted hex value : ' ||

rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

decrypted_raw := dbms_crypto.Decrypt(

src => encrypted_raw,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

decrypted_string :=

CONVERT(UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw),'US7ASCII','AL32UTF8');

dbms_output.put_line('> Decrypted string output : ' ||

decrypted_string);

if input_string = decrypted_string THEN

dbms_output.put_line('> String DES Encyption and Decryption successful');

END if;

dbms_output.put_line('');

dbms_output.put_line('> ========= BEGIN TEST Hash =========');

encrypted_raw := dbms_crypto.Hash(

src => raw_input,

typ => DBMS_CRYPTO.HASH_SH1);

dbms_output.put_line('> Hash value of input string : ' ||

rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

dbms_output.put_line('> ========= BEGIN TEST Mac =========');

encrypted_raw := dbms_crypto.Mac(

src => raw_input,

typ => DBMS_CRYPTO.HMAC_MD5,

key => raw_key);

dbms_output.put_line('> Message Authentication Code : ' ||

rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

dbms_output.put_line('');

dbms_output.put_line('> End of DBMS_CRYPTO tests ');

END;

/

DECLARE

input_string VARCHAR2(16) := 'tigertigertigert';

raw_input RAW(128) :=

UTL_RAW.CAST_TO_RAW(CONVERT(input_string,'AL32UTF8','US7ASCII'));

key_string VARCHAR2(8) := 'scottsco';

raw_key RAW(128) :=

UTL_RAW.CAST_TO_RAW(CONVERT(key_string,'AL32UTF8','US7ASCII'));

encrypted_raw RAW(2048);

encrypted_string VARCHAR2(2048);

decrypted_raw RAW(2048);

decrypted_string VARCHAR2(2048);

-- Begin testing Encryption:

BEGIN

dbms_output.put_line('> Input String : ' ||

CONVERT(UTL_RAW.CAST_TO_VARCHAR2(raw_input),'US7ASCII','AL32UTF8'));

dbms_output.put_line('> ========= BEGIN TEST Encrypt =========');

encrypted_raw := dbms_crypto.Encrypt(

src => raw_input,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

dbms_output.put_line('> Encrypted hex value : ' ||

rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

decrypted_raw := dbms_crypto.Decrypt(

src => encrypted_raw,

typ => DBMS_CRYPTO.DES_CBC_PKCS5,

key => raw_key);

decrypted_string :=

CONVERT(UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw),'US7ASCII','AL32UTF8');

dbms_output.put_line('> Decrypted string output : ' ||

decrypted_string);

if input_string = decrypted_string THEN

dbms_output.put_line('> String DES Encyption and Decryption successful');

END if;

dbms_output.put_line('');

dbms_output.put_line('> ========= BEGIN TEST Hash =========');

encrypted_raw := dbms_crypto.Hash(

src => raw_input,

typ => DBMS_CRYPTO.HASH_SH1);

dbms_output.put_line('> Hash value of input string : ' ||

rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

dbms_output.put_line('> ========= BEGIN TEST Mac =========');

encrypted_raw := dbms_crypto.Mac(

src => raw_input,

typ => DBMS_CRYPTO.HMAC_MD5,

key => raw_key);

dbms_output.put_line('> Message Authentication Code : ' ||

rawtohex(UTL_RAW.CAST_TO_RAW(encrypted_raw)));

dbms_output.put_line('');

dbms_output.put_line('> End of DBMS_CRYPTO tests ');

END;

/

Page 88: 3.oracle 11g 透明数据加密(91 页)

88/91

附录4:DBMS_CRYPTO包样例

♠ 用dbms_crypto-11g:

♠ AES 256-Bit 数据加密与解密: declare

input_string VARCHAR2 (200) := 'Secret Message';

output_string VARCHAR2 (200);

encrypted_raw RAW (2000); -- stores encrypted binary text

decrypted_raw RAW (2000); -- stores decrypted binary text

num_key_bytes NUMBER := 256/8; -- key length 256 bits (32 bytes)

key_bytes_raw RAW (32); -- stores 256-bit encryption key

encryption_type PLS_INTEGER := -- total encryption type

DBMS_CRYPTO.ENCRYPT_AES256

+ DBMS_CRYPTO.CHAIN_CBC

+ DBMS_CRYPTO.PAD_PKCS5;

begin

DBMS_OUTPUT.PUT_LINE ('Original string: ' || input_string);

key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes);

encrypted_raw := DBMS_CRYPTO.ENCRYPT

(

src => UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8'),

typ => encryption_type,

key => key_bytes_raw

);

-- The encrypted value in the encrypted_raw variable can be used here:

decrypted_raw := DBMS_CRYPTO.DECRYPT

(

src => encrypted_raw,

typ => encryption_type,

key => key_bytes_raw

);

output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');

DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);

end;

declare

input_string VARCHAR2 (200) := 'Secret Message';

output_string VARCHAR2 (200);

encrypted_raw RAW (2000); -- stores encrypted binary text

decrypted_raw RAW (2000); -- stores decrypted binary text

num_key_bytes NUMBER := 256/8; -- key length 256 bits (32 bytes)

key_bytes_raw RAW (32); -- stores 256-bit encryption key

encryption_type PLS_INTEGER := -- total encryption type

DBMS_CRYPTO.ENCRYPT_AES256

+ DBMS_CRYPTO.CHAIN_CBC

+ DBMS_CRYPTO.PAD_PKCS5;

begin

DBMS_OUTPUT.PUT_LINE ('Original string: ' || input_string);

key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes);

encrypted_raw := DBMS_CRYPTO.ENCRYPT

(

src => UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8'),

typ => encryption_type,

key => key_bytes_raw

);

-- The encrypted value in the encrypted_raw variable can be used here:

decrypted_raw := DBMS_CRYPTO.DECRYPT

(

src => encrypted_raw,

typ => encryption_type,

key => key_bytes_raw

);

output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');

DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);

end;

Page 89: 3.oracle 11g 透明数据加密(91 页)

89/91

附录5:DBMS_CRYPTO包样例

♠ 用dbms_crypto-11g:

♠ BLOB 数据加密与解密: *Creates a table for the BLOB column

*Inserts the raw values into that table

*Encrypts the raw data

*Decrypts the encrypted data

The blob_test.sql procedure follows:

-- 1. Create a table for BLOB column:

create table table_lob (id number, loc blob);

-- 2. Insert 3 empty lobs for src/enc/dec:

insert into table_lob values (1, EMPTY_BLOB());

insert into table_lob values (2, EMPTY_BLOB());

insert into table_lob values (3, EMPTY_BLOB());

set echo on

set serveroutput on

declare

srcdata RAW(1000);

srcblob BLOB;

encrypblob BLOB;

encrypraw RAW(1000);

encrawlen BINARY_INTEGER;

decrypblob BLOB;

decrypraw RAW(1000);

decrawlen BINARY_INTEGER;

leng INTEGER;

begin

-- RAW input data 16 bytes

srcdata := hextoraw('6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D');

dbms_output.put_line('---');

dbms_output.put_line('input is ' || srcdata);

dbms_output.put_line('---');

-- select empty lob locators for src/enc/dec

select loc into srcblob from table_lob where id = 1;

select loc into encrypblob from table_lob where id = 2;

select loc into decrypblob from table_lob where id = 3;

dbms_output.put_line('Created Empty LOBS');

dbms_output.put_line('---');

leng := DBMS_LOB.GETLENGTH(srcblob);

IF leng IS NULL THEN

dbms_output.put_line('Source BLOB Len NULL ');

ELSE

dbms_output.put_line('Source BLOB Len ' || leng);

END IF;

leng := DBMS_LOB.GETLENGTH(encrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Encrypt BLOB Len NULL ');

ELSE

dbms_output.put_line('Encrypt BLOB Len ' || leng);

END IF;

leng := DBMS_LOB.GETLENGTH(decrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Decrypt BLOB Len NULL ');

ELSE

dbms_output.put_line('Decrypt BLOB Len ' || leng);

END IF;

-- 3. Write source raw data into blob:

DBMS_LOB.OPEN (srcblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.WRITEAPPEND (srcblob, 16, srcdata);

DBMS_LOB.CLOSE (srcblob);

dbms_output.put_line('Source raw data written to source blob');

dbms_output.put_line('---');

leng := DBMS_LOB.GETLENGTH(srcblob);

IF leng IS NULL THEN

dbms_output.put_line('source BLOB Len NULL ');

ELSE

dbms_output.put_line('Source BLOB Len ' || leng);

END IF;

/*

* Procedure Encrypt

* Arguments: srcblob -> Source BLOB

* encrypblob -> Output BLOB for encrypted data

* DBMS_CRYPTO.AES_CBC_PKCS5 -> Algo : AES

* Chaining : CBC

* Padding : PKCS5

* 256 bit key for AES passed as RAW

* ->

hextoraw('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F')

* IV (Initialization Vector) for AES algo passed as RAW

* -> hextoraw('00000000000000000000000000000000')

*/

DBMS_CRYPTO.Encrypt(encrypblob,

srcblob,

DBMS_CRYPTO.AES_CBC_PKCS5,

hextoraw ('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F'),

hextoraw('00000000000000000000000000000000'));

dbms_output.put_line('Encryption Done');

dbms_output.put_line('---');

leng := DBMS_LOB.GETLENGTH(encrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Encrypt BLOB Len NULL');

ELSE

dbms_output.put_line('Encrypt BLOB Len ' || leng);

END IF;

-- 4. Read encrypblob to a raw:

encrawlen := 999;

DBMS_LOB.OPEN (encrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.READ (encrypblob, encrawlen, 1, encrypraw);

DBMS_LOB.CLOSE (encrypblob);

dbms_output.put_line('Read encrypt blob to a raw');

dbms_output.put_line('---');

dbms_output.put_line('Encrypted data is (256 bit key) ' || encrypraw);

dbms_output.put_line('---');

/*

* Procedure Decrypt

* Arguments: encrypblob -> Encrypted BLOB to decrypt

* decrypblob -> Output BLOB for decrypted data in RAW

* DBMS_CRYPTO.AES_CBC_PKCS5 -> Algo : AES

* Chaining : CBC

* Padding : PKCS5

* 256 bit key for AES passed as RAW (same as used during Encrypt)

* ->

hextoraw('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F')

* IV (Initialization Vector) for AES algo passed as RAW (same as

used during Encrypt)

* -> hextoraw('00000000000000000000000000000000')

*/

DBMS_CRYPTO.Decrypt(decrypblob,

encrypblob,

DBMS_CRYPTO.AES_CBC_PKCS5,

hextoraw

('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F'),

hextoraw('00000000000000000000000000000000'));

leng := DBMS_LOB.GETLENGTH(decrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Decrypt BLOB Len NULL');

ELSE

dbms_output.put_line('Decrypt BLOB Len ' || leng);

END IF;

-- Read decrypblob to a raw

decrawlen := 999;

DBMS_LOB.OPEN (decrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.READ (decrypblob, decrawlen, 1, decrypraw);

DBMS_LOB.CLOSE (decrypblob);

dbms_output.put_line('Decrypted data is (256 bit key) ' || decrypraw);

dbms_output.put_line('---');

DBMS_LOB.OPEN (srcblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.TRIM (srcblob, 0);

DBMS_LOB.CLOSE (srcblob);

DBMS_LOB.OPEN (encrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.TRIM (encrypblob, 0);

DBMS_LOB.CLOSE (encrypblob);

DBMS_LOB.OPEN (decrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.TRIM (decrypblob, 0);

DBMS_LOB.CLOSE (decrypblob);

end;

/

truncate table table_lob;

drop table table_lob;

*Creates a table for the BLOB column

*Inserts the raw values into that table

*Encrypts the raw data

*Decrypts the encrypted data

The blob_test.sql procedure follows:

-- 1. Create a table for BLOB column:

create table table_lob (id number, loc blob);

-- 2. Insert 3 empty lobs for src/enc/dec:

insert into table_lob values (1, EMPTY_BLOB());

insert into table_lob values (2, EMPTY_BLOB());

insert into table_lob values (3, EMPTY_BLOB());

set echo on

set serveroutput on

declare

srcdata RAW(1000);

srcblob BLOB;

encrypblob BLOB;

encrypraw RAW(1000);

encrawlen BINARY_INTEGER;

decrypblob BLOB;

decrypraw RAW(1000);

decrawlen BINARY_INTEGER;

leng INTEGER;

begin

-- RAW input data 16 bytes

srcdata := hextoraw('6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D');

dbms_output.put_line('---');

dbms_output.put_line('input is ' || srcdata);

dbms_output.put_line('---');

-- select empty lob locators for src/enc/dec

select loc into srcblob from table_lob where id = 1;

select loc into encrypblob from table_lob where id = 2;

select loc into decrypblob from table_lob where id = 3;

dbms_output.put_line('Created Empty LOBS');

dbms_output.put_line('---');

leng := DBMS_LOB.GETLENGTH(srcblob);

IF leng IS NULL THEN

dbms_output.put_line('Source BLOB Len NULL ');

ELSE

dbms_output.put_line('Source BLOB Len ' || leng);

END IF;

leng := DBMS_LOB.GETLENGTH(encrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Encrypt BLOB Len NULL ');

ELSE

dbms_output.put_line('Encrypt BLOB Len ' || leng);

END IF;

leng := DBMS_LOB.GETLENGTH(decrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Decrypt BLOB Len NULL ');

ELSE

dbms_output.put_line('Decrypt BLOB Len ' || leng);

END IF;

-- 3. Write source raw data into blob:

DBMS_LOB.OPEN (srcblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.WRITEAPPEND (srcblob, 16, srcdata);

DBMS_LOB.CLOSE (srcblob);

dbms_output.put_line('Source raw data written to source blob');

dbms_output.put_line('---');

leng := DBMS_LOB.GETLENGTH(srcblob);

IF leng IS NULL THEN

dbms_output.put_line('source BLOB Len NULL ');

ELSE

dbms_output.put_line('Source BLOB Len ' || leng);

END IF;

/*

* Procedure Encrypt

* Arguments: srcblob -> Source BLOB

* encrypblob -> Output BLOB for encrypted data

* DBMS_CRYPTO.AES_CBC_PKCS5 -> Algo : AES

* Chaining : CBC

* Padding : PKCS5

* 256 bit key for AES passed as RAW

* ->

hextoraw('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F')

* IV (Initialization Vector) for AES algo passed as RAW

* -> hextoraw('00000000000000000000000000000000')

*/

DBMS_CRYPTO.Encrypt(encrypblob,

srcblob,

DBMS_CRYPTO.AES_CBC_PKCS5,

hextoraw ('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F'),

hextoraw('00000000000000000000000000000000'));

dbms_output.put_line('Encryption Done');

dbms_output.put_line('---');

leng := DBMS_LOB.GETLENGTH(encrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Encrypt BLOB Len NULL');

ELSE

dbms_output.put_line('Encrypt BLOB Len ' || leng);

END IF;

-- 4. Read encrypblob to a raw:

encrawlen := 999;

DBMS_LOB.OPEN (encrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.READ (encrypblob, encrawlen, 1, encrypraw);

DBMS_LOB.CLOSE (encrypblob);

dbms_output.put_line('Read encrypt blob to a raw');

dbms_output.put_line('---');

dbms_output.put_line('Encrypted data is (256 bit key) ' || encrypraw);

dbms_output.put_line('---');

/*

* Procedure Decrypt

* Arguments: encrypblob -> Encrypted BLOB to decrypt

* decrypblob -> Output BLOB for decrypted data in RAW

* DBMS_CRYPTO.AES_CBC_PKCS5 -> Algo : AES

* Chaining : CBC

* Padding : PKCS5

* 256 bit key for AES passed as RAW (same as used during Encrypt)

* ->

hextoraw('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F')

* IV (Initialization Vector) for AES algo passed as RAW (same as

used during Encrypt)

* -> hextoraw('00000000000000000000000000000000')

*/

DBMS_CRYPTO.Decrypt(decrypblob,

encrypblob,

DBMS_CRYPTO.AES_CBC_PKCS5,

hextoraw

('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F'),

hextoraw('00000000000000000000000000000000'));

leng := DBMS_LOB.GETLENGTH(decrypblob);

IF leng IS NULL THEN

dbms_output.put_line('Decrypt BLOB Len NULL');

ELSE

dbms_output.put_line('Decrypt BLOB Len ' || leng);

END IF;

-- Read decrypblob to a raw

decrawlen := 999;

DBMS_LOB.OPEN (decrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.READ (decrypblob, decrawlen, 1, decrypraw);

DBMS_LOB.CLOSE (decrypblob);

dbms_output.put_line('Decrypted data is (256 bit key) ' || decrypraw);

dbms_output.put_line('---');

DBMS_LOB.OPEN (srcblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.TRIM (srcblob, 0);

DBMS_LOB.CLOSE (srcblob);

DBMS_LOB.OPEN (encrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.TRIM (encrypblob, 0);

DBMS_LOB.CLOSE (encrypblob);

DBMS_LOB.OPEN (decrypblob, DBMS_LOB.lob_readwrite);

DBMS_LOB.TRIM (decrypblob, 0);

DBMS_LOB.CLOSE (decrypblob);

end;

/

truncate table table_lob;

drop table table_lob;

Page 90: 3.oracle 11g 透明数据加密(91 页)

90/91

参考资源

♠ Oracle 原厂: ♠ Oracle® Database

♠ Advanced Security Administrator’s Guide

♠ 10g Release 2 (10.2) B14268-01

♠ Oracle® Database

♠ Advanced Security Administrator’s Guide

♠ 11g Release 2 (11.2)E10746-01

Page 91: 3.oracle 11g 透明数据加密(91 页)

91/91

参考资源

♠ Oracle 原厂: ♠ Oracle® Database Security Guide

11g Release 2 (11.2)

Part Number E10574-04