首页 > 解决方案 > 编码 RSA 算法 Java

问题描述

所以,我试图从头开始创建一个 RSA 算法。

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

然后,我继续使用我的 public BigInteger findZ()方法来计算 φ,即 (p-1)(q-1)。

使用这个新计算的 φ,我想找到一个数字,或者更确切地说创建一个遵循 1<(e)<φ 或简单 gcd(e,φ) = 1 的 e 变量因此,我最初将 temp 设置为等于我的常数 ONE (等于一)+ 1 来满足范围。但是,经过不断的调试尝试,循环永远不会找到 GCD 等于 1 的值,因为我需要使用 BigInteger,所以我创建了一个常量来表示。是否有一个原因?

这是我的代码。

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;
}

}

任何帮助是极大的赞赏。

谢谢!

标签: javaencryptionrsabigintegergreatest-common-divisor

解决方案


既然您要求任何帮助,我将回答您的问题并提供其他提示。

如何获得电子

一个提示是使用equals()而不是compareTo()仅在检查相等性时使用。有时这可以减少正在完成的工作量,并且也更容易阅读。

您的代码中最大的错误temp是用于设置 的原始值GCD,但未链接temp到 GCD。他们保持断开连接。如果您temp以后更改,GCD将不知道并且不会更改。您需要GCD直接添加一个。这是一些示例代码:

BigInteger e = BigInteger.valueOf(3);
while (! phi.gcd(e).equals(BigInteger.ONE)) {
    e = e.add(BigInteger.ONE);
}

查看 overBigInteger的方法

BigInteger通过使用您最喜欢的搜索引擎并进行搜索,了解您可以轻松使用 's 做什么BigInteger 8 API。8 适用于您正在使用的 Java 版本,因此可能会发生变化。API 用于方法列表。

在搜索结果的早期,您应该找到这个 API 页面BigInteger有很多好用又方便的方法,快来看看吧。它甚至有一个构造函数,可以为您提供BigInteger您想要的任何大小,这很可能是一个素数,这对于为新的随机 RSA 密钥生成素数非常有用。

使用BigInteger的内置常量

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

  • BigInteger.ZERO
  • BigInteger.ONE
  • BigInteger.TEN

除非您确定它适合,否则切勿转换BigIntegerlong

您正在将BigIntegers 转换为long,这是一个坏主意,因为有很多BigIntegers 不适合 a long,从而给您不正确的结果。为了正确性(这比速度更重要),直接用s做算术BigInteger

当您intValue()获得long. 使用longValueExact(). 就此而言,intValueExact()请在获得int.

因此,要计算 φ:

BigInteger pMinusOne = p.subtract(BigInteger.ONE);
BigInteger qMinusOne = q.subtract(BigInteger.ONE);

BigInteger phi = pMinusOne.multiply(qMinusOne);

现在您知道它会给出正确的结果,即使对于更大BigInteger的 s。它也不难阅读,这有利于以后维护代码。

存储什么

您还应该只存储ne(以及d,但前提是它是私钥)永远不要使用 RSA存储pqφ,因为它们可以让您轻松地从公钥中找出私钥。

一般来说,不要在getZZZ方法中计算

您应该在构造函数方法中找出ne(以及d,但前提是它是私钥),并仅将它们存储在实例变量中。然后,您可以使用getN()andgetE()方法来获取预先计算的实例变量。例如(您不必使用此代码,它只是提供一个想法):

public class RSA {
    private final BigInteger n;
    private final BigInteger e;
    private final BigInteger d;

    public RSA(final BigInteger p, final BigInteger q) {
        this.n = p.multiply(q);

        // Calculate phi
        final BigInteger pMinusOne = p.subtract(BigInteger.ONE);
        final BigInteger qMinusOne = q.subtract(BigInteger.ONE);
        final BigInteger phi = pMinusOne.multiply(qMinusOne);

        // Calculate e
        BigInteger e = BigInteger.valueOf(3L);
        while (! phi.gcd(e).equals(BigInteger.ONE)) {
            e = e.add(BigInteger.ONE);
        }
        this.e = e;

        // Calculate d
        this.d = e.modInverse(phi);
    }

    public BigInteger getN() {
        return n;
    }

    public BigInteger getE() {
        return e;
    }

    public BigInteger getD() {
        return d;
    }
}

推荐阅读