安全地存储客户端机密

Posted

技术标签:

【中文标题】安全地存储客户端机密【英文标题】:Store client secret securely 【发布时间】:2015-04-20 23:36:30 【问题描述】:

我知道public client shouldn't use a client secret,因为无论你如何混淆它,它都不会受到reverse engineering 的保护。

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

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

我对安全性了解不多,所以不知道能不能解决这个问题,或者android(min sdk 15)是否为这种场景提供了任何机制。

有什么想法吗?

【问题讨论】:

Best Practice for storing private API keys in Android的可能重复 OAuth secrets in mobile apps的可能重复 【参考方案1】:

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

    以明文形式存储

    使用对称密钥加密存储

    使用 Android 密钥库

    使用非对称密钥加密存储

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

【讨论】:

【参考方案2】:

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

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

干杯

【讨论】:

不能反编译并不意味着不能检查:本机代码可以被反汇编成接近编译器生成的汇编指令。它比高级代码更难阅读,但它仍然是代码。【参考方案3】:

正如您所说,无论您做什么,您如何尝试隐藏您的密钥,您都无​​法 100% 隐藏它。 但是,如果你想让逆向工程师的工作更加努力;

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

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

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

【讨论】:

这一定是最糟糕的建议了。 其实这个建议还不错。虽然秘密应该在应用程序和主网关之间,而不是在其他服务之间。不过,我不想过多更改答案,所以我会单独发布一个。 @Johny19 为什么你认为这很糟糕?【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

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

    服务器生成一个特定于客户端登录的密钥对。 发送服务器的公钥以进行特定于客户端登录的加密 该应用会为自己的目的生成一个密钥对 应用程序将发送使用服务器公钥加密的公钥 服务器将验证公钥是否已使用其公钥签名。

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

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

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

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

【讨论】:

以上是关于安全地存储客户端机密的主要内容,如果未能解决你的问题,请参考以下文章

谷歌云存储 - 客户端机密

在哪里/如何存储或生成客户端机密?

在 App Engine 上的 Django 应用上存储客户端机密

如何在数据库中存储加密的机密用户信息,需要在运行时解密?

如何在 CI 管道中存储多个客户端的机密文件?

确保机密数据免受Nuget包的侵害