【问题标题】:Is using the BigInteger probablePrime function safe for RSA encryption?使用 BigInteger probablePrime 函数对 RSA 加密安全吗?
【发布时间】:2015-04-11 23:40:38
【问题描述】:

我编写了一个代码,它能够生成 2048 位素数 p & q,并使用它来加密 RSA 中的消息。我生成这些数字的方法是使用 java.math.BigInteger 包的 probablePrime() 函数。我的问题是这些函数生成的素数在加密方面的加密强度如何。

这是我生成这些数字的代码,isPrime 只是我编写的一个布尔函数,用于检查数字是否为素数。

BigInteger definitePrime(int bits, Random rnd) {
  BigInteger prime = new BigInteger("4");
  while (!isPrime (prime)) {
    prime = BigInteger.probablePrime(bits, rnd);
  }
  return prime;
}

【问题讨论】:

  • 我并不是要怀疑你的编程能力,但你是说你写了一个可以有效测试BigInteger.probablePrime(2048, new Random())返回的值是否为素数的方法?
  • 你应该在这里使用 do/while 循环,以避免初始化和冗余的第一次测试。
  • 是的,它是一个从 i = 2 开始运行的 for 循环,只要 i 小于数字的平方根,它就会一直持续下去。然后它采用数字 mod i,如果值为零,则返回 false。如果它在没有 num%i 导致为零的情况下通过循环,则返回 true。这是检查数字是否为素数的一种非常有效的方法。

标签: java encryption rsa biginteger


【解决方案1】:

正如 Stephen C 在 his answer 中指出的那样,对于 RSA 加密来说,素数可能还可以。

加密随机性

我要补充一点,您实际上不应该使用任何 Random 实例,而应该只使用您的系统最好的 SecureRandom 实现。

new Random() 不是加密随机源,而new SecureRandom() 应该是。如果用于生成素数的随机数在密码学上不安全,那么攻击者可能有机会根据其他信息(例如时间或弱随机源的先前输出)简单地重新创建这些随机数。

没有教科书 RSA

您自己在做“所有事情”,而且您似乎真的想用它来进行严肃的加密。如果你是,你错过了一些关键的东西,那就是填充方案。

使用BigInteger 方法很容易实现RSA 以使其正常工作,但不足以使其安全。您需要使用 PKCS#1 v1.5(不再推荐)或 PKCS#1 v2 OAEP(推荐)等填充方案。

使用现有实现

不要为您的“手工”RSA 实现这些填充方案,而是使用 Java 的 Cipher instance,它为 RSA 提供了这些填充方案:

  • RSA/ECB/PKCS1Padding
  • RSA/ECB/OAEPWithSHA-256AndMGF1Padding

【讨论】:

  • 我这样做只是为了好玩。不过,我要感谢您的意见,我一定会研究填充方案。
  • 如果您的输入和输出是不需要转换为字节和字符串的大整数,您真的需要填充吗?在这种情况下要填充什么?
  • @OlegGryb 填充仅用于安全性。如果您不关心安全性并且安全性和混淆的混合对您来说就足够了,那么您可以跳过填充。由于填充通常以二进制形式应用,因此您必须将输入转换为字节,然后添加填充(希望是 OAEP),将其转换回 BigInteger 并作为 Textbook RSA 执行其余步骤。我建议不要自己实施 RSA 或一些 RSA 填充。也许您正在向旁道攻击或简单的密码分析开放实现。
  • @Artjom B. 你没有阅读我的 qs。输入已经是一个大整数。在这种情况下,您要填充什么以及如何填充?还有一个重要的细节——它小于钥匙的大小。
  • @Artjom B. 任何事情都没有 100%。即使使用语义上优于 PKCSv1.5 的 OAEP,您是否会说 OAEP/SHA1(更不用说 PKCSv1.5)不安全,每个人都应该使用 OAEP/SHA256?说某事是安全的或不安全的并不能说明什么。很高兴看到破解 RSA、RSA/PKCS1.5、RSA/OAEP/SHA1 和 RSA/OAEP/SHA256 需要多少次暴力破解尝试。对于 AES 128 或 256,我已经看到了这些数字。如果您有任何 RSA,请分享。安全是一个比较的东西。
【解决方案2】:

javadocBigInteger.probablePrime() 表示:

返回一个可能是素数的正 BigInteger,具有指定的 bitLength。此方法返回的 BigInteger 是复合的概率不超过 2-100

2-100 表示 1,267,650,600,228,229,401,496,703,205,376 中的一次机会;即 ~1.267 * 1030

中的 1 次机会

由于您尝试生成 2 个素数,这意味着您在大约 1030 中有 2 次机会生成弱 RSA 密钥对。

我认为这已经足够了,但如果您不这么认为,那么您可以使用 BigInteger.isProbablePrime(certainty) 来测试您的主要候选人,以获得更高的确定性。


我的问题是这些函数生成的素数在加密方面的加密强度如何。

我不知道是否有一种数学上严格的方法来量化加密算法的强度。但是上面的分析告诉你给定生成的密钥对很弱/容易破解的概率。

【讨论】:

  • 感谢您的意见,这对我来说绝对是足够的概率
【解决方案3】:

如果您使用 java.util.Random 之类的东西而不是 SecureRandom 的实例,则生成的素数是不安全的。您的代码 sn-p 没有告诉我们您正在使用什么,因此无法验证您的代码。当然,您可能应该只使用 JCE 来生成新的 RSA 密钥。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    相关资源
    最近更新 更多