企業級加密文件系統 eCryptfs 詳解

來源:http://www.ibm.com/developerworks/cn/linux/l-cn-ecryptfs/index.html?ca=drs-cn-0917
一。加密文件系統概述

什麼是加密文件系統

近年來,保護敏感數據不被泄漏成爲人們關注的熱點問題。入侵者除了直接盜取物理存儲設備,還可以通過網絡攻擊來竊奪文件數據;而且,由於共享的需求,敏感數據會由多人訪問,這也增大了泄漏的可能性。對數據或文件進行加密已經成爲一種公認的比較成功的保護方法。事實上,人們早已開發了許多優秀的加密算法,如 DES、AES、RSA 等,並且有一些應用程序如 crypt 使用這些加密算法,用戶通過這些工具手工地完成加密、解密的工作。由於這些應用程序操作麻煩、沒有和整個系統緊密地結合而且容易受到攻擊,因此一般用戶並不願意使用。

加密文件系統通過將加密服務集成到文件系統這一層面來解決上面的問題。加密文件的內容一般經過對稱密鑰算法加密後以密文的形式存放在物理介質上,即使文件丟失或被竊取,在加密密鑰未泄漏的情況下,非授權用戶幾乎無法通過密文逆向獲得文件的明文,從而保證了高安全性。與此同時,授權用戶對加密文件的訪問則非常方便。用戶通過初始身份認證後,對加密文件的訪問和普通文件沒有什麼區別,就好像該文件並沒有被加密過,這是因爲加密文件系統自動地在後臺做了相關的加密和解密的工作。由於加密文件系統一般工作在內核態,普通的攻擊比較難於奏效。還有一類系統級加密方案是基於塊設備,與它們相比,加密文件系統具有更多的優勢,例如:

  1. 支持文件粒度的加密,也就是說,用戶可以選擇對哪些文件或目錄加密。而且,應用程序不用關心文件是否被加密,可以完全透明地訪問加密文件。
  2. 無需預先保留足夠的空間,用戶可以隨時加密或恢復文件。
  3. 對單個加密文件更改密鑰和加密算法比較容易。
  4. 不同的文件可以使用不同的加密算法和密鑰,增大了破解的難度。
  5. 只有加密文件才需要特殊的加密/解密處理,普通文件的存取沒有額外開銷。
  6. 加密文件轉移到別的物理介質上時,沒有額外的加密/解密開銷。

加密文件系統的分類

加密文件系統基本上可以分爲兩大類,兩類的實現方式和目標都有比較大的區別。一類是面向網絡存儲服務的,通常是基於 NFS 客戶/服務器模型,通常稱爲網絡加密文件系統。在網絡加密文件系統中,數據以密文的方式保存在網絡文件系統中,用戶通過客戶機服務進程與網絡文件服務器交互,網絡文件服務器負責將用戶請求的密文傳遞到客戶機服務進程,由客戶機服務進程進行解密再交給應用程序。在這個模型中,只要求客戶機操作系統是可信的,而網絡服務器由於不接觸明文數據,不要求其可信。另一類是本地加密文件系統,密文數據直接存放在本地物理介質上(硬盤,U 盤等),由操作系統或服務進程完成數據的讀取、加密/解密工作。本地加密文件系統的目標是應對存儲介質失竊的威脅,安全模型同樣把加密文件系統所在的操作系統視爲可信的。

本地加密文件系統又可以細分爲兩種,一種是在原有的普通文件系統上直接加入加密功能,如 Reiser4,但是現有的 Ext2, Ext3 等常用文件系統並不支持加密功能,因此用戶不得不轉換整個文件系統;另一種被稱爲堆疊式加密文件系統(Stackable Cryptographic File System)。這種加密文件系統可以看成一個加密/解密的轉換層,而並不是一個真實的全功能文件系統。堆疊式加密文件系統沒有相應的磁盤佈局,也不實現數據在物理介質上存取的功能。它必須架構在別的普通文件系統之上,讀加密文件時先通過下層普通文件系統將文件的密文讀入內存,解密後再將明文返回到上層的用戶進程;寫加密文件時先將內存中的明文加密,然後傳給下層普通文件系統,由它們真正地寫入物理介質。堆疊式加密文件的優勢在於實現相對容易(因爲功能相對簡單)且用戶可以任意選擇下層的普通文件系統來存放加密文件。本文討論的 eCryptfs 屬於本地堆疊式加密文件系統的範疇。

現有加密文件系統的不足

