我编写的代码不多,但是,当我尝试在JAVA中实现RSA加密时,我的加密和解密工作适用于较小的素数,但是当我尝试针对1536位大小的素数进行加密时,解密就停止了。我已经解决了,但是我看不出问题出在哪里。
我已经尝试查看位长在什么时候开始成为问题,似乎是当我将其设置为50时才停止工作。如果我的mod逆方法引发关于e.modinv(lambda)的错误,我也容易出错 不可能。我尝试通过添加do循环来解决此问题,但看来这并不能解决问题。
public BigInteger Random_Prime()
{
SecureRandom random = new SecureRandom();
byte [] randomize = new byte [192];
random.nextBytes(randomize);
BigInteger big = new BigInteger(randomize);
return big.probablePrime(1536,random);
}
public BigInteger lcm(BigInteger p, BigInteger q)
{
long p1 = p.longValue()-1;
long q1 = q.longValue()-1;
BigInteger test1 = p.valueOf(p1);
BigInteger test2 = p.valueOf(q1);
return test1.multiply(test2).divide(test1.gcd(test2));
做{
p = obj1.Random_Prime();
q = obj1.Random_Prime();
lambda = obj1.lcm(p, q);
}
while(lambda.gcd(e).compareTo(ONE)!=0);
BigInteger n = p.multiply(q);
BigInteger m = new BigInteger("75");
BigInteger d = e.modInverse(lambda);
BigInteger c = obj1.Encrypt(n,e,m);
我希望75经过加密和解密后会恢复为75。
答案 0 :(得分:4)
您的lcm()
错误。
Java long
只有64位(包括符号),并且不能表示大于2 ^ 63的数字。 (或相等,但是大质数永远不等于2的幂)。因此,您的lcm
计算应该对最多63位的p,q有效,并且对我有用,但是对于任何更大的东西。而是将{p,q}.subtract(BigInteger.ONE)
用于您乘以gcd除以的数字。
此外,BigInteger.probablePrime(int,Random)
是static
(又称全班级)方法;您不需要使用任何实例来调用它,更不用说使用浪费时间计算的随机值了,因为它被忽略了。因此,BigInteger.valueOf(long)
也是static
,并且会忽略用于调用它的任何实例。如果您使用的是比仅在外壳或COMMAND中键入javac
更高级的Java开发环境,它应该(至少有选择地)向您发出有关使用实例调用静态方法的警告。
最后,如果您不知道,直接使用RSA原语m ^ e mod n和c ^ d mod n加密/解密数据(尤其是小数据)是不安全的。您必须使用足够大且随机的填充方案,才能完全确保安全;请参见wikipedia进行简短说明,如果您想在https://crypto.stackexchange.com上进行更多次搜索并回答{em>很多次的https://security.stackexchange.com,甚至是here。而且,如果仅通过执行c.modPow(d,n)
来解密(未显示),则效率低下(请参阅有关CRT的维基百科)和不安全(请参阅有关计时攻击的Wikipedia,以及crypto.SX和security.SX)。而且直接将RSA用于数据非常有限且效率低下,因此在实践中人们使用 hybrid 加密-使用对称算法(如今通常为AES)在随机数密钥下加密数据,并对随机数进行加密使用RSA的密钥-或者使用RSA-KEM更好的 derive (再次参见Wikipedia crypto.SX security.SX)。
如果您确实想要安全性而不仅仅是玩耍,请使用Java库中的加密货币,该加密货币已由有能力的人正确实施(并审核),与以往不同您的代码。