APP安全之APK完整性校验
2016-05-22 21:19
381 查看
APP安全之APK完整性校验
前言
APK 完整性校验,虽然很难做到绝对的安全,但能提高应用的安全性和破解难度。一、认识APK安全性
危害
可以通过修改客户端文件篡改客户端行为。攻击者可以让客户端显示自己制作的钓鱼网站,偷取用户信息二、完整性校验原理
完整性校验的几种方式
CRC校验MD5值校验
SHA1值校验
常见android完整性检测
检测签名校验classes.dex
校验整个apk
检测签名
Android对每一个Apk文件都会进行签名,在Apk文件安装时,系统会对其签名信息进行比对,判断程序的完整性,从而决定该Apk文件是否可以安装,在一定程度上达到安全的目的。MANIFEST.MF:这是摘要文件。程序遍历Apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个用SHA1生成摘要信息,再用Base64进行编码。如果你改变了apk包中的文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是程序就不能成功安装。
CERT.SF:这是对摘要的签名文件。对前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用开发者的私钥进行签名。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息(即,MANIFEST.MF文件)进行对比,如果相符,则表明内容没有被异常修改。
CERT.RSA文件中保存了公钥、所采用的加密算法等信息。系统对签名文件进行解密,所需要的公钥就是从这个文件里取出来的。
这三个文件在apk META-INFO文件夹
结论:从上面的总结可以看出,META-INFO里面的说那个文件环环相扣,从而保证Android程序的安全性。(只是防止开发者的程序不被攻击者修改,如果开发者的公私钥对对攻击者得到或者开发者开发出攻击程序,Android系统都无法检测出来。)
虽然系统通过以上方式可以防止,但如果是root的手机就不安全了,建议通过服务器来校验,
校验classes.dex
用crc32对classes.dex文件的完整性进行校验public class MainActivity extends Activity { @Override protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String apkPath = getPackageCodePath(); Long dexCrc = Long.parseLong(getString(R.string.classesdex_crc)); //建议将dexCrc值放在服务器做校验 try { ZipFile zipfile = new ZipFile(apkPath); ZipEntry dexentry = zipfile.getEntry("classes.dex"); Log.i("verification","classes.dexcrc="+dexentry.getCrc()); if(dexentry.getCrc() != dexCrc){ Log.i("verification","Dexhas been modified!"); }else{ Log.i("verification","Dex hasn't been modified!"); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
校验整个apk
用哈希值对整个apk完整性进行校验public class MainActivity extends Activity { @Override protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String apkPath = getPackageCodePath(); MessageDigest msgDigest = null; try { msgDigest = MessageDigest.getInstance("SHA-1"); byte[] bytes = new byte[1024]; int byteCount; FileInputStream fis = new FileInputStream(new File(apkPath)); while ((byteCount = fis.read(bytes)) > 0) { msgDigest.update(bytes, 0, byteCount); } BigInteger bi = new BigInteger(1, msgDigest.digest()); String sha = bi.toString(16); fis.close(); //这里添加从服务器中获取哈希值然后进行对比校验 } catch (Exception e) { e.printStackTrace(); } } }
我们将把crc值和sha1值放在服务器做处理
相关文章推荐
- android:theme 与 setTheme()设置透明效果并不同
- Android View源码解读:浅谈DecorView与ViewRootImpl
- 【黑马Android】(10)绑定的方式调用服务的方法/图片的各种操作/人脸识别
- Android中的类加载器
- iOS多线程的初步研究(九)-- dispatch源
- iOS多线程的初步研究(一)-- NSThread
- iOS常用尺寸
- SQLite数据库基本使用(swift)
- Unity3D 之UGUI 滑动条(Slider)
- 设计模式与代码重构——ios篇
- Unity 简单读取txt文档内容的方法
- Swift 协议详解
- Android 定时任务的多种实现方式
- iOS实时卡顿监控
- IOS学习笔记——object-C基础 (二)
- Android的4中启动模式
- 一个刚到此吧的IT新人,第一次发博客,望大家多多指教
- <Android 基础(一)> Service
- <Android 基础(一)> Service
- ubuntu16.04的启动栏(Unity)方向更改