加密文件系統的概念由來已久,現實世界中已有諸多的實現,例如 CFS[2], TCFS, Crypt-FS, FSFS, Waycryptic 和 Windows EFS 等,但是這些加密文件系統有着內在的侷限和安全問題。

CFS 和 TCFS 通過 NFS 客戶/服務器模型來提供加密服務,只使用了 DES 算法來加密文件內容。這兩種文件系統主要的缺點在於:難於使用、共享加密文件非常困難、用戶不能選擇加密算法、交換區或臨時文件可能會泄漏明文以及性能較差等等。

Waycryptic 是一個堆疊式加密文件系統,通過修改 Linux 內核的虛擬文件系統層(VFS)來提供加密及解密的功能。Waycryptic 使用兩種算法來加密文件:加密文件內容使用對稱密鑰算法,如AES,密鑰隨機產生;同時使用一種公開密鑰算法,如RSA,加密剛纔提及的密鑰。這種綜合兩種加密算法的方式既保證了加密/解密的速度,又極大地提高了安全性。同時Waycryptic允許加密文件方便安全地在多個用戶間共享;爲了應對密鑰的丟失,Waycryptic允許用戶指定別的帳號來恢復文件。但是 Waycryptic 主要是一個研究項目,比較適合個人單機使用,無法滿足企業或需要更高安全級別的用戶的需求。

Windows EFS(Encrypting File System) 是對 NTFS 文件系統的功能擴充,可以方便地加密 NTFS捲上的文件或目錄。Windows EFS 簡單易用,功能強大,不足之處在於只能在 Windows 操作系統的 NTFS 捲上才能使用,文件內容使用的加密算法比較單一。此外,如果事先沒有備份證書的話,一旦重裝系統就無法再訪問加密文件。

二.使用 eCryptfs

eCryptfs 簡介

eCryptfs 是在 Linux 內核 2.6.19 版本中引入的一個功能強大的企業級加密文件系統,堆疊在其它文件系統之上(如 Ext2, Ext3, ReiserFS, JFS 等),爲應用程序提供透明、動態、高效和安全的加密功能。

本質上,eCryptfs 就像是一個內核版本的 Pretty Good Privacy(PGP)[3] 服務,插在 VFS(虛擬文件系統層)和 下層物理文件系統之間,充當一個“過濾器”的角色。用戶應用程序對加密文件的寫請求,經系統調用層到達 VFS 層,VFS 轉給 eCryptfs 文件系統組件(後面會介紹)處理,處理完畢後,再轉給下層物理文件系統;讀請求(包括打開文件)流程則相反。

eCryptfs 的設計受到OpenPGP 規範的影響,使用了兩種方法來加密單個文件:

  1. eCryptfs 先使用一種對稱密鑰加密算法來加密文件的內容,推薦使用 AES-128 算法,密鑰 FEK(File Encryption Key)隨機產生。有些加密文件系統爲多個加密文件或整個系統使用同一個 FEK(甚至不是隨機產生的),這會損害系統安全性,因爲:a. 如果 FEK 泄漏,多個或所有的加密文件將被輕鬆解密;b. 如果部分明文泄漏,攻擊者可能推測出其它加密文件的內容;c. 攻擊者可能從豐富的密文中推測 FEK。
  2. 顯然 FEK 不能以明文的形式存放,因此 eCryptfs 使用用戶提供的口令(Passphrase)、公開密鑰算法(如 RSA 算法)或 TPM(Trusted Platform Module)的公鑰來加密保護剛纔提及的 FEK。如果使用用戶口令,則口令先被散列函數處理,然後再使用一種對稱密鑰算法加密 FEK。口令/公鑰稱爲 FEFEK(File Encryption Key Encryption Key),加密後的 FEK 則稱爲 EFEK(Encrypted File Encryption Key)。由於允許多個授權用戶訪問同一個加密文件,因此 EFEK 可能有多份。

這種綜合的方式既保證了加密解密文件數據的速度,又極大地提高了安全性。雖然文件名沒有數據那麼重要,但是入侵者可以通過文件名獲得有用的信息或者確定攻擊目標,因此,最新版的 eCryptfs 支持文件名的加密。

eCryptfs 使用方法

eCryptfs 需要相應的內核模塊和用戶態的工具同時配合使用。用戶態的工具可以從 https://launchpad.net/ecryptfs 獲得,使用 Debian 或 Ubuntu 系統的用戶,用 apt-get 命令安裝 ecryptfs-utils 包即可。如果用戶自行編譯內核,則需要如下選項:


