李春杰+張啟軍+譚嘉瑞+顏智潤
摘 要:對文件內(nèi)容加密,可有效解決數(shù)據(jù)泄露問題。目前傳統(tǒng)的第三方軟件多采用非透明式加密,對用戶而言,操作不便;新型的堆疊式文件加密方案可以有效解決透明性問題,但此類設(shè)計方案實施較為復雜,并存在內(nèi)核版本依賴性。文中采用Hook機制,通過監(jiān)控用戶對指定文件目錄進行操作,捕獲用戶對該目錄具體文件的訪問;自動調(diào)用應(yīng)用層的加解密模塊,完成對具體文件的加解密,解決透明性問題。由于該系統(tǒng)的加解密功能在應(yīng)用層實現(xiàn),與具體文件系統(tǒng)無關(guān),因此又可以有效簡化系統(tǒng)設(shè)計,災難恢復性強,穩(wěn)定性高。
關(guān)鍵詞:數(shù)據(jù)加密;進程間約束;消息Hook機制;鎖機制
中圖分類號:TP309.7;TP316.81 文獻標識碼:A 文章編號:2095-1302(2018)02-00-03
0 引 言
最近幾年,基于Linux內(nèi)核開發(fā)的操作系統(tǒng)逐漸從服務(wù)端走向用戶終端。尤其某些單位,從服務(wù)器到個人終端都以Linux作為系統(tǒng)支撐。因此,對于存放在Linux上的敏感數(shù)據(jù)進行加密保護,已成為一個急需解決的問題。
多數(shù)第三方加密軟件均采用非透明式文件存儲方式,需要用戶在打開指定文件時調(diào)用解密模塊;同樣,當用戶關(guān)閉文件時,需要調(diào)用加密模塊,導致體驗效果不好。
新型堆疊式文件加密系統(tǒng)[1]雖然可以解決用戶透明性問題,但需要重新設(shè)計一個新的文件管理層,用以對文件加密,因此需要對加密文件系統(tǒng)進行重新設(shè)計。此類方案對于設(shè)計者而言,需要深入掌握Linux各方面的知識,如文件系統(tǒng)管理、內(nèi)存管理、驅(qū)動設(shè)計等。雖然設(shè)計方案在理論上可行,但在系統(tǒng)的具體實現(xiàn)過程中卻十分復雜,而且開發(fā)周期長,成本昂貴,短期內(nèi)看不出測試結(jié)果。
1 整體方案設(shè)計
該系統(tǒng)使用文件鎖[2]和消息Hook機制[3]進行設(shè)計,既可以有效解決用戶透明性問題,又可以降低整體設(shè)計難度。如圖1所示,系統(tǒng)中目錄A作為被監(jiān)控目錄,用于存放需要加密的文件,目錄B可以視為緩存目錄或者備份目錄。當明文文件被存放到目錄A中時,加密子進程在目錄B中創(chuàng)建一個新的臨時文件,用以保存加密之后的密文。當明文文件加密完成后,再利用目錄B中的臨時密文文件替換目錄A中的文件。同樣,當需要對目錄A中的密文文件解密時,讀取目錄B中的臨時密文文件,然后調(diào)用解密子進程對其解密,最后將解密之后的數(shù)據(jù)覆蓋目錄A的密文文件。
整體方案只需調(diào)用Linux提供的接口就可以完成設(shè)計,且絕大部分數(shù)據(jù)處理過程都位于應(yīng)用層。即便系統(tǒng)遇到不可控因素而產(chǎn)生災難性后果,也可以在現(xiàn)有文件系統(tǒng)中找到保存完整的加密數(shù)據(jù),對其進行解密操作,有效解決文件恢復問題。可以看出,基于應(yīng)用層的方案設(shè)計無須對Linux內(nèi)核進行深層次的修改,降低了開發(fā)難度。
2 關(guān)鍵技術(shù)點
目錄A和目錄B間的數(shù)據(jù)交換需要多個子進程先后進行協(xié)調(diào)工作,包括維護子進程、加密子進程、解密子進程。如果用戶操作目錄A以及目錄A中的文件,那么維護子進程就能夠捕捉到用戶的操作,并且通知其他子進程進行后續(xù)操作。
系統(tǒng)方案的設(shè)計需要解決兩個技術(shù)點,即監(jiān)控目錄和進程間控制。
2.1 監(jiān)控目錄
在Linux內(nèi)核最新版本中添加了監(jiān)控操作文件的消息Hook模塊,即inotify,利用inotify作為實現(xiàn)監(jiān)控目錄的核心。
監(jiān)控模塊經(jīng)過初始化后,返回相應(yīng)的監(jiān)控實例id,然后將需要監(jiān)控的對象路徑添加到監(jiān)控實例中,這些對象可以是文件,也可以是文件目錄。若不監(jiān)控該對象,則可以從監(jiān)控實例中移除。
監(jiān)控用戶操作文件并產(chǎn)生消息隊列的過程如圖2所示。當用戶對監(jiān)控目錄A中的文件進行操作時,消息Hook模塊便對虛擬文件系統(tǒng)(VFS)進行監(jiān)控,將用戶的操作類型通過消息方式發(fā)送到應(yīng)用層的消息隊列中,使得后臺維護子進程(通過輪詢方式)能夠?qū)崟r捕捉。
維護子進程通過讀取消息隊列[4]判斷產(chǎn)生的事件并調(diào)用對應(yīng)的加密或解密子進程。通常用戶在訪問一個文件時,可能會產(chǎn)生連續(xù)多個消息事件。例如,用戶打開一個加密文件,監(jiān)控模塊首先產(chǎn)生IN_OPEN消息事件,然后產(chǎn)生IN_WRITE消息事件,最后產(chǎn)生IN_CLOSE消息事件。因此,在監(jiān)控一個對象時,需要維護子進程依次捕獲該對象所產(chǎn)生的一系列消息事件,判斷當前監(jiān)控對象需要進行的操作。
2.2 進程間控制
用戶使用編輯器等軟件打開目錄A中的密文文件,維護子進程自動調(diào)用加解密模塊完成文件解密過程,將解密之后的明文數(shù)據(jù)呈現(xiàn)給用戶。在解密過程中,采用文件鎖方式使用戶進程產(chǎn)生等待,便于解密模塊解密。
但多數(shù)編輯軟件在打開文件時不檢查文件鎖,而是直接讀取文件內(nèi)容,因此用戶讀取的是密文數(shù)據(jù)。為了使這些軟件產(chǎn)生等待,在文件打開時,需要將這些軟件產(chǎn)生的進程強制性地檢查文件是否被鎖定。由于這些進程打開的文件最終都需要調(diào)用內(nèi)核層中的open函數(shù),所以需要修改Linux內(nèi)核中系統(tǒng)定義的open部分[5]。
在Linux內(nèi)核中需要添加文件鎖檢測函數(shù),命名為myFlock。由于內(nèi)核中Flock的系統(tǒng)定義只能提供給上層進行系統(tǒng)調(diào)用而不能直接被內(nèi)核層的其他函數(shù)調(diào)用,所以需要在do_sys_open中調(diào)用自定義的鎖。由于內(nèi)核中的函數(shù)都通過EXPORT_SYMBOL等方式輸出全局信號量[6],因此,F(xiàn)lock和myFlock可以通過調(diào)用全局輸出的信號量來共享緩存隊列,從而使得其他進程在打開文件時強制檢查鎖。此外,內(nèi)核層中進程之間的約束過程如下:
(1)在控制進程中,密文文件被維護子進程調(diào)用flock(),維護子進程持有加密文件鎖;
(2)將與密文文件相關(guān)的信息加入緩存隊列中;
(3)其他進程打開文件需要調(diào)用open()函數(shù),在do_sys_open()返回文件描述符之前[7],需要先調(diào)用myFlock()自定義鎖;endprint
(4)若該文件是被監(jiān)控文件,則其他進程的訪問需要等待文件鎖釋放;
(5)do_sys_open()將通過系統(tǒng)調(diào)用open()返回文件描述符給其他進程;
(6)其他進程讀取文件。
文中詳述了利用文件鎖方式進行進程間控制的過程,使得多個并發(fā)進程能夠有序調(diào)度。如果打開的對象不是被監(jiān)控文件,那么其他進程在內(nèi)核層中獲取鎖之后應(yīng)該立即釋放文件鎖,避免整個系統(tǒng)被鎖死。
3 模塊方案設(shè)計
雖然系統(tǒng)中有多個子進程先后協(xié)調(diào)工作,但為了降低方案設(shè)計的復雜度,可以將系統(tǒng)分為加密過程和解密過程[8]兩部分。
3.1 讀解密操作
對于用戶而言,監(jiān)控目錄下存放的文件雖然以密文數(shù)據(jù)的形式存放在磁盤中,但當用戶訪問文件時,文件應(yīng)當以明文形式呈現(xiàn)給用戶。
如圖3所示,當用戶打開一份密文文件時,需要先讓用戶等待。此時的監(jiān)控模塊產(chǎn)生IN_OPEN消息并插入到消息隊列中,然后維護子進程捕獲該消息,調(diào)用解密子過程直到解密完成后,返回維護子進程使得維護子進程釋放目錄A下的文件鎖,用戶再讀取解密文件時便可以獲得明文。系統(tǒng)的解密過程如下:
(1)維護進程初始化時會掃描目錄A下的文件及目錄,并把這些目錄和文件的絕對路徑放入到已加密文件的監(jiān)控鏈表中,同時給文件添加文件鎖(系統(tǒng)默認目錄A中已存在的文件為密文或目錄為空);
(2)用戶打開目錄A中的加密文件2,監(jiān)控模塊產(chǎn)生IN_OPEN消息事件,由于文件鎖的存在,使得用戶進程產(chǎn)生等待;
(3)維護子進程通過不斷輪詢捕獲到該消息并查找已加密文件監(jiān)控鏈表,判斷該消息所代表的文件是否為密文;
(4)復制目錄A中的加密文件2到目錄B中;
(5)維護子進程調(diào)用解密程序,解密程序讀取目錄B中的加密文件2并解密,將解密之后的數(shù)據(jù)寫入目錄A中的解密文件2中;
(6)解密完成,解密程序?qū)⒓用芪募?從已加密文件監(jiān)控鏈表中移除,并將其添加到待加密的文件鏈表(在監(jiān)控目錄A中以明文形式存在的文件)中;
(7)維護子進程刪除目錄B中的加密文件2并釋放目錄A中解密文件2的文件鎖;
(8)用戶讀取解密文件2。
需要注意的是待加密的文件鏈表中存放的是目錄A中未加密的明文文件節(jié)點,當用戶讀取文件數(shù)據(jù)或者其他操作結(jié)束之后便關(guān)閉該文件并產(chǎn)生IN_CLOSE消息事件,此時就需要維護線程通過讀取待加密的文件鏈表,重新對該目錄A中的明文文件進行加密處理。解密過程如圖4所示。
3.2 寫加密操作
存在于目錄A下的明文文件可以來源于從其他目錄轉(zhuǎn)移到目錄A中的新明文文件,或者用戶讀取目錄A中的密文文件時通過讀解密操作之后留下的明文文件。針對第二種情況,在上述解密操作過程中,后臺子進程已自動將解密文件相關(guān)信息添加到了待加密文件鏈表中,當IN_CLOSE消息到來時就可以通過加密程序?qū)γ魑奈募M行加密操作。然而,對于第一種情況,監(jiān)控模塊也會產(chǎn)生對應(yīng)的IN_OPEN以及IN_CLOSE消息。因此,只要將監(jiān)控目錄中的新文件相關(guān)信息加入到待加密文件鏈表中,IN_CLOSE消息到來時就可通過加密程序?qū)π旅魑奈募M行加密操作。如圖5所示,系統(tǒng)的加密過程如下:
(1)訪問監(jiān)控目錄A并產(chǎn)生相應(yīng)消息事件;
(2)如果是一份新明文文件N,那么監(jiān)控模塊將依次產(chǎn)生IN_OPEN和IN_CLOSE等多個重要的消息;
(3)維護進程首先掃描消息鏈表,得到IN_OPEN消息;
(4)將明文文件N的節(jié)點添加到待加密的文件鏈表中;
(5)維護子進程繼續(xù)掃描消息隊列;
(6)維護子進程掃描IN_CLOSE消息,在待加密文件鏈表里找到該消息代表的文件;
(7)調(diào)用加密程序?qū)ξ募M行加密;
(8)加密程序完成后,將該文件節(jié)點從待加密文件鏈表中移除,并給該文件上鎖。
目錄A中的文件既存有明文文件,又存有密文文件。在寫加密操作中,一些待加密的文件都通過待加密文件鏈表維護。
4 測試結(jié)果
文件加密系統(tǒng)初始化運行,指定目錄A的絕對路徑。首先讀取路徑下的所有文件及子目錄。然后對整個目錄A的文件加密。最后,強行中止文件加密系統(tǒng)運行。如圖6所示,打開該目錄下的文件,顯示的是用戶無法閱讀的亂碼,如文本(txt),圖片(jpg)。
關(guān)閉上述所打開的文件,再重新啟動文件加密系統(tǒng)。因為已經(jīng)運行過一次,所以需要讀取日志文件[9],但發(fā)現(xiàn)所有文件都已被加密。
再打開上述文件,此時后臺維護子進程啟動,調(diào)用解密子進程完成文件解密過程,釋放文件鎖。如圖7所示,用戶讀取的文本(txt)為明文,圖片(jpg)無格式錯誤,能夠進行正常預覽。
5 結(jié) 語
本文主要采用文件鎖和消息Hook機制進行系統(tǒng)設(shè)計,因此需要多個子進程之間的協(xié)調(diào)工作。基于應(yīng)用層的設(shè)計,降低了整個系統(tǒng)的實現(xiàn)復雜度。同時,兼容了各種文件系統(tǒng)格式,通過對監(jiān)控目錄的備份保證了數(shù)據(jù)的可恢復性。解密之后的文件可以對文件內(nèi)容進行Hash校驗[10],從而確定解密之后的文件是否與原始文件的內(nèi)容相同。
參考文獻
[1]刑常亮,卿斯?jié)h,李麗萍.一個基于Linux的加密文件系統(tǒng)的設(shè)計與實現(xiàn)[J].計算機工程與應(yīng)用,2005,41(17):101-104.
[2] Randal E Bryant , David OHallaron.Computer Systems: A Programmers Perspective[M].北京:機械工業(yè)出版社,2011.
[3]劉剛,趙劍川. Linux系統(tǒng)移植[M].北京:清華大學出版社,2011.
[4]邱鐵,周玉,鄧瑩瑩.Linux內(nèi)核API完全參考手冊[M].北京:機械工業(yè)出版社,2011.
[5] Wolfgang Mauerer. Professional Linux Kernel Architecture[M]. 北京:人民郵電出版社,2008.
[6] Neil Matthew,Richard Stones. Beginning Linux Programming [M].北京:人民郵電出版社,2000.
[7]龐麗萍,鄭然.操作系統(tǒng)原理與Linux系統(tǒng)實驗[M].北京:機械工業(yè)出版社,2011.
[8]解雙建,原亮,郝琳,等.一種有效的RSA算法改進方案[J].計算機應(yīng)用,2010,30(9):2293-2397.
[9]劉斌.基于Linux的文件實時備份系統(tǒng)設(shè)計與實現(xiàn)[D].保定:華北電力大學,2014.
[10]徐術(shù)坤.Hash算法的研究及應(yīng)用[D].武漢:湖北工業(yè)大學,2006.endprint