使用 BigInteger probablePrime 函数对 RSA 加密安全吗?
Is using the BigInteger probablePrime function safe for RSA encryption?
我编写了一个代码,能够生成 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()
的 javadoc 说:
Returns a positive BigInteger that is probably prime, with the specified bitLength. The probability that a BigInteger returned by this method is composite does not exceed 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)
来测试您的主要候选人,以达到更高的确定性。
My question is how strong of an encryption these function generated prime numbers are in terms of encryption.
我不知道是否有数学上严格的方法来量化加密算法的强度。但是上面的分析告诉你给定的生成的密钥对很弱/容易破解的概率。
正如 Stephen C 在 中指出的那样,素数可能适用于 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
如果您使用 java.util.Random 之类的东西而不是 SecureRandom 的实例,则生成的素数是不安全的。您的代码片段没有告诉我们您在使用什么,因此无法验证您的代码。当然,您可能应该只使用 JCE 来生成新的 RSA 密钥。
我编写了一个代码,能够生成 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()
的 javadoc 说:
Returns a positive BigInteger that is probably prime, with the specified bitLength. The probability that a BigInteger returned by this method is composite does not exceed 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)
来测试您的主要候选人,以达到更高的确定性。
My question is how strong of an encryption these function generated prime numbers are in terms of encryption.
我不知道是否有数学上严格的方法来量化加密算法的强度。但是上面的分析告诉你给定的生成的密钥对很弱/容易破解的概率。
正如 Stephen C 在
加密随机性
我要补充一点,你实际上不应该使用任何 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
如果您使用 java.util.Random 之类的东西而不是 SecureRandom 的实例,则生成的素数是不安全的。您的代码片段没有告诉我们您在使用什么,因此无法验证您的代码。当然,您可能应该只使用 JCE 来生成新的 RSA 密钥。