Android 如何在客户端验证APK签名证书?
我正在开发一个android应用程序,它正在与服务器对话,我想在运行时验证我的应用程序在我发布后没有被修改过(使用修改过的应用程序的用户应该不能登录到应用程序) 由于修改后的应用程序签名与原始签名不同,我决定:Android 如何在客户端验证APK签名证书?,android,security,certificate,client-server,apk,Android,Security,Certificate,Client Server,Apk,我正在开发一个android应用程序,它正在与服务器对话,我想在运行时验证我的应用程序在我发布后没有被修改过(使用修改过的应用程序的用户应该不能登录到应用程序) 由于修改后的应用程序签名与原始签名不同,我决定: 提取嵌入到android应用程序中的签名证书 将其与登录请求一起发送到服务器(在客户端(即apk)编码整个验证过程不起作用,因为有人可能修改apk以绕过它。) 核实一下 如果证书有效,则处理登录请求/else返回错误 这是我上面1号的代码: Context context = this;
Context context = this;
PackageManager pm = context.getPackageManager();
String packageName = context.getPackageName();
int flags = PackageManager.GET_SIGNATURES;
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(packageName, flags);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Signature[] signatures = packageInfo.signatures;
所以我的问题是:
2.1发送证书会占用高带宽吗?
2.2如何验证证书?(我在服务器端有mykey.jks,我最初用于签署apk)
(这也是我关于stackoverflow的第一个问题,因此我非常感谢您指出我在提问时犯的任何错误)首先,人们总是可以绕过这种安全性,例如,通过硬编码传递给服务器的证书。你只能尽力让它变得更难,但它永远不会是100%安全的 尽管如此,你现在所做的似乎还可以。请注意,最新SDK中的
pm.signingInfo
不推荐使用pm.signingInfo
就大小而言,证书并不大,但要使请求更小,您可能只需要发送一个哈希(例如SHA256)
防止用户对请求中的证书进行硬编码,还可以考虑将另一个值与证书一起散列,即散列(证书+时间戳),并在请求中发送时间戳,这样您就可以重新计算哈希服务器端。如果时间戳距离当前日期太远,则拒绝请求。同样,它不是完全安全的,但它为代码的反向工程增加了另一层复杂性。您还可以添加versionCode并开始拒绝旧版本的请求(例如,如果您在一个旧版本中检测到安全漏洞),并提示这些用户更新应用程序(或者在后台为他们执行此操作,并且由于新的API Play提供,仅提示安装)
正如有人指出的,您的代码还可以检查安装是否来自Play(packageManager.getInstallerPackageName(getPackageName()).equals(“com.android.vending”);
),但这些信息很容易被伪造,因此不确定是否会增加安全性
希望这会有所帮助,正如@Pierre已经指出的那样,您执行检查的方式是有效的,但我想提醒您一个事实,使用诸如或之类的检测框架,可以在运行时绕过证书固定,但仍然建议您将其用作另一个安全层。有关这方面的更多见解,请快速阅读以了解钉扎如何易于实现,从操作角度来看,钉扎如何可能成为维护的噩梦,以及如何绕过钉扎 有没有更好的方法来验证apk 是的,它存在,被称为移动应用程序认证。此解决方案将包括集成在移动应用程序中的SDK,该SDK在后台与云服务通信,因此不会影响用户体验
移动APP认证解决方案在运行时保证应用程序不是中间人攻击、被篡改、不在根除或越狱设备中运行、不附在调试器上、不运行在仿真器上,而是与App Store或谷歌Play商店上传的原始版本相同。 因此,成功认证移动应用完整性的云服务会发布一个非常短暂的签名,该签名使用的秘密只有API服务器和云中运行的移动应用认证服务知道。在认证失败时,JWT使用API服务器不知道的秘密进行签名。在每个对API服务器的请求中,移动应用程序将发送此JWT令牌,API服务器将验证签名是否有效以及令牌是否已过期,并在任何验证失败时拒绝请求
云认证服务所使用的秘密不被移动应用程序所知,即使在移动应用程序被篡改、在有根设备中运行或通过作为中间人攻击的目标的连接进行通信时,也不可能反向设计JWT令牌。 你可以在(我在这里工作)中找到这样一个服务,它有几个平台的SDK,包括Android。集成还需要在API服务器代码中进行一次小检查,以验证JWT令牌
面向开发人员、逆向工程师和安全研究人员的动态检测工具包 Xposed是一个模块框架,可以在不接触任何apk的情况下更改系统和应用程序的行为 基于令牌的身份验证 JSON Web令牌是一种开放的行业标准RFC 7519方法,用于在双方之间安全地表示声明或者你可以检查一下你的应用程序。是否从play store下载。就是这样。这也很好,但问题是,它完全依赖于客户端,所以可以相对容易地绕过它。但这也不会影响到检查的水平。是的,我在寻找一种完美(至少是近乎完美)的方法。我想我太天真了。但无论如何,我想添加多层安全检查并没有什么坏处。另外,感谢您对SDK和API以及时间戳方法的更新。我一定会留意的。您可以在发布之前在服务器上保存发布时间戳