使用Jsch生成4096位RSA密钥比2048位慢

时间:2014-12-31 01:21:29

标签: java performance rsa jsch

我需要为客户端/服务器应用程序创建公共和私有RSA密钥,我正在使用JSch library来执行此操作。到目前为止,我一直在生成4096位密钥,因为我希望尽可能提供最好的安全性。但是,这需要3~5分钟,而生成2048位密钥则需要10秒钟。有一个sscce:

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.KeyPair;

public class KeyGenerator {

    public static void main(String[] args) {
        JSch jsch = new JSch();

        System.out.println("Starting...");

        try {
            KeyPair keyPair = KeyPair.genKeyPair(jsch, KeyPair.RSA, 4096);
        }
        catch (JSchException e) {
            e.printStackTrace();
        }

        System.out.println("Done.");
    }
}

预计这一代发生时间会有多大差异吗?我不是很清楚如何生成RSA密钥(因此使用库),但我想所需的时间可能是指数级的?它似乎......太指数了。

这是JSch API(因为图书馆本身及其来自的网站旁边没有文档)。

更新:我做了一些分析。这是keygen时间图表,从512位开始,最高可达4096,每个密钥大小有30个样本。

Chart of JSch key generation times. 30 samples each for 512, 1024, 2048, and 4096-bit keys.

这是一个类似的图表,排除了4096位试验(同一数据集):

Chart of JSch key generation times without 4096-bit key data.

这些看起来非常相似,表示时间上相当平滑的指数增长。我想我只是不耐烦了!

3 个答案:

答案 0 :(得分:10)

生成RSA密钥需要找到两个满足特定条件的大型随机素数。找到这样的素数基本上是挑选随机数,然后通过执行某些测试来检查它们是否是素数。 Prime Number Theorem告诉我们,随着素数越来越大,它们也越来越少,所以你必须生成更多的随机数才能找到一个素数。确定数字是否为素数的检查对于更大的数字也需要更长的时间。

所有上述因素都会导致生成更大的密钥所需的时间增加,但除此之外,听起来这个库并不是特别快。在相当现代的PC上使用OpenSSL,我可以在约1秒内生成2048位密钥,在10秒内生成4096位密钥,因此10秒和3-5分钟的时间似乎过多。如果性能是一个问题,我建议尝试一个不同的库,理解比任何库生成大密钥要比较小的密钥慢!

答案 1 :(得分:3)

答案有点迟,但由于其他答案纯粹是启发式的,所以这里有一些关于为什么需要这么长时间的背景:

RSA密钥生成的最慢部分通常是Fermat测试,必须为每个主要候选x运行,并且包括检查2 ^ {x-1} = 1模x(使用2可以更快)而不是使用其他基地)。那么Fermat测试所需的时间如何取决于x的位长?

  1. 乘法的运行时间大约是因子的位长度的二次方,所以长度加倍使时间增加四倍(学校乘法的倍数;如果你使用Karatsuba,那么其大约三倍时间;对于更复杂的乘法方法,RSA的比特长度太短。)

  2. 模幂运算的运行时间在指数的位长度上是线性的。

  3. 随机n位数为素数的概率为1:log(2 ^ n),其中log是自然对数,即,它是1:(n * log(2))。

  4. 因此,对于RSA密钥生成的运行时间而言,比特长度加倍可以得到(1)的因子4和(2)和(3)的2倍因子,因此总的运行时间为费马测试增加了16倍(或使用Karatsuba时增加了12倍)。

    由于密钥生成的其他部分的运行时间不会那么快,因此约为10 as indicated in the answer of by Iridium的因素是合理的。

答案 2 :(得分:0)

生成4096位长密钥比2048位密钥花费的时间要多得多,请参阅基准数here