1. 程式人生 > >ORACLE透明加密

ORACLE透明加密

--官網文件:https://www.oracle.com/technetwork/cn/tutorials/tde-096009-zhs.html#t
概述
Oracle 資料庫 10g 第 2 版透明資料庫加密功能簡化了信用卡號碼以及社會安全保險號等機密個人資訊的加密。 使用透明資料加密功能,不必將加密例程巢狀到現有應用程式中,顯著降低了加密的成本和複雜性。
大多數加密解決方案都需要在應用程式程式碼中對呼叫加密函式。 這樣做開銷很高,因為它通常需要深入瞭解應用程式並要能夠編寫和維護軟體。
通過 SQL 執行的應用程式邏輯不需要進行更改,仍能正常執行。 Oracle 資料庫在將資訊寫入磁碟之前將自動對資料進行加密,隨後的選擇操作將透明地解密資料,因此應用程式將繼續正常地執行。

設定加密金鑰:Oracle 透明資料加密提供了實施加密所必需的關鍵管理基礎架構。 加密的工作原理是將明文資料以及祕密(稱作金鑰)傳遞到加密程式中。 加密程式使用提供的金鑰對明文資料進行加密,然後返回加密資料。 以往,建立和維護金鑰的任務由應用程式完成。 Oracle 透明資料加密通過為整個資料庫自動生成一個萬能金鑰解決了此問題。 在啟動 Oracle 資料庫時,管理員必須使用不同於系統口令或 DBA 口令的口令開啟一個 Oracle Wallet 物件。 然後,管理員對資料庫萬能金鑰進行初始化。 萬能金鑰是自動生成的。

效能:由於索引資料未被加密,因此加密通常會影響現有的應用程式索引。 Oracle 透明資料加密對與給定應用程式表關聯的索引值進行加密。 這意味著應用程式中的相等搜尋對效能的影響很小,甚至沒有任何影響。 例如,假設應用程式 PERSON ID 存在一個索引,並且此應用程式執行以下語句:
--Oracle 資料庫將使用現有的應用程式索引,儘管 PERSON ID 資訊已經在資料庫中加密。
SQL> Select rating from credit where person id = '23590';

建立一個包含加密列的表,為加密列建立一個索引,並授予訪問某個使用者的列的許可權, 然後,您將建立一個包含對加密資料進行相應訪問控制的函式,隨後通過 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/)))

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";

--需要開啟錢夾(它在您關閉資料庫時已經關閉),但您不希望建立一個新的萬能金鑰
alter system set wallet open identified by "welcome1";

由於每個表都有各自的加密金鑰,因此萬能加密金鑰是必需的。這些列金鑰儲存在資料庫中。 由於錢夾只能儲存有限數目的金鑰,並且可伸縮性不高,因此使用萬能金鑰加密列金鑰。 這樣,您便可以擁有所需數量的列金鑰,並且錢夾中只儲存少量的萬能金鑰(包括過期金鑰,當您某一天從舊的備份磁帶解密資料時可能需要它)。 預設情況下,以上命令使用 192 位的高階加密標準 (AES192) 生成一個金鑰。 也可以使用 3DES,或使用較小或較大的 AES 加密位數。

--建立一個包含加密列的表,為加密列建立索引並授予資料的訪問許可權。執行以下操作:
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/oracle
drop user JKING cascade;
drop user LSMITH cascade;
drop user LDORAN cascade;
drop function f_policy_oe_cust_payment_info;
connect oe/oe
drop table cust_payment_info;
exit;