我正在尝试在运行时检查我的应用程序的发布签名以防止篡改。但是,我一直在阅读的是我需要在运行期间记录签名,以便我可以将其硬编码到我的应用程序中以进行运行时比较。但我发现这有两个问题: 1)调试(读取日志)时获得的签名将与发布签名不同。 2)如果我获得了发布签名,然后将其放入我的代码中进行运行时比较,那么这不会改变下一个版本构建的签名...因此鸡和鸡蛋问题? 我错过了什么?静态最终字符串不会改变签名吗?同样,如果我记录发布输出,日志代码不会更改签名吗?对发布签名有何影响和不影响?
答案 0 :(得分:0)
If compute the signature over bytes that include the signature itself then yes, you will have chicken and egg problem. But you don't have to: compute the signature over everything but the signature. That's in fact how signatures generated by jarsigner
are done.
But what I think you really want, since apk
files are already signed, is to check if the signer information matches your own. And that can be done by comparing the package's signer certificate with your own certificate.
You can see an adopted example from Android Security Cookbook that performs such check here.
答案 1 :(得分:0)
如果我想更改您的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%的解决方案。因此,我可能会找到一种通过此检查的方法。但是你让我更难篡改:)