安全地存储客户机密

Store client secret securely

我知道 public client shouldn't use a client secret because, no matter how much you obfuscate it, it won't be protected from reverse engineering.

但是,我正在验证的服务的负责人不希望to/can不更改它。因此,我需要存储客户端机密并尽可能保护它免受逆向工程。

所以,我想到了在构建时使用 gradle 加密它并将其存储在一个文件中。然后,当我在 运行 需要它时,我会解密它。但现在我必须解决如何存储加密密钥的问题...

我不太了解安全性,所以,我不知道这是否可以解决,或者 Android (min sdk 15) 是否为这种情况提供任何机制。

有什么想法吗?

正如你所说,无论你做什么,你多么想隐藏你的密钥,你都不可能 100% 隐藏它。 但是,如果你想让逆向工程师的工作更难;

首先混淆你的客户(我想你已经这样做了)。

其次,不要把你的密钥硬编码到客户端。登录或用户打开应用程序后收到密钥。并通过 SSL 将密钥传递给客户端。将秘密存储为字节数组,不要将其保存到客户端中。存入内存即可。

这些步骤并不能保证密钥的安全,反而使逆向工程师的工作变得非常困难。

您也可以尝试Dexguard混淆和加密数据。 Dexguard 是由开发 proguard 的同一个人制作的。

This article 建议这些选项,从不太安全到更安全:

  1. 以明文形式存储

  2. 使用对称密钥加密存储

  3. 使用 Android 密钥库

  4. 使用非对称密钥加密存储

可能,结合使用#4 和某种方式来明确识别设备会足够安全

也许最好的选择是使用 NDK 因为它不能被反编译,就像 Godfrey Nolan 点 here

这是我发现有用的资源,可以帮助我实现它link to the resource

干杯

@Semih 的回答是正确的。密钥部分是需要扩展的部分。

  1. 密钥在应用程序和网关服务器之间,而不是底层服务。
  2. 网关服务器负责将该密钥转换为特定于服务的内容。

登录过程完成后使用以下内容构建密钥

  1. 服务器生成客户端登录专用的密钥对。
  2. 发送服务器的 public 密钥用于客户端登录专用的加密
  3. 应用程序会为自己的目的生成密钥对
  4. 应用程序将发送使用服务器的 public 密钥加密的 public 密钥
  5. 服务器将验证 public 密钥是否使用其 public 密钥签名。

任何未来的请求都将涉及以下内容

所有从客户端发送到服务器的数据都将使用 JWT 加密,消息将由应用程序的私钥签名并使用服务器的 public 密钥加密。

问题是确保#1 任何人都可以登录并启动流程,那么您将如何防止这种情况发生?我能想到的唯一方法是对登录进行验证码检查。

该解决方案将客户端机密的存储推送到服务器而不是应用程序本身,并使用应用程序的凭据保护它。