【问题标题】:How to store RSA Private Key into app given by backend? [closed]如何将 RSA 私钥存储到后端提供的应用程序中? [关闭]
【发布时间】:2018-02-16 04:57:46
【问题描述】:

我正在开发一个 Android 应用程序,我必须在其中使用有效负载加密。对于这个后端,给我一个预先生成的密钥对(RSA 公钥和私钥)用于加密和解密。

到目前为止,我将这 2 个密钥(RSA 公钥和私钥)保存在硬编码的字符串中,但每个人都知道这样做并不安全。

所以在这个过程中,客户端将使用服务器的公钥加密发送请求,服务器将使用自己的私钥解密。并且响应只能由客户端的私钥解密,因为它是由客户端的公钥加密的。

注意 - RSA 公钥和私钥对于我的应用来说是静态的,我想将其放在安全的地方进行管理。

所以主要的问题是我应该把那个私钥放在我的应用程序的什么地方。密钥在我的应用程序中是静态的,因为服务器人员将其分发给移动团队。而且我们不能使用我们自己生成的私钥。

那么,第一次在客户端提供私钥的最佳方式是什么。

我厌倦了this 链接和this,但没有一个适合我。

编码愉快 :-)

【问题讨论】:

  • 不应传输私钥。这有暴露他们的风险,因此他们不再是私人的。
  • @GurV,实际上我们希望通过传输密钥来保证安全,因为密钥传输本身并不安全。
  • @Code-Apprentice,实际上密钥不是由服务器传输的,最初是服务器给我们(客户端),然后我们将它们保持为硬编码。
  • “最初服务器给我们(客户端)”是什么意思?这是如何实现的?
  • 是的@Code-Apprentice,服务器给我们密钥对并告诉我们保留这些密钥,您只能使用这些密钥进行加密或解密。

标签: java android encryption android-keystore


【解决方案1】:

应用程序应生成自己的密钥,然后将公钥传输到后端。然后后端可以加密数据以发送到应用程序。如果需要反方向加密,后端也可以生成密钥,并将其公钥传输给应用进行加密。

【讨论】:

  • 你是对的,非常好,最好的答案!!
  • @SahdevRajput74 这就是为 =p 点赞的原因
  • @Code-Apprentice,我同意你的方法,但问题是我们的方法略有不同 - 克林特使用服务器的公钥加密数据,服务器使用他们的私钥解密,服务器加密数据使用客户端的公钥,客户端使用自己的私钥解密,我们(客户端和服务器)不共享他们的公钥或私钥,只是将它们硬编码。
  • @BajrangHudda 这听起来与我建议的方法相同。
  • 代码学徒说的和你说的一样..
【解决方案2】:

您可能应该将服务器方法更改为public key exchange 并在android 设备上单独生成密钥。这样会很安全。

您必须将带有证书的私钥存储在KeyStore 中。以下是实现此目的的步骤:

步骤 1. 解码 Base64 PKCS#8 以获得 PrivateKey 的实例:

PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = kf.generatePrivate(ks);

第 2 步。这种情况可能是您的服务器发送带有私钥的证书,或者 PKCS#8 blob 也包含公钥。

步骤 3. 如果服务器不发送证书,您需要为私钥生成证书。 Here 是使用 BouncyCastle 的示例。

第 4 步。 在 KeyStore 上存储密钥:

X509Certificate certificate = ... // get certificate for private key or generate
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
keystore.setKeyEntry("MyAlias", privateKey, null, new Certificate[] { certificate });

如果您确实必须将私钥从服务器传输到设备,则可能会有以下更安全的情况:

  1. 在设备上生成 AES 密钥。
  2. 首先获取服务器的公钥。
  3. 使用该公钥封装生成的 AES 密钥。
  4. 将加密的 AES 密钥传输到服务器。
  5. 使用私钥在服务器端解密加密的 AES 密钥。
  6. 使用 AES 密钥加密私钥,并将其传输到设备。

问题已更新,因此更新了答案:

如果您必须在应用程序中保留公钥私钥对,我建议您使用 Android NDK 保留密钥字节,并对其进行强烈混淆。

但是,如果我是你,由于混淆工具对于强大的 Android C++ 代码加密来说很昂贵,我会将这些静态密钥保留在服务器端,而不是在应用程序中硬编码。然后我会使用我在使用对称加密之前提到的步骤将静态密钥发送到设备。

但是,如果您选择使用 NDK 选项,它也比将密钥存储在文件或 Java 代码中要好,但并非完全防弹。一旦用户打开应用程序,您就可以将从 C++ 代码中检索到的密钥存储在 KeyStore 中,因此,您可以确保它是安全的。

因此,如果您想使用最快的选项来保证应用程序二进制文件中的私钥安全,请选择 NDK 选项,以后您可以对其进行混淆处理。如果你有时间做一些服务器端的安排来传输私钥,然后存储在 keystore 上,然后去我写的步骤。

这里有一些资源可能会对您的 NDK 有所帮助:

https://androidsecurity.info/2016/12/15/storing-your-secure-information-in-the-ndk/

https://medium.com/@abhi007tyagi/storing-api-keys-using-android-ndk-6abb0adcadad/

【讨论】:

  • 我将如何获得 privateKeyBytes?同样,我必须在我的代码中保持硬编码。虽然传输 privateKeyBytes 当然不是一个好的解决方案。
  • @BajrangHudda 如果您要从服务器传输 Base64 编码的私钥,您可以在您的应用程序中对其进行解码。所以,你得到了私钥字节。
  • 另外,您已经注意到密钥对将由后端在单独的文件中提供,我只能在我的应用程序中使用这些密钥,但要在安全的地方使用。因此,您可以从已传输的文件中获取您的私钥字节。
  • 更安全的情况可能是,您在移动设备上生成 AES(或任何对称)密钥,然后获得服务器的公钥。之后,您可以使用服务器的公钥包装您的 AES 密钥。然后,当您将加密的 AES 密钥发布到服务器时,您可以使用该 AES 密钥加密私钥,并在设备上对其进行解密。
  • 我已经更新了我的答案,其中包含如何使用 AES 密钥传输私钥的步骤。
猜你喜欢
  • 1970-01-01
  • 2017-12-23
  • 2013-12-04
  • 2010-11-14
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 2015-01-30
  • 2014-05-27
相关资源
最近更新 更多