【问题标题】:Confirm APK identity with keystore使用密钥库确认 APK 身份
【发布时间】:2013-08-24 03:57:01
【问题描述】:

我正在构建一个与在线网络服务通信的 Android 应用程序。我计划在 GitHub 上发布应用程序的源代码。对于我的生产版本,它将使用我的个人网络服务,我只想允许我的数字签名 apk 连接。

是否可以请求 APK 的密钥库并从该密钥库确认用户名/密码?

如果这是不可能的,我还能如何产生这个功能?

编辑:

我已阅读课程Certificate 看起来我可以使用公钥/私钥来确认身份。但我仍然不确定实现方式

【问题讨论】:

  • 密钥库中的用户名/密码?如果我理解正确,您想将您的网络服务限制为您签名的 apk?
  • 没错,现在我能想到的唯一方法是确认 apk 是由我使用我的用户名/密码进行数字签名的。
  • 您使用用户名签名?怎么样?
  • 在发布过程中,您将创建一个包含您的用户名/密码的密钥库文件。 Play 商店使用它来验证您的身份。更多信息请访问developer.android.com/tools/publishing/app-signing.html

标签: android authentication key keystore


【解决方案1】:

我用这个——

    static public String getPackageFingerPrint( Context ctx ) {
        PackageManager pm = ctx.getPackageManager();
        String packageName = ctx.getPackageName();
        int flags = PackageManager.GET_SIGNATURES;

        PackageInfo packageInfo = null;

        try {
                packageInfo = pm.getPackageInfo(packageName, flags);
        } catch (NameNotFoundException e) {
                return "";
        }
        Signature[] signatures = packageInfo.signatures;

        byte[] cert = signatures[0].toByteArray();

        InputStream input = new ByteArrayInputStream(cert);

        CertificateFactory cf = null;
        try {
                cf = CertificateFactory.getInstance("X509");


        } catch (CertificateException e) {
                return "";
        }
        X509Certificate c = null;
        try {
                c = (X509Certificate) cf.generateCertificate(input);
        } catch (CertificateException e) {
                return "";
        }


        try {
            MessageDigest md = MessageDigest.getInstance("SHA1");
            byte[] publicKey = md.digest(c.getPublicKey().getEncoded());


            StringBuffer hexString = new StringBuffer();
            for (int i=0;i<publicKey.length;i++) {
                String appendString = Integer.toHexString(0xFF & publicKey[i]);
                if(appendString.length()==1)hexString.append("0");
                hexString.append(appendString);
                }


            return hexString.toString();

        } catch (NoSuchAlgorithmException e1) {
            return "";
        } 
    }

我在您的方法中看到的问题是,任何人都可以确定包裹指纹或您的包裹并将其发送到您的网络服务。更好的可能性是使用质询-响应机制:您的 Web 服务向您发送一个唯一的会话令牌,您的应用程序使用共享算法对其进行加密或摘要,然后将此加密的令牌发送回您的服务进行验证。当然,您不会想将该算法发布到 github。

【讨论】:

  • 这个方法看起来很有帮助。但是,对于您提供的有关共享算法的信息-我不愿将任何“秘密”放在 apk 中,因为反编译并找出应用程序的几乎所有部分是如何编码的都是微不足道的
  • 这是真的,当然——你可以稍微混淆你的代码,但最终,没有安全的 java 之类的东西。但即使你使用钥匙或指纹,一旦它通过电线,这也是公平的游戏。
【解决方案2】:

您不能将 Web 服务限制为由特定密钥签名的 apk。

您的 apk 签名由 Android 操作系统验证,并且不会直接与设备连接的网络服务共享。即使您从密钥库中读取您的签名并将其与请求一起发送,攻击者也可以发送相同的签名(例如相同的字节流)而无需访问您的私钥。他只需要获取您签名的 apk,从密钥库中读取字节(或侦听合法请求)并破坏数据。

您需要签署单独的请求以获得一定程度的安全性。但是,如果您在发布版本中保留私钥(该密钥未在 gitHub 上分发),并使用该密钥签署请求,您就不安全,因为私钥是作为您的 apk 的一部分分发的,因此很容易被提取。

以任何方式,您的 API 都可能被其他 apk 访问。

但是,可能还有另一种方式来限制您的 API,例如使用许可证令牌等。在这种情况下,您可能不会关心用户是否自己构建 apk,只要他有有效的许可证令牌.如果许可证令牌被利用和分发,您可以对该许可证令牌上的大量流量做出反应,例如阻止其进一步请求。由于我不使用 Google Play,我不确定它们可以从您的服务器获得多远的验证,但也许 application licensing portal 是搜索合适令牌的良好起点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多