如何验证发送POST请求的应用程序的身份

时间:2019-02-11 11:02:50

标签: java android http reverse-engineering signature

我正在制作一个服务器API,它将向我的应用返回一些机密密钥。

然后,应用将使用这些键执行特定的操作。我将通过SSL发送密钥,以便任何“中间人”攻击都无法读取它们。

首先,我将首先输入Package名称,然后再验证一下可以确保我的应用程序尚未反编译和重新编译且该软件包不是伪造的东西。

基本上我想避免这些问题:

1)某人未创建伪造的软件包名称,然后发送请求 2)有人没有重新编译我的应用程序,然后发送请求 3)如果没有通过MIM跟踪服务器的响应的人

到目前为止,我认为最好的方法是使用HASH密钥,然后在服务器中对其进行比较,以查看POST密钥是否与服务器中存储的密钥相同。

但是我找不到与该应用的签名密钥相关的密钥,任何拥有我的应用APK的人都无法访问该密钥。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

如果您使用Android NDK库中可用的C ++代码在应用中创建密钥,则可以添加额外的保护层。这是一个了不起的tutorial。基本上,这可以防止您的应用受到反编译工具的攻击,反编译工具通常会反编译Java文件。另外,建议您在通过SSL服务器的发布请求发送密钥之前,在密钥上添加AES encryption

在您的onCreate()方法上,从本机C ++实现中获取密钥:

String nativeKey = invokeNativeFunction()

然后将其加密:

byte[] keyStart = nativeKey.getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();    

// encrypt
byte[] encryptedData = encrypt(key,b);

加密方法:

private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(clear);
    return encrypted;
}

编辑CSRF

这里有一个有趣的答案:Authenticity_token in Rails + Android,也在Wikipedia上,对于如何应对跨站点请求伪造也有很多建议。其中包括:

Synchronizer token pattern
Cookie-to-header token

仅举几例。

这里还有一层额外的安全性,可以识别authenticity of the app request