Java 为什么不';是否将大型RSA密钥加密为唯一值?

Java 为什么不';是否将大型RSA密钥加密为唯一值?,java,cryptography,rsa,biginteger,key-pair,Java,Cryptography,Rsa,Biginteger,Key Pair,我正在使用BigInteger的probablePrime方法计算两个2048位素数,如下所示:BigInteger.probablePrime(2048,new Random())。我们分别称这些素数为p和q。我使用以下代码计算私有指数:biginger.TWO.multiply(r)、add(biginger.ONE)、divide(e)>24), (字节)(t>>16), (字节)(t>>8), (字节)t, }; BigInteger p=BigInteger.probablePri

我正在使用BigInteger的
probablePrime
方法计算两个2048位素数,如下所示:
BigInteger.probablePrime(2048,new Random())。我们分别称这些素数为
p
q
。我使用以下代码计算私有指数:
biginger.TWO.multiply(r)、add(biginger.ONE)、divide(e)e
相当于
biginger。value of(3)
r
相当于一个biginger,其值为:
(p-1)(q-1)

创建加密的BigInteger如下:
message.modPow(e,r)
,其中
message
是一个BigInteger

假设我希望加密
774356626352684872522728355634287624183747537537718011900969524254770659766752605764866132228010801740792162094
。这个大整数是“敏捷的棕色狐狸跳过了懒狗”。转换成二进制,然后转换成十进制。我的结果是
464326058229369014486528960945777245568243099145851675968955900279041350590262478935529494941451499366781745887243451051416055835411438062567069130399798367828605286094702345302515687649240227134432014786530128741317715599933776184879296961137474878787878787288775878787878725125906252525276767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676

不管我运行上面的代码多少次,它总是加密到相同的精确值。它生成哪个素数似乎无关紧要——对于特定的
消息
值,加密值始终是上面的值

现在在这里它变得特别特别,如果我生成512位素数,结果是唯一的。每次我运行上面的代码,生成512位素数而不是2048位甚至1024位素数,每次运行时都会生成一个唯一的结果。但是,如果我希望生成1024或2048位的素数,无论生成的素数是什么,结果总是相同的

有人能解释为什么会发生这种情况,或者需要对代码进行哪些更改才能使用2048位素数生成唯一的加密整数吗?具体来说,为什么它适用于512位或更低的素数,而不适用于1024位或更大的素数?如果这不是一个结构最合理的问题,我深表歉意,因此,如果有什么令人困惑的地方,请不要犹豫要求澄清

谢谢

编辑:以下是产生问题的代码:

import java.io.IOException;
导入java.math.biginger;
导入java.security.SecureRandom;
公开课{
公共静态void main(字符串[]args)引发IOException{
int t=(int)(System.currentTimeMillis()/1000);
字节[]日期=新字节[]{
(字节)(t>>24),
(字节)(t>>16),
(字节)(t>>8),
(字节)t,
};  
BigInteger p=BigInteger.probablePrime(2048,新SecureRandom(日期));
BigInteger q=BigInteger.probablePrime(2048,新SecureRandom(日期));
biginger e=biginger.valueOf(3);
BigInteger r=p.subtract(BigInteger.1)。乘法(q.subtract(BigInteger.1));
BigInteger消息=新的BigInteger(“77435626352684872522728356342876241837475537718011900969524254770659766752605764866132228010801740792162094”);
System.out.println(message.modPow(e,r));
}
}

你想运行多少次就运行多少次。它总是产生
464326058229369014486528960945777245568243099145851675968955900279041350590262478935529494941451499366781745887243451051416055835411438062567069130399798367828605286094702345302515687649240227134432014786530128741317715599933776184879296961137474878787878787288775878787878725125906252525276767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676。现在,如果我们在第16行和第17行将
2048
交换为
512
,每次运行都会产生一个唯一的值…

您正在执行原始/教科书式RSA,其中加密只是与公共指数的模幂运算。当然,还有一些对整数的转换、改变或解释

现在你的公众指数很小:3。因此,很可能小的输入明文在求幂后比模小<代码>敏捷的棕色狐狸跳过了懒狗。
是45个字符/字节,或360位。如果您有一个360位的数字,并且您使用3执行幂运算,那么您将得到一个360 x 3=1080位的值,远低于2 x 2048=4096位的模,因此不会执行模缩减。2 x 512=1024,所以对于那些素数的大小,你的值只比模大“几位”,所以模值很重要

当然,您可以使用Fermat(F4)的第五个素数,其值为65537。这将导致模块化减少为360 x 65537>4096。但是,为了安全起见,应该使用填充方法,如中指定的填充方法。这些将扩展明文值,因此依赖于明文的数字表示将更接近模数(以位为单位)。然后,模幂运算的结果将实际执行至少几次模缩减,因此取决于不同的模值


更重要的是,PKCS#1 v1.5或PKCS#1 v2.2中指定的OAEP填充本身是随机的,因此即使使用相同的密钥对/模,加密相同的明文也会产生不同的密文。对于较大的密钥大小,即使指数3也被认为是安全的,尽管大多数RSA实现(OpenSSL、Java、C#/.NET等)仍然首选F4.

关于
Random
的文档清楚地表明它不适合这种应用程序,并建议您改用
SecureRandom
。感谢您的回复。我已将Random替换为SecureRandom。不幸的是,问题依然存在。编辑:将尝试使用当前时间进行种子设定。@DavidSchwartz各位,我更新了这篇文章以包含我正在使用的代码示例