閱讀539 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Oracle數據安全解決方案(1)——透明數據加密TDE

原文地址:

https://www.oracle.com/technology/oramag/oracle/05-sep/o55security.html

TECHNOLOGY: Security

 

透明數據加密TDE

By Arup Nanda

不寫一行代碼,透明的加密敏感數據!

   

這可能是你的公司最恐怖的噩夢:有人偷走了數據庫的備份磁帶!當然,你可能構造了一個安全的係統,加密了最敏感的資產,然後圍繞數據庫服務器建了一圈防火牆來保護。但是,小偷卻采取了最簡單的方法:他偷走了備份磁帶,在另外一個服務器上恢複數據庫、啟動了數據庫,然後他就可以邊喝咖啡邊從容的瀏覽數據了。

保護數據以防這種小偷不隻是一個好的實踐,同時也是很多法律、規則、方針的要求,你如何保護你的數據庫以防止這種漏洞呢?

                                           

一種解決方法是在數據庫中將敏感數據加密,然後將加密密鑰存儲在一個不同的地方,這樣即使數據被盜也是沒有用的。然而,你必須在兩個互相矛盾的概念間進行平衡:應用程序訪問加密密鑰的方便性、防止密鑰被盜的安全性。為了能夠遵從公司和政府的規章製度,你需要一個快速的解決方案,而不需要進行複雜的編碼。

                                           

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所示:

 

1TDE工作原理

你可以加密表的部分或者所有列,例如一個表有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_SIDSWBT4,則錢夾將存儲在/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');

                                             

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

                                             

加密列之後,當查看表的時候你可以看到如下信息:

                                           

SQL> desc accounts

 

Name           Null?         Type

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

ACC_NO                       NUMBER

ACC_NAME                     VARCHAR2(30)

SSN                          VARCHAR2(9) ENCRYPT

                                           

需要注意的是ENCRYPT關鍵字在數據類型之後。如果需要查找數據庫中加密的列,你可以在數據字典視圖中搜索DBA_ENCRYPTED_COLUMNSTDE不能在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密鑰。

 

 

2Oracle 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還可以對表空間進行加密,至於何時選擇對列進行加密,何時選擇對表空間加密,請另外搜索。

 

 

最後更新:2017-04-02 04:00:24

  上一篇:go c#如何將一個整數轉換二進製,並進行位運算
  下一篇:go 歸並排序