ORACLE使用透明數據庫加密
--官網文檔:https://www.oracle.com/technetwork/cn/tutorials/tde-096009-zhs.html#t
Oracle 數據庫 10g 第 2 版透明數據庫加密功能簡化了信用卡號碼以及社會安全保險號等機密我的信息的加密。 使用透明數據加密功能,沒必要將加密例程嵌套到現有應用程序中,顯著下降了加密的成本和複雜性。
大多數加密解決方案都須要在應用程序代碼中對調用加密函數。 這樣作開銷很高,由於它一般須要深刻了解應用程序並要可以編寫和維護軟件。
經過 SQL 執行的應用程序邏輯不須要進行更改,仍能正常運行。 Oracle 數據庫在將信息寫入磁盤以前將自動對數據進行加密,隨後的選擇操做將透明地解密數據,所以應用程序將繼續正常地運行。html
設置加密密鑰:Oracle 透明數據加密提供了實施加密所必需的關鍵管理基礎架構。 加密的工做原理是將明文數據以及祕密(稱做密鑰)傳遞到加密程序中。 加密程序使用提供的密鑰對明文數據進行加密,而後返回加密數據。 以往,建立和維護密鑰的任務由應用程序完成。 Oracle 透明數據加密經過爲整個數據庫自動生成一個萬能密鑰解決了此問題。 在啓動 Oracle 數據庫時,管理員必須使用不一樣於系統口令或 DBA 口令的口令打開一個 Oracle Wallet 對象。 而後,管理員對數據庫萬能密鑰進行初始化。 萬能密鑰是自動生成的。算法
性能:因爲索引數據未被加密,所以加密一般會影響現有的應用程序索引。 Oracle 透明數據加密對與給定應用程序表關聯的索引值進行加密。 這意味着應用程序中的相等搜索對性能的影響很小,甚至沒有任何影響。 例如,假設應用程序 PERSON ID 存在一個索引,而且此應用程序執行如下語句:
--Oracle 數據庫將使用現有的應用程序索引,儘管 PERSON ID 信息已經在數據庫中加密。
SQL> Select rating from credit where person id = '23590';sql
建立一個包含加密列的表,爲加密列建立一個索引,並授予訪問某個用戶的列的權限, 而後,您將建立一個包含對加密數據進行相應訪問控制的函數,隨後經過 VPD 策略應用該函數。
透明數據加密在數據寫入磁盤以前對其進行加密,並在讀取該數據時將其解密。 這對全部使用 SQL 層的應用程序都是透明的。 所以,沒法輕鬆地驗證數據是否真正被加密。 因爲 Oracle LogMiner 對寫入磁盤的數據進行記錄,所以您能夠訪問該信息。數據庫
準備用於加密的數據庫
在本部份內容中,您將更新 sqlnet.ora、建立一個加密錢夾 (ewallet.p12)、打開此錢夾併爲 TDE 建立萬能密鑰。執行如下操做:
1.您須要更新 sqlnet.ora 文件以包含一個 ENCRYPTED_WALLET_LOCATION 條目。打開一個終端窗口,而後輸入如下命令:
cd $ORACLE_HOME/network/admin
gedit sqlnet.ora安全
--將如下條目添加到文件末尾,能夠爲加密錢夾選擇任何目錄,但路徑不該指向在數據庫安裝過程當中建立的標準模糊錢夾 (cwallet.sso):
ENCRYPTION_WALLET_LOCATION=
(SOURCE=(METHOD=FILE)(METHOD_DATA=
(DIRECTORY=/u01/app/oracle/product/10.2.0/db_1/)))session
2.接下來,您須要打開錢夾並建立萬能加密密鑰。從終端窗口中,輸入如下命令:
cd /home/oracle/wkdir
sqlplus /nolog
@tde00_dbsetup架構
--只有擁有「alter system」權限的用戶才能建立萬能密鑰或打開錢夾;萬能密鑰只能建立一次,除非您想要使用新的加密密鑰從新加密數據
connect / as sysdba
--若是指定的目錄中不存在加密錢夾,則將建立加密錢夾 (ewallet.p12)、打開此錢夾並建立/從新建立 TDE 的萬能密鑰; 若是指定目錄中存在加密錢夾,則將打開此錢夾並建立/從新建立 TDE 的萬能密鑰。
alter system set key identified by "welcome1";oracle
--須要打開錢夾(它在您關閉數據庫時已經關閉),但您不但願建立一個新的萬能密鑰
alter system set wallet open identified by "welcome1";app
因爲每一個表都有各自的加密密鑰,所以萬能加密密鑰是必需的。這些列密鑰存儲在數據庫中。 因爲錢夾只能存儲有限數目的密鑰,而且可伸縮性不高,所以使用萬能密鑰加密列密鑰。 這樣,您即可以擁有所需數量的列密鑰,而且錢夾中只存儲少許的萬能密鑰(包括過時密鑰,當您某一天從舊的備份磁帶解密數據時可能須要它)。 默認狀況下,以上命令使用 192 位的高級加密標準 (AES192) 生成一個密鑰。 也可使用 3DES,或使用較小或較大的 AES 加密位數。ide
--建立一個包含加密列的表,爲加密列建立索引並授予數據的訪問權限。執行如下操做:
1.首先須要建立一些用戶。從 SQL*Plus 會話中,執行如下腳本:
@tde01_crusers
connect system/oracle
prompt Create users: JKING, LSMITH and LDORAN
grant connect to JKING identified by welcome1;
grant connect, DBA to LSMITH identified by welcome1;
grant connect to LDORAN identified by welcome1;
注意: 您已經授予了 LSMITH DBA 角色,以演示 TDE 對相等性搜索索引的支持。 所以,dbms_xplan 的輸出應包含 INDEX RANGE SCAN。
2.接下來,您將建立一個表,其中包含一個用於存儲加密(默認爲 AES192)信用卡信息的列。 因爲 credit_card_number 將有一個索引,所以未指定 SALT,當對加密值進行 salt 處理時將不會生成索引。從 SQL*Plus 會話中,執行如下腳本:
@tde02_crtabl
connect oe/oe
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));
3.如今,能夠向剛剛建立的表中添加一些數據。從 SQL*Plus 會話中,執行如下腳本:
@tde03_poptabl
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');
4.爲提升性能,您將爲信用卡號碼建立一個索引。從 SQL*Plus 會話中,執行如下腳本:
@tde04_cridx
create index cust_payment_info_idx on cust_payment_info (credit_card_number);
5.須要向用戶授予客戶付款信息表的訪問權限。 在本實例中,LSMITH 是惟一一個能夠更新此信息的用戶。 其餘用戶只能查看它。從 SQL*Plus 會話中,執行如下腳本:
@tde05_grant_access
grant select on oe.CUST_PAYMENT_INFO to LDORAN;
grant select, update on oe.CUST_PAYMENT_INFO to LSMITH;
grant select on oe.CUST_PAYMENT_INFO to JKING;
在本部分中,您將以 LSMITH 的身份對錶進行更改。執行如下操做:
1.因爲您授與了 LSMITH 更新訪問權限,所以可以進行更改。從 SQL*Plus 會話中,執行如下腳本:
@tde06_make_update
prompt *** Connect as Lindsay Smith (Card_V)
conn LSMITH/welcome1;
update oe.CUST_PAYMENT_INFO set ACTIVE_CARD='NO'
where CREDIT_CARD_NUMBER='4556988708236902';
2.要查看執行計劃,請執行如下腳本:
@tde06a_review_xplan
select * from table (dbms_xplan.display_cursor);
3.表 user_encrypted_columns 將通知您哪一個列已經加密以及它的加密算法。從 SQL*Plus 會話中,執行如下腳本:
@tde07_select_encrypt_col
connect oe/oe
col TABLE_NAME format a18;
col COLUMN_NAME format a19;
col ENCRYPTION_ALG format a17;
select * from user_encrypted_columns;
添加並應用 VPD 策略
因爲加密並不替換相應的訪問控制,所以您將使用一個很是簡單的 VPD 策略限制行的訪問權限。 首先,您將檢查登陸到數據庫的用戶是不是員工,而後將按信用卡號碼限制 oe.cust_payment_info 的訪問權限:
Card_A 從「34」或「37」開始 Janette King
Card_V 從「4」開始 Lindsay Smith
Card_M 從「5」開始 Louise Doran
若是查看加載到表中的數據,則會看到,受權用戶將沒法選擇與「Albert Einstein」關聯的信用卡號碼。 只有避開訪問控制策略的入侵者或不受這些策略約束的管理用戶才能夠選擇它。 這能夠對該表進行高度集中的審計。
執行如下操做:
1.首先須要建立包含信用卡和員工驗證所需邏輯的表。從 SQL*Plus 會話中,執行如下腳本:
@tde08_crfunction
connect system/oracle;
prompt
prompt *** Create policy function to create the where-clause:
create or replace function f_policy_oe_cust_payment_info
-- Function must have the following parameters
(schema in varchar2, tab in varchar2)
-- Function will return a string that is used as a WHERE clause
return varchar2
as
v_manager_id number:=0;
is_employee number:=0;
v_user varchar2(20);
out_string varchar2(70) default '1=2 ';
begin
-- get session user
v_user := lower(sys_context('userenv','session_user'));
-- Is the user an employee?
begin
select manager_id into v_manager_id
from hr.employees
where lower(email) = v_user;
is_employee:=1;
exception
when no_data_found then
is_employee:=2;
end;
-- create where clause when user is authorized to see parts of the table
if is_employee=1 and lower(v_user)='jking' and v_manager_id=146 then
out_string := out_string ||'or CREDIT_CARD_NUMBER like ''34%''
or CREDIT_CARD_NUMBER like ''37%''';
elsif is_employee=1 and lower(v_user)='lsmith' and v_manager_id=146 then
out_string := out_string ||'or CREDIT_CARD_NUMBER like ''4%''';
elsif is_employee=1 and lower(v_user)='ldoran' and v_manager_id=146 then
out_string := out_string ||'or CREDIT_CARD_NUMBER like ''5%''';
end if;
return out_string;
end;
/
2.如今,能夠將該策略添加到 cust_payment_info 表中。從 SQL*Plus 會話中,執行如下腳本:
@tde09_addpolicy
prompt
prompt *** Add policy to 'oe.cust_payment_info' table:
begin
dbms_rls.add_policy('oe','cust_payment_info','ac_cust_payment_info',
'system','f_policy_oe_cust_payment_info', policy_type => dbms_rls.context_sensitive);
end;
/
--測試策略,將以每一個員工的身份鏈接以查看該策略是否起做用。 有三個方面能夠體現 TDE 的真正透明性:
加密列已經使用索引
即便加密存儲了信用卡號碼,VPD 策略中的 where 子句仍搜索明文格式的號碼並檢索相應的行。
對三名員工可見的行包含明文格式的信用卡號碼。 一般,員工甚至不知道已經加密存儲了數據。
1.您將首先以 Janette King 的身份鏈接。 她能夠訪問從「34」或「37」開始的 Card_A。從 SQL*Plus 會話中,執行如下腳本:
@tde10_testpolicy_jking
prompt
prompt *** Connect as Janette King (Card_A)
conn JKING/welcome1;
col CREDIT_CARD_NUMBER heading Card_A format a18;
select * from oe.CUST_PAYMENT_INFO order by CREDIT_CARD_NUMBER;
2.您如今將以 Louise Doran 的身份鏈接。 她能夠訪問從「5」開始的 Card_M。從 SQL*Plus 會話中,執行如下腳本:
@tde11_testpolicy_ldoran
prompt
prompt *** Connect as Louise Doran (Card_M)
conn LDORAN/welcome1;
col CREDIT_CARD_NUMBER heading Card_M format a18;
select * from oe.CUST_PAYMENT_INFO order by CREDIT_CARD_NUMBER;
3.而後,您將以 Lindsay Smith 的身份鏈接。 她能夠訪問從「4」開始的 Card_V。從 SQL*Plus 會話中,執行如下腳本:
@tde12_testpolicy_lsmith
prompt
prompt *** Connect as Lindsay Smith (Card_V)
conn LSMITH/welcome1;
col CREDIT_CARD_NUMBER heading Card_V format a18;
select * from oe.CUST_PAYMENT_INFO order by CREDIT_CARD_NUMBER;
--使用 LogMiner 查看重作日誌
因爲 TDE 是在寫入數據以前執行的而且對全部應用程序都是透明的,所以沒法輕鬆地驗證是否真正加密了數據。 因爲 Oracle LogMiner 記錄寫入磁盤的數據,所以可使用它查看日誌文件中包含的內容。執行如下步驟:
1.從 SQL*Plus 會話中,執行如下腳本:
@tde13_logminer
connect / as sysdba;
alter database add supplemental log data;
REM select member as LOG_FILE_LOCATION from v$logfile;
EXECUTE DBMS_LOGMNR.ADD_LOGFILE
('+MY_DG2/racdb/onlinelog/group_3.263.562151437', DBMS_LOGMNR.NEW);
EXECUTE DBMS_LOGMNR.ADD_LOGFILE
('+MY_DG2/racdb/onlinelog/group_2.262.562151433', DBMS_LOGMNR.ADDFILE);
EXECUTE DBMS_LOGMNR.ADD_LOGFILE
('+MY_DG2/racdb/onlinelog/group_1.261.562151431', DBMS_LOGMNR.ADDFILE)
prompt start LogMiner:
EXECUTE DBMS_LOGMNR.START_LOGMNR
(options => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.COMMITTED_DATA_ONLY);
select sql_redo from v$logmnr_contents where
table_name = 'CUST_PAYMENT_INFO' and operation='INSERT';
--LogMiner 不支持加密數據,所以 credit_card_number 列中的加密值顯示爲 Unsupported Type。
--在無加密列的狀況下從新建立表,爲顯示在未對列進行加密的狀況下將看到的內容之間的差別,要刪除該表並在無加密列的狀況下從新建立它。執行如下操做:
1.從 SQL*Plus 會話中,執行如下腳本:
@tde14_crtabl2
connect oe/oe
drop table cust_payment_info;
create table cust_payment_info
(first_name varchar2(11),
last_name varchar2(10),
order_number number(5),
credit_card_number varchar2(20),
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');
create index cust_payment_info_idx on cust_payment_info (credit_card_number);
grant select on oe.CUST_PAYMENT_INFO to LDORAN;
grant select, update on oe.CUST_PAYMENT_INFO to LSMITH;
grant select on oe.CUST_PAYMENT_INFO to JKING;
prompt *** Connect as Lindsay Smith (Card_V)
conn LSMITH/welcome1;
update oe.CUST_PAYMENT_INFO set ACTIVE_CARD='NO'
where CREDIT_CARD_NUMBER=4556988708236902;
--查看重作日誌,從新運行 logminer 腳原本查看它所包含的內容
1.從 SQL*Plus 會話中,執行如下腳本:
@tde15_logminer2
connect / as sysdba;
EXECUTE DBMS_LOGMNR.ADD_LOGFILE
('+MY_DG2/racdb/onlinelog/group_3.263.562151437', DBMS_LOGMNR.NEW);
EXECUTE DBMS_LOGMNR.ADD_LOGFILE
('+MY_DG2/racdb/onlinelog/group_2.262.562151433', DBMS_LOGMNR.ADDFILE);
EXECUTE DBMS_LOGMNR.ADD_LOGFILE
('+MY_DG2/racdb/onlinelog/group_1.261.562151431', DBMS_LOGMNR.ADDFILE)
prompt start LogMiner:
EXECUTE DBMS_LOGMNR.START_LOGMNR
(options => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.COMMITTED_DATA_ONLY);
select sql_redo from v$logmnr_contents where
table_name = 'CUST_PAYMENT_INFO' and operation='INSERT';
--該列未加密,且 LogMiner 顯示已寫入磁盤的名文數據。
--要清理環境,請執行如下步驟:
1.從 SQL*Plus 會話中,執行如下腳本:
@tde16_cleanup
connect system/oracledrop user JKING cascade;drop user LSMITH cascade;drop user LDORAN cascade;drop function f_policy_oe_cust_payment_info;connect oe/oedrop table cust_payment_info;exit;