我正在尝试使用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数字在运行之间是相同的,甚至在设备之间也是如此。
我错过了什么?我怎样才能重复生成这些密钥?
由于
答案 0 :(得分:8)
你想做什么?即使这样可行,这段代码依赖于Android上的SHA1PRNG实现的怪癖,因此它可能随时中断。通常,setSeed()
会增加熵,因此即使您使用相同的种子为SecureRandom
播种,也无法保证获得相同的数字。如果您在桌面Java上尝试此代码,它很可能会失败。到目前为止它适用于大多数(所有?)当前的Android版本,但这不能保证。
如果您需要可预测的密钥,则可能需要为每个设备配置预先生成的密钥。如果您需要安全地存储它们,请使用ICS上的KeyChain
API或pre-ICS设备上的密码短语保护密钥库。即使您不存储实际密钥,如果有人知道如何生成密钥(种子),他们也可以生成相同的密钥,并且您的密钥只能与种子一样安全。如果它是特定于设备的,那么很可能找不到它。
至于为什么这不起作用,RSA密钥生成器基本上在循环中生成随机BigIntegers
,测试素数。主要测试是概率性的,因此您可能会在每次运行时选择不同的素数。您可能希望得到SpongyCastle,在模拟器上运行此命令并在RSAKeyPairGenerator.java
中设置断点以检查究竟发生了什么。