清單 1. 使用 eCryptfs 所需的內核選項
General setup  --->
[*] Prompt for development and/or incomplete code/drivers
File systems  --->
Miscellaneous filesystems  --->
<M> eCrypt filesystem layer support (EXPERIMENTAL)
Security options  --->
<M> Enable access key retention support
Cryptographic API  --->
<M> MD5 digest algorithm
<M> AES cipher algorithms

首先需要加載 eCryptfs 內核模塊,執行modprobe ecryptfs。然後將 eCryptfs 掛載到準備存放加密文件的目錄,執行 sudo mount -t ecryptfs real_path ecryptfs_mounted_path。推薦ecryptfs_mounted_path 和 真實目錄 real_path 一致,這樣非授權用戶不能通過原路徑訪問加密文件。

圖 1. eCryptfs 掛載結果
 

eCryptfs默認使用 AES-128 算法以及用口令加密 FEK,更多掛載選項請參考 eCryptfs 的 man page。如果用戶想使用公鑰加密算法加密 FEK,需要事先用 OpenSSL 產生公鑰/私鑰對。用戶還可以在主目錄下的 .ecryptfsrc 文件中寫入缺省選項,配置文件的格式請參閱 http://ecryptfs.sourceforge.net/README 。


三.eCryptfs 的設計

eCryptfs 設計目標

爲了評估一個加密解決方案的可行性,企業往往要考慮諸多因素,例如員工的學習曲線、增量備份是否受到影響、密鑰丟失的話如何防止信息泄漏或如何恢復信息、轉換及使用成本、潛在的風險等等。eCryptfs 在設計之初,充分考慮企業用戶的如下需求:

  1. 易於部署。eCryptfs 完全不需要對 Linux Kernel 的其它組件做任何修改,可以作爲一個獨立的內核模塊進行部署。同時,eCryptfs 也不需要額外的前期準備和轉換過程。
  2. 用戶能夠自由選擇下層文件系統來存放加密文件。由於不修改 VFS 層,eCryptfs 通過掛載(mount)到一個已存在的目錄之上的方式實現堆疊的功能。對 eCryptfs 掛載點中文件的訪問首先被重定向到 eCryptfs 內核文件系統模塊中。
  3. 易於使用。每次使用 eCryptfs 前,用戶只需執行 mount 命令,隨後 eCryptfs自動完成相關的密鑰產生/讀取、文件的動態加密/解密和元數據保存等工作。
  4. 充分利用已有的成熟安全技術。例如,eCryptfs 對於加密文件採用 OpenPGP 的文件格式、通過 Kernel Crypto API使用內核實現的對稱密鑰加密算法和散列算法等。
  5. 增強安全性。eCryptfs 的安全性最終完全依賴於解密 FEK 時所需的口令或私鑰。通過利用 TPM 硬件(TPM可以產生公鑰/私鑰對,硬件直接執行加密/解密操作,而且私鑰無法從硬件芯片中獲得),eCryptfs 最大程度上保證私鑰不被泄漏。
  6. 支持增量備份。eCryptfs 將元數據和密文保存在同一個文件中,從而完美的支持增量備份及文件遷移。
  7. 密鑰託管。用戶可以預先指定恢復帳號,萬一遺失加密 FEK 的口令/私鑰,也可以通過恢復帳號重新獲得文件的明文;但是如果未指定恢復帳號,即使系統管理員也無法恢復文件內容。
  8. 豐富的配置策略。當應用程序在 eCryptfs 的掛載點目錄中創建新文件的時候,eCryptfs 必須做出許多決定,比如新文件是否加密、使用何種算法、FEK 長度、是否使用 TPM 等等。eCryptfs 支持與 Apache 類似的策略文件,用戶可以根據具體的應用程序、目錄進行詳細的配置。

eCryptfs 的架構

圖 2. eCryptfs 加密文件系統的架構
 

eCryptfs Layer 是一個比較完備的內核文件系統模塊,但是沒有實現在物理介質上存取數據的功能。在 eCryptfs Layer自己的數據結構中,加入了指向下層文件系統數據結構的指針,通過這些指針,eCryptfs就可以存取加密文件。清單 2 列出幾種主要的數據結構:

清單 2. eCryptfs Layer 主要數據結構

static struct file_system_type ecryptfs_fs_type = {
	.owner = THIS_MODULE,
	.name = "ecryptfs",
	.get_sb = ecryptfs_get_sb,
	.kill_sb = ecryptfs_kill_block_super,
	.fs_flags = 0
};

struct ecryptfs_sb_info {
	struct super_block *wsi_sb;
	struct ecryptfs_mount_crypt_stat mount_crypt_stat;
};

