1. 程式人生 > >Oracle 透明資料加密TDE

Oracle 透明資料加密TDE

透明資料加密TDE

Oracle 10g R2提供了一個新的特性,讓你只需要做如下動作:你可以不寫一行程式碼,只需要宣告你需要加密某列。當用戶插入資料的時候,資料庫透明的加密資料然後儲存加密後的資料。同樣的,當用戶讀取資料時,資料庫自動進行節目。由於加解密操作對應用程式來說都是透明的,不需要應用程式修改程式碼,因此這個特性就叫做:透明資料加密(TDE

1 TDE如何工作?

我在January/February 2005 issue of Oracle Magazine上提到了Oracle 10g資料庫加密的基本原理。現在我們概述一下關鍵點:加密時你需要應用一個加密演算法和一個加密金鑰對明文輸入的資料進行加解密操作;為了能夠成功的解密,你必須知道加密採用的演算法和金鑰。

在那篇文章中,我描述瞭如何使用Oracle提供的加密工具來構建一個加密框架。然而,使用Oracle 10g R2資料庫和TDE,你將不需要自己構建這樣一個框架。你所要做的只是定義需要加密的列,Oracle 10g資料庫將為包含加密列的表建立一個私密(譯者注:使用者不需要知道)的安全加密金鑰,然後採用你指定的加密演算法加密指定列的明文資料

這種機制下,保護表的加密金鑰(以下簡稱“表金鑰”)就顯得非常重要了。Oracle 10g通過一個master金鑰來對錶金鑰進行加密。master金鑰儲存在一個叫做“錢夾(wallet)”的安全的地方,錢夾可以是資料庫伺服器上的一個檔案,加密的表金鑰儲存在資料字典中。

當用戶插入資料到需要加密的列中的時候,Oracle 10g從錢夾中獲取master金鑰,用master金鑰解密資料字典中的表金鑰,然後用解密後的表金鑰加密輸入資料,再將加密後的資料儲存在資料庫中。如下圖1所示:

圖1:TDE工作原理

你可以加密表的部分或者所有列,例如一個表有4列,如上圖1所示,第2列和第3列被加密,但Oracle只會生成一個表級的加密金鑰,然後用這個金鑰加密所有的加密列。在磁碟上,第1列和第4列是明文儲存的,第2列和第3列是加密儲存的。由於資料是加密儲存的,所有後續的組建例如備份和歸檔日誌,都是加密的格式。

當用戶查詢一個加密列的時候,Oracle 10g透明的(譯者注:使用者不可感知

)將加密的表金鑰從資料字典中取出,再取出master金鑰,然後解密表金鑰,再用解密後的表金鑰來解密磁碟上加密的資料,最後返回明文給使用者。

通過這種加密資料的方式,即使儲存在磁碟上的資料被盜,由於master金鑰並沒有被盜,沒有master金鑰的情況下,資料無法被獲取。即使“錢夾(wallet)”被盜,如果沒有錢夾密碼(譯者注:TDE涉及3個密碼,一個是錢夾密碼,用來啟動錢夾;一個是master金鑰,用來加解密表金鑰;一個是表金鑰,用來加解密資料,錢夾密碼是使用者手工輸入的,master金鑰和表金鑰是系統管理的),master金鑰還是無法獲取。因此,即使竊賊盜取了磁碟或者資料檔案的拷貝,也無法解密資料。這樣做滿足了很多規則和指南的要求,而所有的這些並不需要修改應用程式或者編寫複雜的加密和金鑰管理系統。

接下來我將向你展示如何開啟和使用TDE。

1.1 一次安裝

你第一次使用TDE時,必須1)指定“錢夾”的位置,2)設定錢夾密碼,3)開啟錢夾。

指定錢夾位置

當你第一啟用TDE,必須建立錢夾。預設情況下,錢夾創建於$ORACLE_BASE/admin/$ORACLE_SID/wallet目錄下。因此,如果$ORACLE_BASE是/u01/app/oracle且$ORACLE_SID是SWBT4,則錢夾將儲存在/u01/app/oracle/admin/SWBT4/wallet目錄下。你也可以通在位於$ORACLE_HOME/network/admin目錄下的sqlnet.ora檔案中指定的方式選擇一個不同的目錄。例如:如果你想講錢夾放在/orawall目錄下,在sqlnet.ora檔案中寫入如下內容:

ENCRYPTION_WALLET_LOCATION =

 (SOURCE=

   (METHOD=file)

     (METHOD_DATA=

       (DIRECTORY=/orawall)))

在如下的樣例中,我們將假設錢夾位於預設的位置下。你也應該在常規的備份中包含錢夾。

建立錢夾

現在,你必須建立錢夾,而且必須設定訪問密碼。為了能夠完成此操作,通過如下的操作給一個使用者賦予特權(privilege):

