概述
Android的签名机制相信大家经常会遇到的,当我们做好一款APP准备发布的时候我们就需要一个realese的key文件给我们这个app签名.那我们没有指定的APK是不是就没有签名呢,?并不是,所有的APK都是有签名的,如果没有指定签名文件,编译时会默认用SDK目录下的debug签名文件.
签名作用
Android签名机制有很多的作用 :
应用程序升级:如果你希望用户无缝升级到新的版本,那么你必须用同一个证书进行签名。这是由于只有以同一个证书签名,系统才会允许安装升级的应用程序。如果你采用了不同的证书,那么系统会要求你的应用程序采用不同的包名称,在这种情况下相当于安装了一个全新的应用程序。如果想升级应用程序,签名证书要相同,包名称要相同!
应用程序模块化:Android系统可以允许同一个证书签名的多个应用程序在一个进程里运行,系统实际把他们作为一个单个的应用程序,此时就可以把我们的应用程序以模块的方式进行部署,而用户可以独立的升级其中的一个模块
代码或者数据共享:Android提供了基于签名的权限机制,那么一个应用程序就可以为另一个以相同证书签名的应用程序公开自己的功能。以同一个证书对多个应用程序进行签名,利用基于签名的权限检查,你就可以在应用程序间以安全的方式共享代码和数据了
使用方法
命令行配置
Gradle配置
签名文件分析
签名文件有很多种,这里主要是介绍Android相关的,比如最早的keystore,jks,pem/pk8等
KeyStore: KeyStore是Eclipse开发Android的时候最早的签名文件了.
JKS(Java key store): JKS是目前Android Studio中创建签名文件的格式(Build -> Generate Signed APK)即可创建和使用签名文件为对应apk进行签名
pem/pk8 :这个是系统的签名文件,Android系统在编译的时候也是需要签名,所以这个是系统的签名文件,那系统签名文件可不可以签名APK呢?答案是:可以.
上面就是我们APP解压以后的文件结构。META-INF里面存放的就是签名文件生成的内容。
META-INF\ :描述包信息的目录,签名后的信息存放的地方
res\:存放资源文件的目录
libs\:ndk 编出来的 so 库
classes.dex:Dalvik字节码,超过64K,所以分包,有多个
resources.arsc 编译后的二进制资源文件
接下来针对META-INF\文件进行分析
MANIFEST.MF:存储的是APK包中的每一个文件利用SHA1算法生成的摘要信息。
CERT.SF:保存的是MANIFEST.MF的摘要值(第一项),以及MANIFEST.MF中每一个摘要项的摘要值
CERT.RSA:文件保存了签名和公钥证书。签名用到的信息摘要就是CERT.SF内容
签名生成
首先使用哈希算法(SHA1 或者 SHA256)对未签名 apk 的每一个文件进行 hash计算,将值以 Base64 的格式保存在 MANIFEST.MF 文件中,这是生成每个文件的消息摘要;
对 MANIFEST 文件生成消息摘要,在对 MANIFEST.MF 中每个文件的内容再生成消息摘要,并将结果保存在 CERT.SF的头属性中,在对MANIFEST.MF文件中各个属性块做一次算法,存到到一个属性块中。
对CERT.SF文件做签名,内容存档到CERT.RSA中
最后将生成的三个文件放入到 META-INF 目录下,并打包成 apk,这样就完成了应用程序的签名。
签名校验
应用的签名只有开发者才拥有,如果别人修改了代码,也必须要签名才能运行,但是修改者的签名与官方签名是不一致的,我们在so里面存储了应用程序官方签名的hashcode值,在应用启动后so就会检查签名是不是官方的签名,如果不是,应用程序直接关闭,so里面的加密函数也都不起作用
如图更改了签名的安装包覆盖安装时会报错,禁止安装:
传统的在java层的签名校验有很多不足,不仅容易被反编译,而且操作不够灵活。目前签名校验有以下几种加强方式:
NDK层校验
简单来说,NDK就是用C/C++在Android开发的一组套件,一般来讲以so的形式存在,JAVA代码通过JNI接口来调用,当然也可以独立编译为具有main入口的可执行程序
NDK的好处是增加了程序的复杂度,因为so通过反汇编,得到的是ARM代码,而不是smali这种易重修改、易理解的代码。修改so难度将大增。
修改签民文件大小
app安装解析的过程中都没有对文件大小进行强制验证 可以通过 contentInfo 中的 length 来确定文件大小,是,即可以在文件末尾任意增加字符而不会影响使用。因此可以在文件末尾增加任意大小的字符,若被重新签名可以通过验证文件大小来确定。
服务端校验
challenge-response的方法,服务器发来challenge,然后程序用自身特性的一个字符串加密后再返回response,如果正确,则通过验证,反之则阻止运行。
升级版:服务器不是返回一个字段,而是返回一段核心代码,然后程序动态执行这段核心代码。
加强混淆
在APP打包过程中在 Jar => Dex 这步用了自定义的混淆方式,将类名、函数名和变量名都替换成了繁体中文
目前大多数反编译工具对 这种utf8 字符的处理存在问题
爱又米APP安全加固分析
已做措施:
1.采用HTTPS请求
2.通过签名让服务端校验请求来源的合法性
3.敏感性静态常量数据打散、加密存储
4.混淆
5.支付密码采用安全键盘
6.应用双开检验
适合加强的措施:
1.签名校验
2.恶意进程的检测,比如xposed
3.加强版混淆
4.加强加密存储方式,账号密码之类的不明文存储
5养成Android安全编程的习惯:
不允许打印敏感数据,再在发版前必须关闭打印日志的开关
对于要和外部交互的组件,应当添加一下访问权限的控制,还需要要对传递的数据
进行安全的校验对外开放的组件可以接收Intent,一般里面会包含一些数据,当我们没有对这些数据判空时候,app一般会crash,攻击者可能发送数据为空的Intent来攻击。
6.对于支付密码的自定义键盘截屏保护,因为连续快速截屏,或者视频录制可以获取用户的密码。
应对方案:对第三方或系统截屏编写抵抗逻辑,例如屏蔽和截屏相关的函数或是当客户端处于进程栈顶层时将截屏图片用纯黑色图片对象进行覆盖。
7用户操作上:
添加手势密码或指纹登录,进入信用钱包需验证;应用切换到后台但程序没有结束运行,再返回应用的时候也进行密码验证;
修改密码添加私密问题验证
待研究方向---应用加固
应用加固包括病毒扫描模块,防注入,防调试,防篡改模块四个模块,目前行业内已经出现了很多的应用加入解决方案,入爱加密、梆梆加密、百度加密等。
总结
我们爱又米APP既有电商业务又有金融业务,因此我们需要有一套较完善的安全技术方案做支撑,希望通过这次关于android签名和应用安全加固的分享,能使我们的APP变的更安全!
领取专属 10元无门槛券
私享最新 技术干货