为什么KeyPairGenerator.genKeyPair()这么慢

时间:2015-04-03 09:33:33

标签: java openssl cryptography rsa key-generator

我有一些Java代码,当我运行函数KeyPairGenerator.genKayPair()时,它的工作时间为40秒或更长。怎么改变这种情况?如果我跑

openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout server.key -out cert.pem 
它的工作时间为3秒。慢代码:

KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
gen.initialize(4096, random);        
keyPair = gen.generateKeyPair();        
PublicKey pubk = keyPair.getPublic();
PrivateKey prvk = keyPair.getPrivate();

1 个答案:

答案 0 :(得分:4)

首先,尽管Java在业务逻辑方面肯定是快速的,但是在加密方面,优化的C代码(具有重要性的程序集)将会被淘汰出局。 Java将使用BigInteger来执行这些计算,而BigInteger - 据我所知 - 不包含原生优化的蒙哥马利乘数。脚本语言通常比Java差得多,除非它们调用本机代码。

Java还需要时间来优化字节代码。这意味着如果多次调用它会运行得更快。因此,您需要至少调用一个密钥来查看如果在您的应用程序中多次调用此类方法会发生什么。在这种情况下,运行时可能非常高,以至于它已经能够进行优化 - 这取决于VM。

RSA密钥生成主要取决于找到两个大质数。寻找大质数是一个非常耗费CPU的过程。它还取决于随机数生成器来创建起点。所以使用的实际随机数生成器实现会产生很大的不同 - 尤其是如果随机数生成器可以阻塞,如果没有足够的熵可用。因此,请使用随机数生成器,直到找到足够快速且安全的生成器。

找到一定长度的素数是一个没有指定运行时间的过程。拾取一个非常大的数字(在这种情况下大小约为2048位)并开始测试后续数字是否为素数。这是锤击你的CPU的原因。因此,您需要计算生成素数的平均值运行时间 - 如果您生成了大量素数 - 或者您将不得不忍受所需时间的不确定性。


尽管如此,这有点无聊。一般而言,您不需要大量的RSA密钥 - 每个用户生成一到三个密钥。所以这只会成为一个问题,1)你有很多用户2)你有一个需要很多密钥对的协议或3)你需要非常大的RSA密钥。

如果您希望更快地生成密钥对,可以执行以下操作:

  1. 获取为您执行此操作的Java Provider的本机实现;
  2. 切换到另一种快速生成密钥对的算法,例如Elliptic Curve Cryptography;
  3. 使用openssl生成密钥,只需在Java应用程序中导入/使用它们;
  4. 通常你需要修复协议而不是密钥对生成器。