alter system set encryption key

authenticated by "remnant";

這條命令完成如下功能:

  • 在步驟1中指定的目錄下建立了一個錢夾
  • 設定了錢夾的密碼為“remnant”
  • 打開了用於TDE儲存和獲取master金鑰的錢夾

錢夾密碼是大小寫敏感的且必須用雙引號括起來。密碼“remnant”在任何動態效能檢視或者日誌中都不會顯示為明文。

開啟錢夾

由於錢夾只需要建立一次,因此上面的兩個步驟只需要執行一次。錢夾必須顯式的在資料庫啟動後開啟。當你建立錢夾的同時錢夾也被打開了。當建立錢夾且設定密碼後,每次開啟資料庫的時候,你都必須使用密碼按照如下方式開啟錢夾:

alter system set encryption wallet open authenticated by "remnant";

你可以通過如下方式關閉錢夾:

alter system set encryption wallet close;

為了TDE能夠正常工作,錢夾必須被開啟。如果錢夾被關閉,你還是可以訪問沒有加密的列,但不能夠訪問加密的列。

1.2 加密列

為了使用TDE加密列,所有你需要做的只是在定義列的時候增加一個簡單的謂詞“ENCRYPT”。在定義之前,理所當然的你需要決定採用什麼樣的加密演算法和金鑰長度。詳細討論請參考我前面提到的文章“Encrypt Your Data Assets”。

在一個常規的schema中,假設你有一個如下定義的名稱為“account”表:

ACC_NO      NUMBER

ACC_NAME    VARCHAR2(30)

SSN         VARCHAR2(9)

目前表的所有資料是明文的,你想轉換SSN列為加密的,因此SSN儲存了敏感的“社會保險號”,你可以通過如下方式設定:

alter table accounts modify (ssn encrypt);

這條語句完成了如下兩件事:

  • 為表建立了一個表金鑰,如果你修改同一個表中的另外的列為加密的,將會使用同一個表金鑰
  • 將所有列的值轉換為加密的形式

這條語句並不修改資料型別或者列的長度,也不建立觸發器或者檢視。

預設情況下采用192位金鑰長度的AES演算法。你也可以選擇不同的演算法,只需要在SQL命令中指定即可。例如,如果要使用128位的AES演算法,你可以採用如下語句:

alter table accounts modify (ssn encrypt using 'AES128');

你可以使用AES128、AES192、AES256、或者3DES168。這些值是自解釋的,例如:AES256指採用AES演算法、256位長度的金鑰。

加密列之後,當查看錶的時候你可以看到如下資訊:

SQL> desc accounts

Name           Null?         Type

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

ACC_NO                       NUMBER

ACC_NAME                     VARCHAR2(30)

SSN                          VARCHAR2(9) ENCRYPT

需要注意的是ENCRYPT關鍵字在資料型別之後。如果需要查詢資料庫中加密的列,你可以在資料字典檢視中搜索DBA_ENCRYPTED_COLUMNS(TDE不能在SYS所有的表中啟用).

2 效能考慮

由於加解密消耗CPU,因此你必須考慮效能的影響。當你訪問表中不加密的列時,效能和不使用TDE的表沒有任何差別。只有在訪問加密列的時候,會有小的效能負擔,包括查詢加密列和插入加密列,因此你也許想有選擇的加密列。

如果你不再需要對一個列加密,你可以通過如下方式關閉加密功能:

alter table account modify (ssn decrypt);

索引的使用也必須考慮。在上面的樣例中,讓我們假設在SSN列上有一個叫做in_accounts_ssn的索引。如果針對ACCOUNT表的查詢有一個相等的謂詞,如下所示:

select * from accounts

where ssn = '123456789';

這樣in_accounts_ssn就會用到。如果用LIKE謂詞來代替,如下所示:

select * from accounts

where ssn like '123%';

則索引不會被用到,而會採用整表掃描的方式。原因很簡單,索引的B-樹結構保證了具有相同字首的值—例如"fraternal", "fraternity"等等在物理上是相鄰的。當處理LIKE謂詞時,Oracle 10g通過模式匹配來搜尋索引入口(entry),物理上相鄰有助於加快索引搜尋速度,這樣也比整表掃描要好一些。

然而,如果列被加密了,索引上實際的值就完全不一樣了(因為它們被加密了),因此原來相鄰的資料被分散在整個索引上了。這樣導致索引掃描筆整表掃描更加消耗效能。因此對於LIKE謂詞,Oracle 10g將忽略索引,而直接採用整表掃描。

在相等匹配的謂詞情況下,搜尋指定索引取代了按值進行模式匹配,所以使用索引執行比整表掃描要更快,資料庫優化器會選擇使用索引。

