李春杰 孙玉强 徐 楷 颜智润
(中国科学技术大学苏州研究院 江苏 苏州 215000)
近年来,移动终端设备领域的发展十分迅猛,智能手机成了新时代生活的必需品,短短几年间,Android已经成为了最热门的智能终端开发平台之一[1]。如今普通用户习惯使用智能移动设备拍摄照片,对照片进行传播和分享。但智能移动设备上保存的大量照片却产生了隐私泄露的隐患[2]。在Android移动手机平台上,安全防护是一个重要的研究方向,以图片加密为主要功能的隐私保护是其中很重要的一个功能需求[3]。
以往在Android移动手机上实现图片加密,用户通常会通过安装加密软件来解决这个问题。不过现有多数Android图片加密软件的加密过程十分繁琐,每拍摄一张新的照片都需要用户手动进行加密,使得加密的实时性很差,用户体验非常糟糕。于是我们设计了一款名为“透明加密助手”的软件,能够以对用户完全透明的方式将拍摄的照片进行自动加密,在提升用户体验的同时还能保障安全性能。
当用户需要对拍摄的照片进行自动加密时,首先打开本软件并保持其在后台运行,之后用户在Android手机自带的相机软件上进行拍照操作,生成的照片都会自动被本软件捕获到并进行加密存储。从捕获照片到加密存储,这一过程完全不需要用户参与,其实现过程是不可见的,因此用户在每次拍照后无需对生成的照片进行单独的加密操作,只需保证本软件在后台运行即可。此外本软件还集成了解密功能,当用户需要还原被加密的照片时,进入本软件,可以浏览到所有被加密的照片,点击照片对应的“解密”按钮,就可以将照片还原。解密过程由用户参与,用户可以自由选择需要解密的照片。透明加密助手软件的功能示意图如图1所示。
图1 透明加密助手功能示意图
根据软件的功能实现,本软件的结构应分为三个层次。第一层为视图层,本软件的加密过程对用户完全透明,解密过程则需要用户的参与,因此图形用户界面是必不可少的。第二层为业务层,这是结构中最重要的一层,软件主要的功能实现都由业务层来承担,其核心的部分为监听模块[4]、加密模块、存储模块,以及解密模块。第三层为数据库层,本软件的操作对象是图片文件,对文件的操作必然要涉及文件的路径,而加密与解密的过程则离不开密钥,因此这些重要数据都需要存储于数据库中。软件的架构图如图2所示。
图2 透明加密助手软件架构图
透明加密助手的工作原理为:在软件登录成功且处于运行期间,当用户进行拍照操作时,监听模块会捕获到拍照动作并启动加密模块对刚生成的照片进行加密处理,加密成功后存储模块会对密文进行存储;当用户需要解密照片时,点击照片对应的“解密”按钮会启动解密模块完成解密操作,之后密文会被删除,原始照片将被还原至系统图库中。透明加密助手的工作流程如图3所示,从图中可以看出,除了基本的加密与解密功能外,本软件的功能实现还必须解决如下四个方面的技术重点:
图3 透明加密助手工作流程图
我们不希望在本软件中集成拍照功能,这样做一是浪费资源,二是会强行改变用户的使用习惯,因为用户可能更习惯使用系统自带的相机软件。而这便会带来一个问题,就是我们不知道拍照软件的底层代码,因此如何捕获其拍照动作便是一个重点。
本软件的加密对象是照片,而要对照片文件进行加密操作,必须获得其绝对路径,即存储路径加文件名。由于本软件不集成拍照功能,因此照片的存储路径及照片的命名规则均是由系统相机的代码实现的,这样一来我们便不能通过文件名获取到刚拍摄的照片了。
在对目标照片进行加密后,虽然无法查看照片内容了,但是仍然存在加密后的文件被恶意删除或误删除的可能,因此加密后的文件仍然要对用户保持不可见状态。这一功能的实现有两种解决思路:一是加密后的文件仍存储在相机软件的默认路径下,然后将其设为不可见;二是将加密后的文件移至本软件创建的文件夹下,并设该文件夹为不可见。我们需从这两个方法中选出最优的一个。
在解密的过程中,由于加密后的文件路径以及加密算法对应的密钥都是已知的,因此将密文还原为照片并不困难。但是当软件加密了多张照片后,用户需要解密哪一张照片是不确定的,即用户在进入本软件后,需要看到已被加密的照片才能决定解密哪一张。因此如何在照片已被加密的情况下查看原始照片便是解密功能实现的重点。
针对软件功能实现的四项技术难点,我们在调研相关资料之后,给出如下解决方案。
在查阅Android Developer(安卓开发者)文献后,我们发现在Android API14即Android 4.0之后,Google在Camera中添加了一个action,在拍摄照片后系统会发出一条值为:“android.hardware.action.NEW_PICTURE”的无序广播[5],并且这条广播是在照片文件生成后发出的,即在照片存储到默认路径下后可以监听到这条广播。进一步调研相关内容后,我们发现除了官方给出的这个action之外,其实在照片拍摄完成后,系统相机软件会自动发出另一条值为:“com.android.camera.NEW_PICTURE”的无序广播,这条广播并未写进官方的文档,但是在实际的商业应用中,这条广播也经常会用到。
于是我们可以创建一个名为“CameraAction_Rece-iver”的类,让它继承BroadcastReceiver作为广播接收器,并重写其onReceive()方法,创建Intent的实例,在接收到系统相机软件发出的广播后用Intent启动一个Service,由这个Service完成后续操作。我们使用静态注册的方式在AndroidManifest.xml文件中对该广播接收器进行注册,在
在CameraAction_Receiver接收到广播后,通过Intent启动一个Service,在该Service中可以进行查找照片、移动照片及加密照片等操作。我们创建一个名为“Bitmap_Service”的类,让它继承IntentService,继承IntentService的好处是在代码执行完毕后服务会自动关闭,且只需重写一个onHandleIntent()方法。由于我们不知道相机软件的底层代码,所以无法通过文件名来查找目标照片。但是Android本身提供了一个多媒体数据库MediaStore,它包含了Android手机上的所有多媒体信息可供外界查看调用。查找数据库中的内容需要使用接口ContentResolver[6],而ContentResolver对数据的访问则是通过URI,每一个URI地址值都唯一对应一个资源文件。因为我们查找的目标只是图片文件,且文件是处于外部存储空间中的,所以查找的范围应为“MediaStore.Images.Media.EXTERNAL_CONTENT_U-RI”,它是ContentProvider的URI地址值,指向所有图片文件。在确定了查找的范围后,调用ContentResolver的query()方法在MediaStore.Images.Media.EXTERNA-L_CONTENT_URI中进行查找。query()方法有5个入口参数,第一个参数为指定的内容提供者的URI地址值,即查找范围;第二个参数为查找返回的结果,这里我们需要获取到MediaStore中所有图片的绝对路径,即new String[]{MediaStore.Images.Media.DATA},结果会以数组的形式返回;第三个参数为查询条件,即对返回的结果进行筛选,这里我们没有特殊的需求,所以可设为null;第四个参数需配合第三个参数使用,可对筛选后的数据进行修改,当然在这里也设为null;第五个参数为排序条件,即对返回结果按条件进行排序,我们需要对MediaStore中的所有图片按ID进行排列,所以参数可设为MediaStore.Images.Media._ID +“DESC”,其中“DESC”表示降序排列。通过query()方法进行查找,我们便能够得到一个按ID降序排列的所有图片的绝对路径集合,显然,刚拍摄生成的照片的绝对路径一定处于这个集合的顶部。使用Cursor类对该集合进行逐条遍历,当Cursor指向第一个数据时我们便得到目标照片的绝对路径了。
通过对市面上多数主流隐私保护软件的调研,我们发现这些软件都是采用将加密后的文件保存在自己生成的不可见目录中的方法,以达到隔离加密文件的效果。这样做符合隐私保护的逻辑:
(1) 加密后的文件不再属于公共类文件,不应该与无访问权限的普通文件存储在一个目录中。
(2) 将本软件加密生成的文件保存在软件自身生成的目录下便于管理。
(3) 将存储加密文件的目录设为不可见可以防止用户将目录误删除而造成文件丢失。
有了这个思路之后,我们可以采用将目标照片文件从源存储路径移动到目的路径同时进行加密的方法使照片与用户隔离起来,代码仍在Bitmap_Service类中实现。上述获取到的目标照片的源存储路径可以通过cursor.getColumnIndex()获得;目的路径由三部分组成:手机外部存储空间的根目录,不可见文件夹名,加密文件的文件名。外部存储空间的根目录可由Environment.getExternalStorageDirectory()获得,不可见文件夹名以“.”开头,命名为“.TransEncryptHelper”,加密文件的文件名由UUID生成的32位唯一识别码命名。得到了原路径和目的路径后,使用Java的I/O流来转移照片。首先创建FileInputStream的实例从源路径读取字节数据,然后创建OutputStream的实例将字节数据写入目的路径,写入的同时对数据进行加密。
加密的方法是创建加密算法的Util类,并生成算法的密钥,之后调用Util类的encrypt()方法将数据流与密钥一同加密,当数据流全部写入目的路径后,得到的就是加密后的文件了。
与加密过程相比,本软件解密功能的实现较为简单,解密的过程需要用户的参与,即由用户来选择需要解密的照片,点击对应的“解密”按钮,通过加密算法的逆算法对加密文件进行解密。解密功能实现的难点是在照片被加密的情况下,在软件内部看到原始图片。为了解决这个问题,我们需要在捕获到目标照片后先生成其缩略图,再对目标照片进行加密操作。
缩略图由Bitmap类生成,但Bitmap类的构造函数是私有的,需使用接口BitmapFactory对Bitmap进行实例化,再调用其decodeFile()方法将Bitmap解析出来。在解析之前,先使用BitmapFacotry.Options实例化一个options对象,options的多个属性可以指定decodeFile()方法的选项,其中inSampleSize属性可以设置解析出来后Bitmap的尺寸。解析出Bitmap后,便可以得到照片的缩略图,调用Bitmap的compress()方法可以设置生成的缩略图的格式,有JPG与PNG两种格式可供选择。最后,将生成的缩略图保存在本软件的私有目录下,其他应用便没有权限访问到该缩略图,当打开本软件后,将缩略图加载到ImageView控件上,用户就可以看到被加密的照片了。
通过上述四个解决方案,我们基本可以实现透明加密助手的功能需求。但是在实际应用中,我们还希望本软件能在加密的安全性与时效性上都有较好的表现,因此,针对目前常用的几种加密算法,我们还需分别进行测试,以选出最优算法。
Android本身带有Java提供的一些软件包,如java.security和javax.crypto,为我们提供了多种加密算法的接口。在选择加密算法之前,我们首先应当排除MD5算法[7],因为MD5算法的加密过程是不可逆的,照片被加密后将无法还原。考虑到本软件对安全性能的要求并不高,常用的加密算法如RSA-1024[8],DES[9]以及AES-128[10]的安全性都是可以满足的,因此我们将针对这三种算法的加、解密效率分别进行测试。测试环境如表1所示。
表1 软件测试环境
我们首先对128位密钥的AES加密算法进行测试。为了使测试结果更加清晰准确,我们将加密部分的代码与解密部分的代码写在同一个Service下,在程序执行完加密操作后立刻执行解密操作。同时我们在程序中用Log.d()语句在logcat内打印三条调试信息,这三条调试信息分别插入在捕获到目标照片的路径、加密完成以及解密完成的代码之后,打印调试信息的同时logcat会自动打印出当前的时间信息,通过比较三条时间信息间的时间差就可以判断算法的加、解密效率如何。
从图4可以看出,AES-128算法对五张照片的加密耗时均不足1秒;对密文的解密耗时较加密耗时长,其中对白色墙壁照片的解密耗时最短,约为2.7秒,对电脑屏幕照片的解密耗时最长,约为24秒。
我们以同样的方法对DES算法和RSA-1024算法分别进行测试。结果显示,DES算法较AES-128算法的性能略有下降,随着照片文件大小的增加,其解密耗时增长较快;RSA-1024算法的性能较差,其对白色墙壁照片的加密耗时达到3分31秒,解密耗时则难以统计。最后我们从三种算法加密的五张照片中各选取三个典型的照片大小,将它们与加密后的密文大小进行比较,如表2所示。可以看出RSA-1024算法对照片加密后,生成的加密文件大小有所增加,而DES算法和AES-128算法加密前后文件大小不变。
通过对安全性能、加密与解密效率以及加密前后文件大小三个方面进行对比后,128位密钥的AES算法无疑是最满足需求的。
最后,我们在华为荣耀7上安装“透明加密助手”软件测试实现效果。首先在未打开本软件的情况下用系统相机拍摄一张水杯的照片,这张照片会保存在“Camera”文件夹内。接下来我们打开“透明加密助手”软件,保持其在后台运行,并再次打开系统相机软件拍摄一张签字笔的照片,这时我们会发现在“Camera”文件夹下并没有出现刚才拍摄的签字笔照片。在Android手机已获取root权限的情况下,打开Root Explorer文件管理器,找到“.TransEncryptHelper”文件夹,可以看到一个加密文件,文件名为UUID生成的32位唯一识别码,这就是签字笔照片被加密后的文件,如图5所示。最后将加密文件还原,进入本软件,在“已加密图片”界面可以看到被加密图片的缩略图,点击解密按钮进解密,如图6所示,解密后的签字笔照片会还原到“Camera”文件夹下,如图7所示。
图5 加密文件
图6 解密界面
图7 签字笔照片
Android操作系统是目前用户数量最多的手机操作系统之一,本文针对Android用户在日常使用中的痛点,改进了对用户所拍摄照片的加密方法,在保证安全性的同时提升了用户体验。经过在华为荣耀7、红米4A等多种型号手机上的测试,本软件均能实现对照片的自动加密,成功率很高。此外,通过监听广播实现文件自动加密的方法还可以推广至音频、视频、文档、短信等安全领域。随着Android用户的不断增长,以及人们对个人隐私安全关注度的提升,我们相信透明加密助手软件在未来有很高的实用价值,本文提出的自动加密方法在实际软件开发中也有较好的应用前景。
[1] 黄振涛,何暖,付安民,等.基于透明加密的移动终端数据防泄露系统[J].通信学报,2016,37(Z1):189-196.
[2] 王艳敏,李永忠,吕少伟.Android平台下文件透明加密技术的研究与实现[J].计算机技术与发展,2014,24(9):137-140.
[3] 周道明,钱鲁锋,王路路.透明加密技术研究[J].信息网络安全,2011(12):54-56.
[4] 包佳敏,胡爱群.Android系统文件监听技术的研究[J].信息网络安全,2014(3):46-51.
[5] 卿斯汉.Android广播机制安全性研究[J].电信科学,2016(10):27-35.
[6] 尹京花,王华军.基于Android开发的数据存储[J].数字通信,2012,39(6):79-81.
[7] 张裔智,赵毅,汤小斌.MD5算法研究[J].计算机科学,2008,35(7):295-297.
[8] 李云飞,柳青,郝林,等.一种有效的RSA算法改进方案[J].计算机应用,2010,30(9):2393-2397.
[9] 解双建,原亮,谢方方.DES算法原理及其FPGA实现[J].计算机技术与发展,2011,21(7):158-160,164.
[10] 张金辉,国晓彪,符鑫.AES加密算法分析及其在信息安全中的应用[J].信息网络安全,2011(5):31-33.