1

我有一个休息服务器,我只希望我的应用程序能够与我的 REST 服务器通信。即,如果有人将 url 放在浏览器中,他们将无法与我的服务器通信

目前我正在考虑在我的请求调用中添加我的密钥哈希作为额外参数,然后存储密钥

哈希不存储在我的应用程序中,而是使用以下方法自动检索。

public static void getHashes(Activity act) {
    PackageInfo info;
    try {
        info = act.getPackageManager().getPackageInfo("com.my.package.myapp", PackageManager.GET_SIGNATURES);
        for (Signature signature : info.signatures) {
            MessageDigest md;
            md = MessageDigest.getInstance("SHA");
            md.update(signature.toByteArray());
            String something = new String(Base64.encode(md.digest(), 0));
            //String something = new String(Base64.encodeBytes(md.digest()));
            Log.i("hash key", something);
        }
    } catch (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());
    }
}

例如,我将在某个时间只调用一次此方法,以便在编译到生产 apk 后我可以在 logcat 上看到它并将其保存到我的服务器。这意味着它不会再次输出给其他人看到。

我会将此密钥存储在我的服务器上,并且我的应用程序将在每次发出请求时发送此密钥。如果密钥不同,那么我的服务器将不会响应。

这种方法安全吗?谁能看出其中的缺陷?

4

2 回答 2

0

不,它不安全。

攻击者可以观察到在请求中发送的此哈希的单个实例,然后将其包含在他们自己的请求中,您的服务器将无法区分。例如,哈希可以由第一个获得它的人在网络上发布。

但是,这不仅仅是您的方法的问题:对于一般问题没有已知的安全解决方案,请参阅此答案以获得更全面的讨论(在 WCF 而不是 Android 的上下文中,但论点是相同的)。

于 2013-09-02T20:36:15.143 回答
0

不,您需要先向服务器询问质询,然后返回应用程序密钥的哈希值、该质询、消息本身的内容(签名除外)以及一些在应用程序和服务器上都已知的随机字节数组边。如果这样做,应该不受网络嗅探、重放攻击以及尝试使用合法应用程序作为消息模板生成器的影响(有效的身份验证,其他内容可能被替换)。您也可以以相同的方式对服务器端进行身份验证。

不幸的是,在 .apk 文件落入攻击者手中后,您的应用程序的逆向工程几乎无能为力。然而,谷歌和亚马逊应用商店提供了一些保护,防止获取 .apk 进行反汇编。

于 2017-07-03T08:28:28.663 回答