當你決定加密某列,考慮加密如何影響索引,而且要特別小心你可能想重寫涉及加密列的特定查詢。

3金鑰和密碼管理

萬一有人得到了表金鑰,或者你懷疑某人可能已經破解了加密的表金鑰,你該如何操作?

你可以簡單的為表建立一個新的金鑰,換句話說就是重新生成金鑰,然後通過如下語句將所有加密列用新密碼重新進行加密。你也許會想選擇另外一個演算法進行加密,例如AES256,你可以通過如下方式同時完成兩件事:

alter table accounts rekey using 'aes256';

萬一有人得到了錢夾的密碼怎麼辦呢?

你可以通過Oracle Wallet Manager修改錢夾密碼,在命令列中輸入OWM即可呼叫如下GUI工具。從頂上的選單選擇Wallet -> Open並且選擇你指定的錢夾的位置,然後給出錢夾密碼,選擇Wallet -> Change Password修改錢夾密碼。需要說明的是修改錢夾的密碼不會修改master金鑰。

圖2:Oracle Wallet Manager

4 如何處理“Salt”

加密是關於如何隱藏資料的,但是如果原始的明文資料有很多重複的資料時,有時很容易能夠猜出加密資料的原始值。例如,一個關於薪水資訊的表將包含很多重複的值,這種情況下,加密後的值也是一樣的。一個入侵者能夠確定同一薪水的所有索引入口。為了防護這種情況,將“salt”加入到資料中使得即使原始值相同的資料加密後具有不同的加密值。TDE預設情況下應用了“salt”技術。

如果你準備在一個加密的列上建立索引,因此你不能包含“salt”。通過以下方式可以將“salt”從SSN列上移除:

alter table accounts modify

(ssn encrypt no salt);

如果你準備在一個包含“salt”的加密列上建立索引,你將得到一個錯誤提示,就像下面的樣例所示:

SQL> create index in_acc_01

on accounts (ssn);

ORA-28338: cannot encrypt indexed column(s) with salt

當你準備加密一個包含“salt”的列時,你將會得到同樣的錯誤。同樣的,如果列上有一個隱含的索引,例如列是主鍵的一部分,或者列被定義為unique,你將也不能使用加密。以此推斷,當一個列是外來鍵的一部分時,你也不能使用salt。

5 匯出TDE加密資料

預設情況下,如果你使用EXPDP工具匯出一個擁有加密列的表,在匯出檔案(dump file)中列是明文的,即使列定義為加密也是如此。如下命令匯出ACCOUNTS表(包括加密的列),將會返回一個警告:

$ expdp arup/arup tables=accounts

ORA-39173: Encrypted data has been stored unencrypted in dump file set.

當然,這只是一個警告,不是錯誤,資料還是會被匯出。

為了在資料匯出檔案中保護你的加密的列資料,你可以在匯出表的時候通過密碼保護機制來保護匯出檔案。這個密碼通過在EXPDP命令中的ENCRYPTION_PASSWORD引數指定,且只會應用到本次匯出,這個不是“錢夾”的密碼(譯者注:和TDE沒有關係)。如下清單演示了在EXPDP命令中加上“pooh”密碼。需要注意的是清單1中的密碼並不會顯示為“pooh”,而是通過*號來隱藏。最終匯出來的dump檔案中將不會看到通過TDE加密的列的明文資料了。

程式碼清單1:匯出密碼保護的dump檔案

$ 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 ...

當你匯入加密的dump檔案時,你也必須提供同樣的密碼,程式碼清單2顯示瞭如何操作:

程式碼清單2:匯入密碼保護的dump檔案

$ 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 ...

如下樣例展示了在匯入的時候不輸入ENCRYPTION_PASSWORD引數時的結果:

$ impdp arup/arup tables=accounts

ORA-39174: Encryption password must

be supplied.

The following shows the result if you provide the wrong password:

$ impdp arup/arup ENCRYPTION_PASSWORD

=piglet tables=accounts

ORA-39176: Encryption password is

incorrect.

注意:原有的匯出工具EXP無法匯出有加密列的表。

6 總結

保護你的資料使其免遭攻擊且使其符合數不清的管理業務相關的法律不是一件微不足道的事情。TDE讓你快速的提供資料加密功能,並且不需要任何程式碼和複雜的金鑰管理就能夠符合這些法律,因此你可以更多的聚焦你的戰略成就!

更多學習

更多加密資訊

oracle.com/technology/oramag/oracle/05-jan/o15security.html

www.dbazine.com/olc/olc-articles/nanda11

更多TDE資訊

Oracle Database Advanced Security Administrator's Guide

7 補充

除了對列進行加密外,Oracle TDE還可以對錶空間進行加密,至於何時選擇對列進行加密,何時選擇對錶空間加密,請另外搜尋。