【问题标题】:Deterministic generation of RSA encryption key pairsRSA加密密钥对的确定性生成
【发布时间】:2012-04-16 01:54:01
【问题描述】:

我正在尝试在 Android 上使用 Java 确定性地生成 RSA 密钥对。我的要求是我无法存储密钥对,并且必须在运行时生成它以等效于任何以前/未来的运行。

我的过程是,我会确定地播种一个随机数生成器并将该生成器传递给创建密钥。我的代码是:

SecureRandom random=SecureRandom.getInstance("SHA1PRNG");
random.setSeed(1234);   //something device specific will be used to set this
KeyPairGenerator keyGen=KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024, random);

KeyPair pair=keyGen.generateKeyPair();
PublicKey pub=pair.getPublic();
PrivateKey priv=pair.getPrivate();

生成的密钥因运行而异。但是,SecureRandom 数字在每次运行时都是相同的,甚至在不同设备之间也是相同的。

我错过了什么?我怎样才能重复生成这些密钥?

谢谢

【问题讨论】:

  • 为什么要这样做?当然,如果您不想存储 RSA 密钥对,那么您也不想存储用于生成 RSA 对的随机种子?奇怪的是,这段代码并没有按照你的意愿去做,但在我看来,你可能会在没有经过深思熟虑的情况下这样做

标签: java android rsa


【解决方案1】:

你想做什么?即使这样可行,此代码也将依赖于 Android 上的 SHA1PRNG 实现的一个怪癖,因此它可能随时中断。通常,setSeed() 会添加熵,因此即使您使用相同的种子播种 SecureRandom,您也不能保证您将获得相同的数字。如果您在桌面 Java 上尝试此代码,它很可能会失败。到目前为止,它适用于大多数(所有?)当前的 Android 版本,但这不能保证。

如果您需要可预测的密钥,您可能需要为每台设备提供预生成的密钥。如果您需要安全地存储它们,请在 ICS 上使用 KeyChain API,或在 ICS 之前的设备上使用受密码保护的密钥库。即使您不存储实际密钥,如果有人知道密钥是如何生成的(种子),他们也可以生成相同的密钥,并且您的密钥与种子一样安全。如果它是特定于设备的,那么可能并不难找到。

至于为什么这不起作用,RSA密钥生成器基本上在循环中生成随机BigIntegers,测试素数。素数测试是概率性的,因此您可能会在每次运行时选择不同的素数。您可能想要获得SpongyCastle,在模拟器上运行它并在RSAKeyPairGenerator.java 中设置断点以检查到底发生了什么。

【讨论】:

  • 感谢您详细解释密钥生成器的工作原理和 SpongyCastle 实现。这都是(被误导的)尽量减少应用内购买盗版内容的一部分。我希望我可以加密服务器上的内容并将其交付给客户端,而无需密钥交换,并即时解密内容。我必须在服务器上生成密钥对,将私钥传输到客户端,然后按照您的建议使用 KeyStore,并使用一些算法生成的密码来增加难度。
  • 我明白了(有点)。您正在尝试实施某种 DRM。 RSA 可能不适合这个。如果您将密钥传输给客户端,您自然需要确保安全地进行,这可能并不容易。想法是将一些设备特定位(IMEI 等)放在 IAB developerPayload 中,并在您验证服务器上的签名时获取它。然后使用它生成一个对称 (AES) 密钥,绑定到该特定设备,加密内容并将其发送到设备。然后设备生成相同的对称密钥,并对内容进行解密。
  • 当然,您可能希望对 IMEI 等进行哈希处理,这样您就不会收集实际的设备识别信息。
  • 使用 AES 的优点,使用 PBKDF 或类似方法从相同的哈希中派生相同的密钥应该很容易。再次感谢。
  • 确定性生成密钥对帮助我们存储种子并每次生成钱包密钥。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 1970-01-01
  • 2011-01-07
相关资源
最近更新 更多