Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/223.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何在客户端验证APK签名证书?_Android_Security_Certificate_Client Server_Apk - Fatal编程技术网

Android 如何在客户端验证APK签名证书?

Android 如何在客户端验证APK签名证书?,android,security,certificate,client-server,apk,Android,Security,Certificate,Client Server,Apk,我正在开发一个android应用程序,它正在与服务器对话,我想在运行时验证我的应用程序在我发布后没有被修改过(使用修改过的应用程序的用户应该不能登录到应用程序) 由于修改后的应用程序签名与原始签名不同,我决定: 提取嵌入到android应用程序中的签名证书 将其与登录请求一起发送到服务器(在客户端(即apk)编码整个验证过程不起作用,因为有人可能修改apk以绕过它。) 核实一下 如果证书有效,则处理登录请求/else返回错误 这是我上面1号的代码: Context context = this;

我正在开发一个android应用程序,它正在与服务器对话,我想在运行时验证我的应用程序在我发布后没有被修改过(使用修改过的应用程序的用户应该不能登录到应用程序)

由于修改后的应用程序签名与原始签名不同,我决定:

  • 提取嵌入到android应用程序中的签名证书
  • 将其与登录请求一起发送到服务器(在客户端(即apk)编码整个验证过程不起作用,因为有人可能修改apk以绕过它。)
  • 核实一下
  • 如果证书有效,则处理登录请求/else返回错误
  • 这是我上面1号的代码:

    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;  
    
    所以我的问题是:

  • 有没有更好的方法来验证apk
  • 如果此方法可行,
    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以及时间戳方法的更新。我一定会留意的。您可以在发布之前在服务器上保存发布时间戳