用Java编写RSA算法

用Java编写RSA算法,java,encryption,rsa,biginteger,greatest-common-divisor,Java,Encryption,Rsa,Biginteger,Greatest Common Divisor,因此,我试图从头开始创建一个RSA算法 到目前为止,我已经成功地创建了选择两个素数的能力(在我当前的示例中,我有11和13个素数)。然后,我通过pxq计算N,得到143 然后,我转到我的public biginger findZ()方法,该方法计算φ,即(p-1)(q-1) 使用这个新计算的ψ,我想找到一个数字,或者更确切地说,创建一个紧跟在1之后的e变量,因为您需要任何帮助,我将回答您的问题并给出其他提示 如何得到e 一个技巧是在检查相等性时使用equals()而不是compareTo()。有

因此,我试图从头开始创建一个RSA算法

到目前为止,我已经成功地创建了选择两个素数的能力(在我当前的示例中,我有11和13个素数)。然后,我通过pxq计算N,得到143

然后,我转到我的
public biginger findZ()
方法,该方法计算φ,即(p-1)(q-1)


使用这个新计算的ψ,我想找到一个数字,或者更确切地说,创建一个紧跟在1之后的e变量,因为您需要任何帮助,我将回答您的问题并给出其他提示

如何得到e 一个技巧是在检查相等性时使用
equals()
而不是
compareTo()
。有时这可以减少所做的工作量,也更容易阅读

代码中最大的错误是
temp
用于设置
GCD
的原始值,但它没有将
temp
链接到GCD。它们保持断开连接。如果您稍后更改
temp
GCD
将不知道也不会更改。您需要直接向
GCD
添加一个。下面是一些示例e代码:

biginger e=biginger.valueOf(3);
而(!phi.gcd(e).equals(biginger.ONE)){
e=e.add(biginger.ONE);
}
查看
biginger
的方法 通过使用您喜爱的搜索引擎并搜索
BigInteger 8 API
,了解您可以轻松使用
BigInteger
做什么。8代表您正在使用的Java版本,因此可能会发生更改。API代表方法列表

在搜索结果的早期,您应该会发现。
biginger
有很多好的和方便的方法,所以请查看它们。它甚至有一个构造函数,可以为您提供一个
biginger
,大小不限,很可能是素数,这对于为新的随机RSA密钥生成素数很好

使用
biginger
的内置常量 不要重新创建以下常量(显示在上面的API页面中):

  • biginger.ZERO
  • biginger.ONE
  • biginger.TEN
切勿将
biginger
转换为
long
,除非您确定它适合 您正在将
biginger
s转换为
long
,这是一个坏主意,因为有很多
biginger
s无法放入
long
,给您带来了不正确的结果。为了正确性(比速度更重要),请直接使用
biginger
s进行算术运算

在获得
long
时,也会大量使用
intValue()
。请使用
longValueExact()
。因此,在获得
int
时,请使用
intValueExact()

因此,要计算φ:

biginger pMinusOne=p.subtract(biginger.ONE);
biginger qMinusOne=q.subtract(biginger.ONE);
BigInteger phi=pMinusOne.multiply(qMinusOne);
现在您知道它将给出正确的结果,即使对于较大的
biginger
s也是如此。它也不难阅读,这有利于以后维护代码

储存什么 您还应该只存储n和e(和d,但仅当它是私钥时)决不使用RSA存储p、q或ν,因为它们允许您轻松地从公钥中找出私钥

通常,不要在
getZZZ
方法中计算 您应该在构造函数方法中计算出n和e(以及d,但只有在它是私钥的情况下)并仅将它们存储在实例变量中。然后,您可以使用
getN()
getE()
方法来获取预计算的实例变量。例如(您不必使用此代码,这只是为了给出一个想法):

公共类RSA{
私有最终大整数n;
私有最终大整数;
私有最终bigd;
公共RSA(最终大整数p,最终大整数q){
n=p乘以(q);
//计算φ
最终的BigInteger pMinusOne=p.subtract(BigInteger.ONE);
最终的BigInteger qMinusOne=q.subtract(BigInteger.ONE);
最终大整数phi=pMinusOne.multiply(qMinusOne);
//计算e
BigInteger e=BigInteger.valueOf(3L);
而(!phi.gcd(e).equals(biginger.ONE)){
e=e.add(biginger.ONE);
}
这个。e=e;
//计算d
此.d=e.modInverse(φ);
}
公共BigInteger getN(){
返回n;
}
public BigInteger getE(){
返回e;
}
公共BigInteger getD(){
返回d;
}
}

while(GCD.GCD(z).compareTo(ONE)!=0){temp++;}唯一改变的是
temp
,它是一个局部变量,因此循环永远不会结束,因为它不会改变。很好,temp在循环中被改变,所以即使它是在局部声明的,它也应该改变。有点像for循环中的索引,对吗?不,
while(GCD.GCD(z).compareTo(ONE)!=0)
不使用
temp
,因此更改它不会difference@ScaryWombat即使在删除temp之后,也要将GDC更改为等于biginger.valueOf(2);然后循环并执行GCD.add(1);直到比较为真,循环才会永远继续。所以无论哪种方式都没有区别。我也尝试过在z-1处启动GCD变量,但是这会导致循环立即结束,所以我的e总是比z小一个,我认为这不起作用。非常好地解释了!非常感谢!这非常有用。I'v直到昨天,我才开始使用BigInteger,所以我没有像应该的那样彻底地查看API。我唯一的问题是,3L的值是多少?@Granzo将
L
放在数字后面意味着将数字视为
long
而不是默认的
int
。因此,
3L
的值
import java.math.BigInteger;

public class RSA 
{
//Intialize the variables.

private BigInteger p;
private BigInteger q;
private BigInteger n;
private BigInteger z;

final private BigInteger ONE = BigInteger.valueOf(1);


public BigInteger getP()
{
    return p;
}

public BigInteger getQ()
{
    return q;
}

//Computes N, which is just p*q.
public BigInteger findN()
{

    n = p.multiply(q);


    return p.multiply(q);
}


public BigInteger findZ()
{
    long pMinusOne = p.intValue() - 1;
    long qMinusOne = q.intValue() - 1;


    z = BigInteger.valueOf(pMinusOne * qMinusOne);

    return z;
}


public BigInteger getE()
{
     int temp = ONE.intValue() + 1;

     BigInteger GCD = BigInteger.valueOf(temp);

     while (GCD.gcd(z).compareTo(ONE) != 0)
     {
         temp++;
     }



    e = BigInteger.valueOf(temp);

    return e;
}