首页 > 解决方案 > 如果在线程休眠之前,RSA 解密需要更长的时间

问题描述

我的主要担忧来自:我有一个 spring boot 应用程序 A,它使用 rest 模板调用另一个 spring boot 应用程序 B。B 的响应包含需要解密的加密字段。

为了解密它,一个 RSA 私钥被加载到应用程序 A 中一次。

解密代码如下所示:

Cipher rsaCipher2 = 
Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher2.init(Cipher.DECRYPT_MODE, Test.privateKey);
rsaCipher2.update(encryptMessage);
byte[] decryptedMessage = rsaCipher2.doFinal();

如果我一个接一个地提交多个请求,我看到响应是应用程序 A 在不同时间处理的,并且每次运行解密(仅上面那 4 行)需要不同的时间,从 5 毫秒到 20 毫秒,即使相同的测试,使用相同的数据,执行。这是正常的吗?我本来希望有更多相似的持续时间。

关于如何将解密时间保持在最低限度的任何想法?我尝试了一个密码池,但效果不佳。

为了查看我是否可以在应用程序之外复制行为,我执行了以下操作:

我使用 RSA 算法生成了一对密钥,我加密了一个字符串。我在一个主方法中,在一个线程上,一个接一个地多次运行解密,平均在5 毫秒内完成一次解密

如果我做同样的事情,但在解密前添加 100 毫秒的超时,则解密平均在20 毫秒内完成。(如果你问我在计算平均值时没有考虑超时)。

有人可以说明为什么会发生这种情况,我该如何避免它。我尝试在 for 语句之前初始化密码,但我没有看到任何改进,我尝试在单独的线程上运行解密并看到了轻微的改进,但与原始结果相去甚远。

使用 RSA 生成一对密钥

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);the same thing, but add a timeout of 100ms before the decryption, the decryption is made on average in 20 ms. (in case you ask i did not take the timeou
KeyPair keyPair = keyGen.genKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

编码一个随机字符串

Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
rsaCipher.update("randomString".getBytes());
encryptMessage = rsaCipher.doFinal();

运行 decript 1000 次

for (int i  =  0 ; i < 1000 ; i++ ) {
  //Thread.sleep(100);
    Long time =  System.currentTimeMillis();    
    Cipher rsaCipher2 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    rsaCipher2.init(Cipher.DECRYPT_MODE, privateKey);
    rsaCipher2.update(encryptMessage);
    byte[] decryptedMessage = rsaCipher2.doFinal();
    System.out.println((System.currentTimeMillis() - time)   + " ms ");
}

以防有人问我的熵:

cat /proc/sys/kernel/random/entropy_avail
3795

标签: javaencryptionrsa

解决方案


首先你需要正确测试:如何在 Java 中编写正确的微基准测试?

如果适当的基准测试显示类似的结果,则可能是由于睡眠导致上下文切换、缓存刷新以及 CPU 较低级别上发生的各种其他事情。睡眠造成的不仅仅是延迟。

这就是为什么我们不在代码中放置随机睡眠的原因。


推荐阅读