概述
在客戶環境中,我們經常會需要對一些敏感數據進行保護,比如身份證號碼、手機號碼、社保編號以及電子郵件地址等等。我們可以使用加密的方式來對敏感數據進行保護,但加密的數據會存在被解密的危險。在 IBM Optim Data Privacy 解決方案中,提供了綜合數據屏蔽技術,使用各種屏蔽選項,包括屏蔽字符或數字,生成隨機或序列數字的技術,以及更高級的屏蔽實用程序,來支持復雜的數據隱私要求。
本文通過使用三種不同的方法,即函數轉換、編寫 Exit Routine 和 Column Map Procedure,以身份證數據轉換為實例,全面地講述了 IBM Optim Data Privacy 技術的使用方法,向讀者介紹編寫自定義數據轉換規則的方法,並能夠讓讀者對這三種方法的使用有所比較。
Optim 數據保護方法概述
IBM Optim Data Privacy 解決方案提供了全面的數據屏蔽技術,以滿足數據隱私遵從性需求:
IBM Optim Data Privacy 提供了基礎屏蔽選項,包括字符替換,選擇子集,或者生成序列和隨機數等常用技術,滿足簡單的數據屏蔽需求。
IBM Optim Data Privacy 解決方案也提供了更高級的數據屏蔽技術,包括 LOOKUP 函數根據樣本數據進行哈希映射,AGE 函數對時間日期類數據進行轉換等。同時,還內置了對常見敏感信息的屏蔽函數,包括社保編號、信用卡編號和電子郵件地址等。
在標准函數無法滿足用戶特殊的數據屏蔽需求時,Optim 還提供了 Exit Routine 和 Column Map Procedure 兩種途徑,使用戶可以自行編程實現特殊業務需求。
在本文中,我們將貫穿身份證數據轉換這個例子,向您展示如何使用 IBM Optim Data Privacy 解決方案實現數據屏蔽以及如何編寫自己的數據變性規則。
先決條件
本文假設您具有 Optim Data Privacy 解決方案的基本使用經驗,能夠完成 Optim 在 Windows 平台的安裝和配置工作。
同時,配合文中的示例,需要您安裝以下軟件
運行在 Windows 平台上的 Optim Data Privacy Solution,版本 7.x
DB2 數據庫,版本 9.1 或 9.5
在 DB2 數據庫中創建 optimdir 和 sourcedb 數據庫,如下:
create db optimdir using codeset utf-8 territory zh_CN
create db sourcedb using codeset utf-8 territory zh_CN
其中,配置 Optim 使用 optimdir 作為 Directory,並且創建 sourcedb 的數據庫別名。
使用附件中提供的 Extract 文件中的數據完成示例。其中 LOOKUP_ID.XF 保存有樣本數據,供哈希轉換函數使用;SAMPLE_ID.XF 文件保存有待轉換數據,使用該數據進行數據轉換。
使用 HASH_LOOKUP 函數進行數據轉換
在 IBM Optim 中,提供了很多轉換函數來幫助實現數據屏蔽,常用的函數有 RAND、SUBSTR、HASH_LOOKUP、AGE 等等。本文,我們使用 HASH_LOOKUP 作為范例說明此類函數的使用方法。
HASH_LOOKUP 函數通過哈希函數映射,將待轉換列中的數據替換為樣本表中的值,從而實現數據轉換的功能。樣本表除了需要提供一個包含樣本值的列外,還需提供一個具有唯一值的整數類型的列以供哈希映射。
樣本數據准備
本文的附件 LOOKUP_ID.XF 中提供了一組身份證樣本數據,該文件是 Optim Extract 文件,可以通過 Insert 功能插入到數據庫當中。具體插入步驟如下。
打開 Optim,選擇“Action->Insert”。在 Insert Request Editor 面板中,Source File 選擇我們提供的“LOOKUP_ID.XF”文件;在 Control file 處填寫 lookup.CF;Table Map Options 選擇“Local”;Process Option 選擇“Insert”。然後點擊“Edit Table Map”按鈕,如圖 1 所示。
圖 1. 新建插入請求
查看原圖(大圖)
在 Table Map Editor 面板中,QualifIEr 選擇 SOURCEDB,creator Id 選擇您自己的 schema,這裡我們選擇為 db2admin; 在下部的 Tables 部分,Destination Table 處填寫“LOOKUP_ID”,按 Tab 鍵,Type 處會顯示“Unknown”。選擇“File->Update and Return”。如圖 2 所示。
圖 2. 設置表映射
查看原圖(大圖)
點擊“Run”按鈕,運行 Insert 請求。如圖 3 所示。
圖 3. 執行插入請求
在彈出的 Create 面板中,選擇“Create all selected objects”按鈕,創建目標表和主鍵約束。如圖 4 所示。
圖 4. 創建樣本表
查看原圖(大圖)
在接下來的兩個界面點擊“proceed”和“continue”, 並關閉創建完成的界面後,Optim 會進行 Insert 操作。插入完成後,會顯示成功,並生成操作報告。
配合本例,我們隨附件同時提供了待轉換的身份證信息樣本,保存在“SAMPLE_ID.XF”文件中。執行同樣的步驟將該文件中的數據插入到 sourcedb 中。這樣就完成了樣本數據的准備工作。
數據轉換
回到 Optim 主界面,選擇“Action->Convert”。在 Convert Request Editor 主界面中,Source File 選擇我們提供的“Sample_ID.XF”文件;Control File 填寫 sample.CF;Destination File 填寫 Convert_ID.XF;Table Map Options 選擇“Local”。然後點擊“Edit Table Map”按鈕。
圖 5. 創建轉換請求
在 Table Map Editor 界面中,QualifIEr 填寫為 SOURCEDB.DB2ADMIN;Destination Table 填寫為 SAMPLE_ID;在 Column Map or “Local”處填寫“Local”,並在該處單擊右鍵,選擇“Open Column Map”。如圖 6 所示。
圖 6. 添加列映射
在 source 的 ID 列的位置,填入如下內容:
HASH_LOOKUP(ID,LOOKUP(no,ID))
單擊 TAB 鍵後,可以看到該行最右側的 Status 列變為“Lookup Function”。如圖 7 所示。
圖 7. 添加哈希轉換
查看原圖(大圖)
連續選擇“File->Update and return” 保存更改,返回到 Convert Request Editor 主界面。單擊“Run”執行該 Convert 請求。執行結束後將自動生成執行報告,如圖 8 所示。可以看到,45 條數據全部轉換成功。
圖 8. 轉換執行報告
轉換結果
回到 Optim 主界面,選擇“Action->Compare”。在 Compare Request Editor 主界面的 General 標簽中,Compare File 填寫“ID.CMP”;選中“Browse Results Immediately”方框,以便比較結束後立即查看結果;Comparision Mode 選擇“Single Table:Source File – Source File”。如圖 9 所示。
圖 9. 創建比較請求
在 Source 標簽中,Source 1 選擇 SAMPLE_ID.XF,Source 2 選擇 Convert_ID.XF。然後執行 Compare 請求。如圖 10 所示。
圖 10. 設置比較文件
查看原圖(大圖)
比較結束後會打開 ID.CMP 文件如下。雙擊表名進入比較界面。
圖 11. 比較結果文件
相鄰的兩行為轉換前後的行,可以看到他們的身份證字段已經全部進行了轉換。
圖 12. 哈希轉換結果
查看原圖(大圖)
使用 Exit Routine 進行數據轉換
如果 Optim 提供的數據轉換函數無法滿足用戶的特殊需求,我們可以通過編寫 Exit Routine 來自定義數據轉換規則,從而實現數據轉換的高級定制。
Exit Routine 介紹
Exit routine 提供給用戶通過編程實現自定義規則的能力。Optim 提供了三種 Exit routine:
Standard Exit: 用於編寫復雜的自定義數據轉換規則,在基本的列映射功能無法實現用戶的復雜轉換需求時發揮重要作用。
Source Format Exit: 在 AGE 函數中使用。主要功能為將源數據列中非時間 / 日期類型的數據經過處理,轉化為時間 / 日期類型,從而完成 AGE 函數的調用。
Destination Format Exit: 在 AGE 函數中使用。主要功能為將源數據列中時間 / 日期類型的數據經過處理,轉化為目標列的數據類型,從而完成 AGE 函數的調用。
其中 Standard Exit 最為常用,我們這裡也采用編寫 Standard Exit 來實現身份證數據轉換。
編寫 Exit Routine
Exit Routine 的調用遵循 C 語言規范。因此,我們在附件中給出了 C 語言的示例程序,包括以下 3 個文件:
PSTEXIT.H: 包含 Optim 定義的數據類型、返回值以及結構。
PSTCMXIT.H:單字節字符集(例如 ASCII)專用頭文件。提供了列映射回調函數原型以及參數的定義。
MYEXIT.C:自定義身份證數據轉換的示例程序。
Optim 調用 Exit Routine 的接口函數 PSTColMapExit(),我們需要在該函數中完成轉換規則的編寫。
PSTColMapExit() 函數的定義如下:
__declspec(dllexport) short
PSTColMapExit( PST_STRUCT_CM_EXIT_PARM * pInputParms,
PST_STRUCT_CM_EXIT_COL_LIST * pSrcColList,
PST_STRUCT_CM_EXIT_COL_LIST * pDstColList )
pInputParms保存了當前列映射操作的信號和參數,其中 FuncCode為當前的處理信號,如果收到 PST_CM_FUNC_TERMINATE信號,則表明程序處理結束;DestColIndex為目標列在表中的排序,用於選定進行轉換的列。PSrcColList為源數據列的指針,pDstColList為指向目標列的指針。
程序進行初始化和條件判斷之後,首先需要獲取源數據列的數據。主要代碼如下:
// 得到源數據列的指針
pCol = &(pSrcColList->Col[ pInputParms->DestColIndex ]);
rc = (*pInputParms->PPSTGetColValue)// 獲取源數據列數據
(pCol->hCol, // 源數據列的句柄
PST_C_CHAR, // 指明列的數據類型
0, //Precision,DECIMAL 數據類型專用,這裡不需要
0, //Scale,DECIMAL 數據類型專用,這裡不需要
&ID, // 保存數據的變量地址
sizeof(ID), // 變量的大小
&IndVar ); // 數據是否為空的標志,-1 為空,不空則為 0
switch ( rc )
{
case PSTEXIT_SUCCESS: // 成功
case PSTEXIT_TRUNC_WARNING: // 含有警告信息,但仍然可以繼續
break;
default:
return( PST_CM_EXIT_ABORT_PROCESS );// 發生嚴重錯誤,數據轉換終止
}
在獲取了身份證數據之後,我們進行轉換。變換規則為:
利用身份證第後 4 位信息座位種子生成隨機數 rand;
身份證頭兩位的省份信息由 rand%31 決定,在省份列表中選取;
生日年份信息由 rand%30+70 決定,區間為 1970~2000;
生日月份信息由 rand%12+1 決定,區間為 1~12;
身份證的最後一位校驗位,由以下規則計算得出:
計算前 17 位的加權和 S,S = Ai * Wi, i = 2, ... , 18,其中 Ai 為第 i 位的身份證號碼數值,Wi 為第 i 位的權重,Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1
取 S 對 11 的模 j,j = mod(S, 11)
根據 j 的值,得到校驗碼 Yj,Yj:1 0 X 9 8 7 6 5 4 3 2,j=0,1...10
轉換部分的關鍵代碼如下:
// 根據身份證最後四位生成隨機數序列
seed=atoi(&ID[14]);
srand(seed);
// 分別獲得隨機生成的省號位置、出生年份和出生月份
pos[0]=rand()%31;
pos[1]=rand()%30+70;
pos[2]=rand()%12+1;
// 將數字轉化為字符
itoa(pos[1],year,10);
itoa(pos[2],month,10);
// 替換省號
ID[0]=pro[2*pos[0]];
ID[1]=pro[2*pos[0]+1];
// 替換年份
ID[8]=year[0];
ID[9]=year[1];
// 替換月份
if(month[1]!='\0')
{
ID[10]=month[0];
ID[11]=month[1];
}
else
{
ID[10]='0';
ID[11]=month[0];
}
// 得到每一位身份證的整形值
for(i=0;i<17;i++)
data[i]=ID[i]-'0';
// 計算校驗位
data[17]=0;
for(i=0;i<17;i++)
data[17]+=data[i]*wi[i];
// 校驗位賦值
ID[17]=yi[data[17]%11];
最後,將變化完成的數據寫到目標列中。代碼如下:
( rc = (*pInputParms->PPSTPutColValue) // 目標列賦值函數
(PST_C_CHAR, // 目標列數據類型
0, //Precision,DECIMAL 數據類型專用,這裡不需要
0, //Scale,DECIMAL 數據類型專用,這裡不需要
ID, // 轉換後的數據
sizeof(ID), // 數據大小
IndVar)); // 賦值是否為空,-1 為空,不空為 0
完成了程序的編寫,我們需要將每一個 Exit Routine 編譯連接生成單獨的 DLL 文件,並將該文件放在 Optim 安裝目錄中 BIN 文件夾下。Optim 會在啟動時自動加載該庫文件。在本例中,將上面的編寫的 Exit Routine 生成 MYEXIT.dll, 並將它放在 Optim 安裝目錄中 BIN 文件夾下。
然後打開一個新的 Convert 請求,步驟和前面 HASH_LOOKUP 一致。在指定 Column Map 界面,我們在 ID 列所在的位置填寫“EXIT MYEXIT”,按 Tab 鍵,可以發現該行最右側的 Status 列狀態變成 Exit。
圖 13. 設置 Exit routine
查看原圖(大圖)
選擇 Update and return,執行該請求,同樣得到成功的報告。
新建一個 Compare 的請求,步驟參考 HASH_LOOKUP 章節中的轉換結果部分,得到的比對結果如下:
圖 14. Exit routine 轉換結果
查看原圖(大圖)
可以看到,轉換同樣成功,並且結果和之前利用 HASH_LOOKUP 得到的結果不同,按照我們設計的規則進行了變化。
編寫 Column Map Procedure 進行數據轉換