【问题标题】:Coding RSA Algorithm Java编码 RSA 算法 Java
【发布时间】:2018-09-28 04:42:03
【问题描述】:

所以,我正在尝试从头开始创建 RSA 算法。

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

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

使用这个新计算的 φ,我想找到一个数字,或者更确切地说创建一个遵循 1

这是我的代码。

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

}

非常感谢任何帮助。

谢谢!

【问题讨论】:

  • 这段代码有什么变化while (GCD.gcd(z).compareTo(ONE) != 0) { temp++; }唯一变化的是temp,它是一个局部变量,所以循环永远不会结束,因为它没有改变
  • 嗯,temp 正在循环中被改变,所以即使它是在本地声明的,它也应该改变。有点像 for 循环中的索引,对吗?
  • 不,while (GCD.gcd(z).compareTo(ONE) != 0) 不使用 temp 所以改变它没有区别
  • @ScaryWombat 即使在删除临时文件后,将 GDC 更改为等于 BigInteger.valueOf(2);然后循环并执行 GCD.add(ONE);直到比较为真会导致循环永远进行。所以无论哪种方式都没有区别。
  • 我也尝试在 z-1 处启动 GCD 变量,但这会导致循环立即结束,所以我的 e 总是比 z 小 1,我认为这是行不通的。

标签: java encryption rsa biginteger greatest-common-divisor


【解决方案1】:

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

如何获得e

当您只是检查是否相等时,一个提示是使用equals() 而不是compareTo()。有时这可以减少工作量,也更容易阅读。

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

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

查看BigInteger的方法

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

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

使用BigInteger的内置常量

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

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

切勿将BigInteger 转换为long,除非您确定它适合

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

当您获得long 时,您还经常使用intValue()。使用longValueExact()。就此而言,当您获得int 时,请使用intValueExact()

所以,计算 φ:

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

BigInteger phi = pMinusOne.multiply(qMinusOne);

现在你知道它会给出正确的结果,即使是更大的BigIntegers。也没有那么难读,有利于后期维护代码。

存储什么

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

一般情况下,不要在getZZZ方法中计算

您应该在构造方法中找出 ne(以及 d,但前提是它是私钥)和仅将那些存储在实例变量中。然后,您可以使用getN()getE() 方法来获取预先计算的实例变量。例如(而且你不必使用这段代码,它只是提供一个想法):

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

【讨论】:

  • 惊人的解释!太感谢了!这很有帮助。直到昨天我才使用 BigInteger,所以我没有像我应该做的那样彻底地查看 API。
  • 我唯一的问题是,3L的价值是多少?
  • @Granzo 将L 放在数字后面意味着将该数字视为long,而不是默认的int。所以,3L 的值就是long 的值3。在这里,它是不需要的,因为 3 (int) 将很好地转换为 3L (long),但是我出于习惯使用它,因为在任何需要 long 的地方,因为数字可能会溢出而没有L 如果它太大而无法容纳在 int 中,并且习惯可以避免这个问题。
  • 抱歉,最后一个问题。当我调用 return d 时,它似乎返回了不正确的值。例如,我用 p 的值为 5 和 q 的值为 7 对其进行测试。但是,经过计算,我得到了 D = 5。它不应该等于 29 吗?
  • 嗯,是的,也不是,d = 29 也可以解密,但 phi 是 24,所以你总是会减少 d 模 phi 以减少以后的计算。减少 29 模 phi,我们得到 29 ≡ 5 (mod 24),因此 d = 5 也可以解密,并且计算所需的时间更少,并且(当数字变大时),存储空间更少。
猜你喜欢
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 2011-11-06
  • 2013-03-25
  • 2017-07-08
相关资源
最近更新 更多