我正在尝试在运行时检查我的应用的发布签名,以防止篡改。但是,我一直在读的是,我需要在运行期间记录签名,以便可以将其硬编码到我的应用程序中以进行运行时比较。但是我看到两个问题:1)调试(读取日志)时获得的签名将与发行签名不同。2)如果我获得了发行签名,然后将其放入我的代码中以进行运行时比较,那会不会更改下一个发行版本的签名...因此出现了鸡与蛋的问题?我想念什么?静态最终字符串不会更改签名吗?同样,如果我发布日志输出,日志代码不会更改签名吗?什么会对发布签名产生影响?
如果计算包括签名本身在内的字节的签名,那么是的,您将遇到鸡肉和鸡蛋问题。但您不必:在签名之外的所有内容上计算签名。实际上,这就是jarsigner
are done生成签名的方式。
但是我想您真正想要的是,因为apk
文件已经签名,所以要检查签名者信息是否与您自己的信息匹配。可以通过将软件包的签名者证书与您自己的证书进行比较来完成。
您可以从Android Security Cookbook中看到通过的示例,该示例执行了这种检查here。
如果我想更改您的apk,请按以下步骤操作:
我会遇到问题,在第5步,因为我没有您的私钥和签名,所以我应该创建自己的私钥并用我的密钥签名。然后,我希望没有人在安装应用程序之前检查标志(没有人做!)。
因此,我被篡改的应用与您的应用有两个区别,即资源更改和签名证书更改。
如果要检查更改的资源(签名超过字节),将遇到鸡和蛋的问题。
阻止我的最简单方法是对应用程序签名进行硬编码],然后检查它是否在运行时更改了。
示例代码位于https://gist.github.com/scottyab/b849701972d57cf9562e
此检查的简单方法:
private boolean validateAppSignature() { APP_SIGN= "f10e2821bbbea527ea02200352313bc059445190"; PackageInfo packageInfo = this.getPackageManager().getPackageInfo( getPackageName(), PackageManager.GET_SIGNATURES); for (Signature signature : packageInfo.signatures) { // SHA256 the signature String AppSign = DigestUtils.sha256Hex(signature.toByteArray()); return APP_SIGN.equalsIgnoreCase(AppSign); } return false; }
当然,即使可以更改混淆的代码,这也不是100%的解决方案。因此,我可能会找到一种通过此检查的方法。但是你让我更难篡改:)