【问题标题】:While attempting to calculate D for an RSA implementation, D always comes out negative在尝试为 RSA 实现计算 D 时,D 总是为负数
【发布时间】:2017-09-22 17:59:15
【问题描述】:

我正在尝试使用扩展欧几里得算法计算 RSA 的 d。然而,每次我跑进去,结果都是负面的。

这是算法的代码,假设 a 是 phi,e 是 65537:

BigInteger exEuc(BigInteger a, BigInteger b){
    BigInteger x = 0;
    BigInteger prevX = 1; //holds the previous value of x
    BigInteger y = 1;
    BigInteger prevY = 0; //holds the previous value of y
    BigInteger temp, q;
        while(b != 0){
            q = a / b;
            temp = b;
            b = a % b;
            a = temp;
            temp = x;
            x = prevX-q*x;
            prevX = temp;
            temp = y;
            y = prevY-q*y;
            prevY = temp;
      }
      return prevY; //this ends up being d
}

我已经使用 e*d mod phi 测试了结果,它给出了预期的 1,但我知道 d 不应该是负数。知道这里出了什么问题吗?

【问题讨论】:

  • 您是否尝试过使用 unsigned 大数字?还是将其打印为 无符号 数字?
  • 您是否尝试过使用调试器单步执行您的代码,以找出结果为负数的位置以及原因?
  • 是的,这就是欧几里得算法的工作方式。对于计算逆运算,您总是需要正余数,you need to add b to the answer if it is negative
  • 当我添加一个 OR b 时,数字仍然是负数,并且在这两种情况下,我尝试时 e*dmodphi=1 测试都失败
  • 我不是你说的那样,但如果你将phi 添加到 d 中,它将是正数,并且 e*d 将等于 1 mod phi。

标签: c++ encryption rsa


【解决方案1】:

扩展欧几里得算法的实现没有任何问题,正如它为加密指数 e 提供正确的模逆 d 的事实所示。

但是,对于 RSA,您确实需要 d 值。为此,只需让:

d = exEuc(phi, e) % phi;

假设您的 BigInteger 库的 % 运算符始终返回非负结果。如果不是这样,那么至少结果应该大于-phi,在这种情况下你可以简单地这样做:

d = exEuc(phi, e) % phi;
if ( d < 0 ) d += phi;

之所以有效,是因为在modular arithmetic 中,模数的加减(整数倍)不会改变数字的同余类。特别是,如果(d*e) % phi == 1,那么也是((d+phi)*e) % phi == 1


顺便说一句,您可以对exEuc() 代码进行一些优化。第一个是你实际上并没有使用 xprevX 值来做任何事情,所以你可以完全摆脱它们,就像这样:

BigInteger exEuc(BigInteger a, BigInteger b){
    BigInteger y = 1;
    BigInteger prevY = 0; //holds the previous value of y
    BigInteger temp, q;
        while(b != 0){
            q = a / b;
            temp = b;
            b = a % b;
            a = temp;
            temp = y;
            y = prevY-q*y;
            prevY = temp;
      }
      return prevY; //this ends up being d
}

第二个优化是,因为我们只对结果模 phi 感兴趣,我们实际上可以在计算过程中随时减少 yphi 以防止它变得太大(或否定!):

// calculate the modular inverse of x modulo m
BigInteger modInv(BigInteger x, BigInteger m){
    BigInteger a = x, b = m;
    BigInteger y = 1;
    BigInteger prevY = 0; //holds the previous value of y
    BigInteger temp, q;
        while(b != 0){
            q = a / b;
            temp = b;
            b = a % b;
            a = temp;
            temp = y;
            y = (prevY-q*y) % m;
            prevY = temp;
      }
      if ( prevY < 0 ) prevY += m;  // may or may not be necessary
      return prevY; // this ends up being d
}

(请注意,我重命名了函数及其参数,以便更好地描述优化版本的实际作用。另外请注意,我包括了一个额外的测试,以确保即使您的 BigInteger 库的返回值也不会为负% 运算符可能返回负值。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    • 2014-03-30
    相关资源
    最近更新 更多