王张军 陈莉君
(西安邮电大学计算机学院 西安710121)
WANG ZhangjunCHEN Lijun
(School of Computer Science,Xi'an University of Posts and Telecommunications,Xi'an 710121)
随着计算机技术的进步,敏感信息泄露的风险也随着更加便利的信息获取和分享方式而变得日益严峻。常见的计算机安全保护措施如防火墙、专用网络、入侵检测等措施都是以入侵者无法直接接触敏感信息为前提的,但是当入侵者可以直接接触到存储着敏感信息的设备时,对于机密信息的安全威胁也随之增加。这种安全隐患的根源在于数据在存储设备上是明文的,解决这种安全隐患的根本方法就是对数据进行加密。透明加密技术[1]在数据存储时默认为数据加密,读取时为数据解密,加解密的过程是自动的、透明的,既保证了文件的安全,也不影响用户正常的读写文件习惯。当敏感信息文件以某种手段被获取时,会因为脱离了透明加密文件系统的环境,而保证了数据的不可读性。
Linux目前已有的透明加密文件系统主要分为三种:用户态透明加密文件系统[2~3]、基于拦截系统调用的加密文件系统[4~5]和基于过滤页缓冲(page cache)[6~7]的透明加密文件系统。用户态透明加密文件系统由于要完成内核态和用户态的频繁切换,性能损耗较大;拦截系统调用技术需要对用户态复杂的参数进行验证,不利于程序的健壮性,另外由于没有采用系统级的缓存优化,系统利用率低。而目前基于过滤页缓冲的透明加密文件系统,均采用单缓冲的方式,即只有一份页缓冲,这在支持授信和非授信进程访问时,就需要频繁的在明文和密文数据之间进行切换,降低了系统的缓冲性能。
本文在总结已有方案的基础上,提出一种新的透明加密机制,即基于双缓冲的透明加密,为授信进程提供明文缓冲区,为非授信进程提供密文缓冲区,减少对同一块缓冲频繁加解密的次数,同时这些操作位于内核态,有效的提高了透明加解密的性能。
虚拟文件系统[8](Virtual File System,VFS)作为内核的子系统,为用户态程序提供统一操作文件的系统调用,当VFS接受到用户态程序的系统调用时,经过一定的处理,便将调用传递给下面的具体文件系统。
堆栈式文件系统[9]是位于VFS和具体文件系统之间的一层文件系统。它通过把要实现的文件系统功能加载到原有文件系统之上以实现“递增”式开发。即在堆栈式文件系统中实现新的功能需求,而不需要对底层文件系统做任何代码级的修改。于是,开发测试工作的焦点就集中在堆栈式文件系统上,而无需关心原有的底层文件系统。同时,堆栈式文件系统以内核模块的形式运行在内核态,省去了内核态和用户态频繁切换的时间开销,因此堆栈式文件系统扩展的系统功能具有性能损失小,开发代价低等优点。堆栈式文件系统的架构模型如图1所示。
图1 堆栈式文件系统模型
在Linux系统中,只有在打开(open)文件后,才能通过系统调用read和write对文件进行读写操作,read和write系统调用经过VFS映射到具体文件系统(如:EXT4),具体文件系统进而在页缓冲(page cache)中查找或者写入文件内容。页缓冲是Linux内核为了提升I/O性能,为最近刚“读”或“写”过的文件内容在内核中保留一份副本,当再次需要缓存中的内容时就不必从磁盘读入,而写入时,则是先写入到页缓冲中,空闲时候再从缓冲写入磁盘。
在Linux中,通过address_space结构体描述一个文件的页缓冲,在该结构体中,通过address_space_operation来维护页缓冲与具体文件系统设备层之间的关系与操作,例如具体文件系统ext4,该数据结构为:
该结构体为操作具体文件系统的块设备提供了统一的接口,readpage和writepage即实现的是页缓冲的读取和写入。每个特定的文件系统都需要实现address_space_operations结构体中的函数,这为在页缓冲上进行数据的加解密提供了有利的条件。
本文提出的基于双缓冲的透明加密文件系统主要由一个堆栈式文件系统组成,其在Linux内核中的位置如图2所示。
图2 系统架构图
该架构设计主要分为四个部分,用户态的控制台用于配置授信和非授信进程;访问控制管理层结合配置策略,决定进程应该访问明文缓冲还是密文缓冲;密钥管理层负责密钥的生成、存储和管理;page cache层维护着每个文件的密文缓冲和明文缓冲。
配置策略层:在用户态,使用QT为用户呈现一个易操作的配置界面,用来配置授信和非授信进程。该部分使用netlink与内核中的访问控制管理层进行通信。
访问控制管理层:在该层将配置策略层传递下来的策略信息用链表组织起来,并且实现了VFS定义的通用接口(open,read,write等),从而将用户态传递下来的对文件的操作和参数拦截下来。利用内核态描述进程和文件的结构体,获取当前正在操作的文件或者进程,和链表中的数据进行比对,来决定需要明文或者密文。
双缓冲层:在内核中使用名为address_space的结构体表示页缓冲,并使用基数树(radix Tree)进行组织。在该部分用两个address_space结构体,分别表示明文缓冲和密文缓冲,以供授信进程和非授信进程读取。另外,当发生写操作时,需要考虑数据一致性的问题,因为在写文件的时候,只是向密文缓冲区中写数据,必然导致两个缓冲区的内容有差异,为了解决数据同步的问题,在发生写操作时,需要去更新另一个缓冲区中基数树上对应的内容。
密钥管理:在本文中使用128位密钥的AES(Advanced Encryption Standard)算法和 FEK(File Encryption Key)、UEK(User Encryption Key)两种密钥[10]。加密文件内容使用的密钥被称为FEK,为了使得某个加密文件的FEK被泄露后,其他文件仍然安全,每个文件使用不同的FEK,即FEK随机产生,并且将加密过后的FEK写在每个文件末尾的128个字节,作为文件的元数据。另外使用公开密钥算法加密FEK,这样就需要一对密钥,统称为UEK,在加密文件系统中,UEK的私钥用来解密加密过的FEK,这是加密文件系统的重要信息,需要被安全的存放,在本文中使用对称加密算法AES对UEK进行加密,并将加密的UEK存放在用户主目录下使用ACL禁止别的用户访问。
Linux为了支持各种不同的文件系统,并且要给用户提供一个统一的文件系统界面,抽象了一个文件系统通用层,即虚拟文件系统(VFS)。VFS主要由一组抽象的,标准的文件操作构成,并且为用户提供系统调用,如read(),write()等。
为了实现双缓冲透明加密功能,首先需要对VFS中定义的open(),read(),write()函数进行重定向,在本文中称之为double_cache_open(),double_cache_file_read()和 double_cache_file_write()函数。在打开文件时,首先需要去文件末尾获取元数据,如果获取到了则说明该文件为加密过的文件,导入用户UEK私钥,解密并保存FEK,为后面解密密文数据做好准备;如果没有获取到元数据,则该文件为明文信息,在读写时依据策略选择加密或者不加密。
读流程如图4所示,T表示查找成功,F表示查找失败,Y表示是,N表示否。
图3 读操作流程图
图3所示的读文件的执行流程如下:
通过访问控制判定需要获取文件的明文或者密文信息。
1)如果需要获取明文数据,则在明文的页缓冲中查找。
(1)查找成功,则返回明文信息给用户态。
(2)查找失败,则在密文缓冲中查找对应的密文数据,找到后解密返回给用户态,并将该明文信息缓存于明文缓冲;如果没有找到,则从块设备获取对应的密文数据,解密返回给用户态并保存于明文缓冲。
2)如果需要查找密文数据,则在密文缓冲中查找数据。
(1)查找成功,返回密文信息给用户态。
(2)查找失败,从块设备中获取所需页,然后依据元数据判断该页是明文还是密文,如果是明文,需要先加密再返回给用户态,如果是密文直接返回给用户态。
写流程如图4所示。
图4 写操作流程图
图4所示的写文件的执行流程如下:
1)判断明文缓冲是否存在。
(1)存在,写入明文缓冲。
(2)不存在,新建明文缓冲后写入。
2)判断密文缓冲是否存在。
(1)存在,生成FEK对要写入的数据进行加密。
(2)不存在密文缓冲,新建密文缓冲,生产FEK对要写入的数据进行加密。
对块设备的读取和写入,内核提供了统一的接口,即struct address_space_operations中定义的钩子函数,所以需要对该结构体中的函数进行重定向,在编码时,做了以下定义:structaddress_space_operations{
在readpage和readpages函数中,当需要明文信息时,需要进行解密操作;在使用prepare_writepage和commit_write进行写操作时,进行加密操作,在磁盘上统一存放密文信息。
本文采用的软硬件测试环境如表1所示。
表1 性能测试的软硬件测试环境
为了评估双缓冲透明加密文件系统的整体性能,笔者分别将基于单缓冲的透明加密文件系统ecryptfs[11]和基于双缓冲的透明加密文件系统安装(mount)在本地磁盘(EXT4)上,并且设置iozone测试工具为非授信进程,创建一个守护进程作为授信进程,并发对文件进行读写操作,分别测试以下几种情况:
1)write:测试写入新文件的功能。
2)re-write:测试写入已经存在文件的性能。
3)read:测试读取新文件的性能。
4)re-read:测试读取最近刚读过的文件性能。
对以上几种测试情况,分别打开iozone测试工具的write,re-write,read,re-read测试开关,测试文件大小选择4M,16M,256M,4G。
安装ecryptfs文件系统后的测试结果如图表2所示。
表2 ecryptfs测试结果(单位:s)
安装双缓冲透明加密文件系统后的测试结果如图表3所示。
表3 双缓冲加密文件系统测试结果(单位:s)
由表2和表3可以得出,re-read和re-write相比于read和write对文件的操作时间明显减少,这主要是由于内核中的页缓冲对文件做了缓存,避免了从磁盘读取文件。基于双缓冲的透明加密文件系统在re-read时,由于在内存中缓存了文件对应的明文和密文信息,省去了频繁加解密的操作,所消耗的时间较ecryptfs减少了20%~33%。在写操作时,双缓冲透明加密文件系统较ecryptfs文件系统所消耗的时间增加了10%左右,这是由于双缓冲透明加密文件系统在写操作时,需要同步两个缓冲带来的时间消耗。
综合上面的测试结果可以得出,与单缓冲的透明加密文件系统相比,基于双缓冲的透明加密文件系统,在写操作上性能相差不大,在读操作上性能得到了明显的提升。在保证文件安全性的前提下,提升了透明加密文件系统的整体性能。
本文在现有透明加密文件系统的基础上,提出了一种基于双缓冲的透明加密机制,减少了现有透明加密文件系统中授信和非授信进程对同一块页缓冲频繁加解密的次数,从而提升了透明加密文件系统的整体性能,同时该文件系统以内核模块的形式存在,可移植性强。最后,通过实验证明了其可用性和高效性。随着信息安全技术的快速发展,如何在保证文件安全的前提下提高加密文件系统的性能,这为Linux操作系统上的加密文件系统提出了更高的要求。