struct ecryptfs_inode_info {
	struct inode vfs_inode;
	struct inode *wii_inode;
	struct file *lower_file; /* wii_inode, lower_file 指向下層文件系統對應的數據結構 */
	struct mutex lower_file_mutex;
	struct ecryptfs_crypt_stat crypt_stat;
};

struct ecryptfs_dentry_info {
	struct path lower_path; /* 下層文件系統的 dentry */
	struct ecryptfs_crypt_stat *crypt_stat;
};

struct ecryptfs_file_info {
	struct file *wfi_file;
	struct ecryptfs_crypt_stat *crypt_stat;
};

Keystore 和用戶態的 eCryptfs Daemon 進程一起負責密鑰管理的工作。eCryptfs Layer 首次打開一個文件時,通過下層文件系統讀取該文件的頭部元數據,交與 Keystore 模塊進行 EFEK(加密後的 FEK)的解密。前面已經提及,因爲允許多人共享加密文件,頭部元數據中可以有一串 EFEK。EFEK 和相應的公鑰算法/口令的描述構成一個鑑別標識符,由 ecryptfs_auth_tok 結構表示。Keystore 依次解析加密文件的每一個 ecryptfs_auth_tok 結構:首先在所有進程的密鑰鏈(key ring)中查看是否有相對應的私鑰/口令,如果沒有找到,Keystore 則發一個消息給 eCryptfs Daemon,由它提示用戶輸入口令或導入私鑰。第一個被解析成功的 ecryptfs_auth_tok 結構用於解密 FEK。如果 EFEK 是用公鑰加密算法加密的,因爲目前 Kernel Crypto API 並不支持公鑰加密算法,Keystore 必須把 ecryptfs_auth_tok 結構發給 eCryptfs Daemon,由它調用 Key Module API 來使用 TPM 或 OpenSSL庫解密 FEK。解密後的 FEK 以及加密文件內容所用的對稱密鑰算法的描述信息存放在 ecryptfs_inode_info 結構的 crypt_stat 成員中。eCryptfs Layer 創建一個新文件時,Keystore 利用內核提供的隨機函數創建一個 FEK;新文件關閉時,Keystore 和 eCryptfs Daemon 合作爲每個授權用戶創建相應 EFEK,一齊存放在加密文件的頭部元數據中。

eCryptfs 採用 OpenPGP 的文件格式存放加密文件,詳情參閱 RFC 2440 規範[4]。我們知道,對稱密鑰加密算法以塊爲單位進行加密/解密,例如 AES 算法中的塊大小爲 128 位。因此 eCryptfs 將加密文件分成多個邏輯塊,稱爲 extent。當讀入一個 extent 中的任何部分的密文時,整個 extent 被讀入 Page Cache,通過 Kernel Crypto API 被解密;當 extent 中的任何部分的明文數據被寫回磁盤時,需要加密並寫回整個 extent(參見圖 5[5])。extent 的大小是可調的,但是不會大於物理頁的尺寸。當前的版本中的 extent 默認值等於物理頁大小,因此在 IA32 體系結構下就是 4096 字節。加密文件的頭部存放元數據,包括元數據長度、標誌位以及 EFEK 鏈,目前元數據的最小長度爲 8192 字節。

圖 3. eCryptfs 加密/解密操作流程圖
 

eCryptfs 的不足

eCryptfs 不足之處在於:

  1. 寫操作性能比較差。筆者用 iozone 測試了 eCryptfs 的性能,發現讀操作的開銷不算太大,最多降低 29%,有些小文件測試項目反而性能更好;對於寫操作,所有測試項目的結果都很差,普遍下降 16 倍左右。這是因爲 Page Cache 裏面只存放明文,因此首次數據的讀取需要解密操作,後續的讀操作沒有開銷;而每一次寫 x 字節的數據,就會涉及 ((x – 1) / extent_size + 1) * extent_size 字節的加密操作,因此開銷比較大。
  2. 有兩種情況可能造成信息泄漏:a. 當系統內存不足時,Page Cache 中的加密文件的明文頁可能會被交換到 swap 區,目前的解決方法是用 dm-crypt 加密 swap 區。b. 應用程序也有可能在讀取加密文件後,將其中某些內容以臨時文件的方式寫入未掛載 eCryptfs 的目錄中(比如直接寫到 /tmp 中),解決方案是配置應用程序或修改其實現。
  3. eCryptfs 實現的安全性完全依賴於操作系統自身的安全。如果 Linux Kernel 被攻陷,那麼黑客可以輕而易舉地獲得文件的明文,FEK 等重要信息。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章