2026年5月28日 星期四

ORA-28374 錯誤分析

在 Oracle 資料庫建立 TDE Key 時,除了會在 wallet 目錄中產生 Key 之外,資料庫的 SYSTEM tablespace 與 control file 也會同步記錄對應的 Key Entry 。即使資料庫中尚未有任何物件進行加密,只要建立過 TDE Key ,相關的 Key 紀錄就會永久保留在 SYSTEM tablespace 中。當資料庫執行加解密操作時,會比對資料庫內所記錄的 Key 與 wallet 中的 Key Entry 是否一致;若兩者不相符,就會出現 ORA-28374: typed master key not found in wallet 的錯誤訊息,也就是資料庫無法在 wallet 中找到對應的 Master Key。


在建立 TDE Key 之後,資料庫與 wallet 會同步建立對應的 Key Entry ,使用 administer key management 建立 Key 如下 :

SQL> alter system set wallet_root='/u01/app/oracle/admin/orcl/wallet' scope=spfile;

SQL> shutdown immediate

SQL> startup

SQL> alter system set tde_configuration='KEYSTORE_CONFIGURATION=FILE';

SQL> administer key management create keystore identified by welcome1;

SQL> administer key management set keystore open identified by welcome1; 

SQL> administer key management set key identified by welcome1 with backup;

SQL> administer key management create auto_login keystore from keystore identified by welcome1;

SQL> administer key management set keystore close identified by welcome1;


建立之後可以透過幾個地方查詢 Key Entry :

 

1. 查詢 v$encryption_keys ,這個會直接解析 wallet 的 TDE Key

SQL> select key_id,activation_time,keystore_type,key_use from v$encryption_keys;

 

2. orapki 查詢 wallet ,結果與 v$encryption_keys 相同

$ orapki wallet display -wallet /u01/app/oracle/admin/orcl/wallet/tde


3. 查詢 system tablespace ,這邊主要是紀錄 master key

SQL> set linesize 150

SQL> column name format a40

SQL> column masterkeyid_base64 format a60

SQL> select  name,utl_raw.cast_to_varchar2( utl_encode.base64_encode('01'||substr(mkeyid,1,4))) || utl_raw.cast_to_varchar2( utl_encode.base64_encode(substr(mkeyid,5,length(mkeyid)))) masterkeyid_base64  FROM (select t.name, RAWTOHEX(x.mkid) mkeyid from v$tablespace t, x$kcbtek x where t.ts#=x.ts#);


4. 查詢 control file ,也是記錄 master key

SQL> select  utl_raw.cast_to_varchar2( utl_encode.base64_encode('01'||substr(mkeyid,1,4))) || utl_raw.cast_to_varchar2( utl_encode.base64_encode(substr(mkeyid,5,length(mkeyid)))) masterkeyid_base64  FROM (select RAWTOHEX(mkid) mkeyid from x$kcbdbk);


若是 wallet 的 Key Entry 與資料庫所記錄的 master key 不符,就會出現 ORA-28374 錯誤。舉個例子來說,把原本已經創建好的 wallet 路徑 rename ,然後重新再產生一個 key :

$ mv /u01/app/oracle/admin/orcl/wallet/tde /u01/app/oracle/admin/orcl/wallet/tde_old

SQL> shutdown immediate

SQL> startup


重新 create keystore ,在 set key 時便會產生 ORA-28374 錯誤 : 

SQL> administer key management create keystore identified by welcome1;

SQL> administer key management set keystore open identified by welcome1;

SQL> administer key management set key identified by welcome1 with backup;


這個原因就是 create keystore 會重新產生一把 master key ,這就會與原本 system tablespace 所記錄的 master key 不同 :


 不能 set key ,那麼也就無法進行任何 TDE 操作了 :


這個時候只能把原本 wallet 的 key 放回去才能正常運行了,萬一原本的 key 真的不幸丟失,可以透過設定隱藏參數 _db_discard_lost_masterkey ,忽略 lost key ,強制使用新的 key :

SQL> alter system set "_db_discard_lost_masterkey"=TRUE;

SQL> administer key management set key identified by welcome1 with backup;


設定完就會更新 system tablespace 裡面的 master key 與 wallet 一致了 :

 

不過設定隱藏參數只能在資料庫完全沒有 Tablespace 加密的情況下使用,透過這種方式來更新或是重設 TDE Key ,若是資料庫已經存在加密的 Tablespace ,那麼就必須一定要找回原本的 TDE Key ,否則已經被加密的 Tablespace 會無法使用。


因此,TDE Key 對於使用資料加密的資料庫而言非常重要。一旦 Key 遺失,被加密的物件將無法存取。由於在建立 TDE Key 的同時,當下的 Key Entry 也會寫入資料庫中,因此這個操作是不可逆的。若 TDE Key 遺失,等同於資料庫損毀;沒有對應的 Key ,即使擁有完整備份,也無法完成資料庫還原或解密操作。


因此創建完 TDE Key 之後,必須立即進行備份,使用 export encryption keys 進行備份 :

SQL> administer key management set keystore open identified by welcome1;

SQL> administer key management export encryption keys with secret "welcome1" to '/home/oracle/tde.bak' identified by welcome1;


這邊要注意的是,若是設定了 auto login 是無法進行 export encryption keys ,必須將 cwallet.sso 移除或 rename ,重開資料庫,這樣才能進行 export 。


若原本的 Key 丟失,重新創建 keystore 之後使用 import keys 將 TDE Key 還原 :

SQL> administer key management create keystore identified by welcome1;

SQL> administer key management set keystore open identified by welcome1;

SQL> administer key management import keys with secret "welcome1" from '/home/oracle/tde.bak' identified by welcome1 with backup;


因為重新 create keystore 與 import keys , v$encryption_keys 會查詢到多筆 entry ,此時必須比對資料庫的紀錄來設定正確的 Key :


使用 use encryption key 設定正確的 Key 之後,就可以 set key :

SQL> administer key management use encryption key 'AV2/kNJSJU/ZvzZ2IrNd4fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' force keystore identified by "welcome1" with backup;


keystore altered.


SQL> administer key management set key identified by welcome1 with backup;


keystore altered.


這樣就完成了 TDE Key 的還原。


除了使用 export encryption keys 進行備份之外,也可以使用 OS 命令例如 tar 直接將 wallet 目錄進行備份。


在資料庫有使用 TDE 功能的情況下, TDE Key 是非常重要的東西,務必做好備份。 

沒有留言:

張貼留言