在13年的时候做过一个项目,公司要求自己生产的AndroidPad只允许安装自己应用市场认证过的应用。
刚接到项目需求的时候就想到了验证数字签名的方案,
然后我就在后端上传应用的时候把Apk给重签名了,并且在PackageManager中做了签名校验,
然后我就交工了,
然后Q&A测试的时候说京东APP打开的时候提示APP是盗版的,
然后产品经理就找我了,
然后我就又开工了……
然后...
好啰嗦啊……好啰嗦
言归正传,前面的实验已经说明了问题,校验数字签名是不可行的,当然不可行的原因不只有这一个(通过数字签名共享进程,通过数字签名覆盖安装等都会有问题)。
在Android 【设置】->【安全】中一个【未知来源】的item。我刚开的时候没有阅读过PackageInstaller的代码,以为这个选项就是用来验证来源的,但是……
内置应用市场有system权限,可以静默安装,不走PackageInstaller,不允许未知来源指的是不可以从SDCard进行安装,变相符合需求,但是通过ADB安装的话是绕开PackageInstaller
上面所提到的方案都被否决了,
这样,要实现产品经理给的需求就又了一个先决条件
不能破坏或者修改APK的数字签名(附加文件等会破坏签名,需要重签)
革命还未成功,同志尚需努力
在分析了PackageParser代码后,并结合Apk包结构后做出了新的方案
先来看看APK的包结构
ZIP中每一个文件的压缩都分成如下三个部分
1.压缩源文件数据
2.压缩源文件目录区
3.压缩源文件目录结束标志
也就是说zip包内的所有分文件的压缩处理都有上面3个部分构成,有完整的开始和结束标志。
因此可以在zip包的末尾追加一些数据是不会影响zip包的完整性及APK解析的,基本方案就出来了
方案出来后怎样来保证渠道确实是自己的呢?我是这么来操作的
1.在apk的1/3,1/10,1/15,1/32等地方各取3个字节,算一个HashCode
2.用SHA-1摘要刚得到的HashCode
3.将SHA-1写入zip末尾(64Byte)
在PackageParser中反向上面步骤
1.从zpk末尾取64Byte数据
2.在zip文件中0到(zip长度-64)区域中1/3,1/10,1/15,1/32等地方各取3个字节,算一个HashCode
3.用SHA-1摘要HashCode
4.与从文件末尾获取的64Byte数据进行比较,相同则继续安装,不同则跳出,并返回安装失败的代码(adb中亦可见)
啰嗦一堆,关键就几句……
TIPS
在小米,联想等手机上,安装apk的时候回弹出一个确认对话框,其原理同样是在PackageParser中进行了修改限定,有时间可以尝试一下