Android:如何以编程方式获取SHA1 / MD5指纹?

Nic*_*ico 1 verification android backend oauth

我正在尝试实现一种与后端服务器进行通信的方法,并确保后端是仅在我的应用程序正在调用时才应答。

所以我的想法是,我只发送带有HTTPS POST请求的SHA1 / MD5指纹,并在后端服务器上对其进行验证。如果指纹匹配,则服务器将应答。

所以我的第一个问题是:如何在运行时以编程方式获取这些内容?可能吗?

第二个问题是:会那么容易吗?还是我真的必须设置OAuth服务器(或使用google-api)?...问题是,我认为OAuth对于我的用例来说有点过头了,我不想处理过期/刷新令牌的内容。

Art*_*hev 14

我补充了 Zulqumain Jutt 提出的解决方案,以便能够以常见形式获得结果,例如:

KeyHelper:MD5 56:ff:2f:1f:55:fa:79:3b:2c:ba:c9:7d:e3:b1:d2:af

public class KeyHelper {

    /**
     * @param key string like: SHA1, SHA256, MD5.
     */
    @SuppressLint("PackageManagerGetSignatures") // test purpose
    static void get(Context context, String key) {
        try {
            final PackageInfo info = context.getPackageManager()
                    .getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_SIGNATURES);

            for (Signature signature : info.signatures) {
                final MessageDigest md = MessageDigest.getInstance(key);
                md.update(signature.toByteArray());

                final byte[] digest = md.digest();
                final StringBuilder toRet = new StringBuilder();
                for (int i = 0; i < digest.length; i++) {
                    if (i != 0) toRet.append(":");
                    int b = digest[i] & 0xff;
                    String hex = Integer.toHexString(b);
                    if (hex.length() == 1) toRet.append("0");
                    toRet.append(hex);
                }

                Log.e(KeyHelper.class.getSimpleName(), key + " " + toRet.toString());
            }
        } catch (PackageManager.NameNotFoundException e1) {
            Log.e("name not found", e1.toString());
        } catch (NoSuchAlgorithmException e) {
            Log.e("no such an algorithm", e.toString());
        } catch (Exception e) {
            Log.e("exception", e.toString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Gop*_*rvi 6

Artur 示例密钥字符串的Kotlin 版本:“SHA1”或“SHA256”或“MD5”。

fun getSig(context: Context, key: String) {
            try {
                val info = context.packageManager.getPackageInfo(
                    BuildConfig.APPLICATION_ID,
                    PackageManager.GET_SIGNATURES
                )
                for (signature in info.signatures) {
                    val md = MessageDigest.getInstance(key)
                    md.update(signature.toByteArray())
                    val digest = md.digest()
                    val toRet = StringBuilder()
                    for (i in digest.indices) {
                        if (i != 0) toRet.append(":")
                        val b = digest[i].toInt() and 0xff
                        val hex = Integer.toHexString(b)
                        if (hex.length == 1) toRet.append("0")
                        toRet.append(hex)
                    }
                    val s = toRet.toString()
                    Log.e("sig", s)
                    
                }
            } catch (e1: PackageManager.NameNotFoundException) {
                Log.e("name not found", e1.toString())
            } catch (e: NoSuchAlgorithmException) {
                Log.e("no such an algorithm", e.toString())
            } catch (e: Exception) {
                Log.e("exception", e.toString())
            }
}
Run Code Online (Sandbox Code Playgroud)


Gab*_*han 5

你试图做的事情是不可能的。您作为 id 发送到服务器的任何内容都可以被另一个应用程序复制。这就是为什么您的用户的密码不在应用程序中的原因 - 来自外部来源的密码是确保请求有效的唯一方法。这只能证明用户是有效的,而不是来自您的应用程序。

  • 从数学上讲,无法仅根据外部代理提供给您的信息来证明外部代理的身份。其他任何人都可以通过获取您的应用程序的 sha 指纹并使用它来谎称他们的 sha 指纹是什么。 (4认同)
  • @GabeSechan 要获取 SHA-1 指纹并在后端注册,您需要用于对应用程序进行签名的密钥库文件、密钥库密码以及别名/密码的组合。如果攻击者设法窃取您的密钥库,您可能会遇到更大的问题,就像从服务器窃取私有证书一样。我并不是说这是最终的身份验证协议,但在我看来它非常安全,这就是 GCP 使用它的原因。 (2认同)
  • @GabeSechan 如果这像你说的那么容易,为什么没有大量报告谈论使用 GCP 的大型应用程序的 API 配额泄漏?如果窃取 API 配额如此容易,那么没有人会使用 GCP,如果是这样的话,为什么 Google 选择这种身份验证方法呢? (2认同)

Zul*_*utt 5

您可以生成以下示例中的内容:

private void getKeyHash(String hashStretagy) {
        PackageInfo info;
        try {
            info = getPackageManager().getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_SIGNATURES);
            for (Signature signature : info.signatures) {
                MessageDigest md;
                md = MessageDigest.getInstance(hashStretagy);
                md.update(signature.toByteArray());
                String something = new String(Base64.encode(md.digest(), 0));
                Log.e("KeyHash  -->>>>>>>>>>>>" , something);

               // Notification.registerGCM(this);
            }
        } catch (PackageManager.NameNotFoundException e1) {
            Log.e("name not found" , e1.toString());
        } catch (NoSuchAlgorithmException e) {
            Log.e("no such an algorithm" , e.toString());
        } catch (Exception e) {
            Log.e("exception" , e.toString());
        }
    }
Run Code Online (Sandbox Code Playgroud)

使用像这样:

getKeyHash("SHA");
getKeyHash("MD5");
Run Code Online (Sandbox Code Playgroud)

第一个答案:您可以使用上述方法安全且独特,我一直在使用它。

第二个答案:您可以使用Auth密钥,但这完全取决于您,您是否满意