【问题标题】:Simplify modular exponentiation C++简化模幂运算 C++
【发布时间】:2014-02-26 22:17:42
【问题描述】:

我正在尝试为 RSA 加密系统编写解密函数,对于 非常 小数字,一切似乎都运行良好,但有时输出不正确(我认为原因可能是浮点错误或某种堆栈溢出)。

导致我出现问题的过程可以简化为 (11^23) mod 187,但我会包含完整的代码,以防有人想看到它。我知道答案应该是 88,因为它是 Simon Singh 博士在“密码书”附录 J 中使用的示例(我也使用 Wolfram Alpha 进行了检查)。但是,我得到了 149 的结果。但是,对于较小的数字,它与 Wolfram Alpha 一致。

我的想法是我需要使用以下知识来简化模幂运算:

a^b = a^c * a^d [ 其中 c + d = b ]

但是,我仍然不能 100% 确定这是否是这个问题,这是我的第一次堆栈溢出吗? (我仍然不是 100% 确定这意味着什么)。在任何人对我动手之前,不,这不是任何家庭作业,如果这个问题看起来微不足道,我很抱歉。如果每个人都认为这太难了,我愿意使用 gmp.h,但如果我完全诚实的话,我宁愿不这样做。我的代码如下(前半部分是计算私钥,我认为这与我遇到的问题无关,但我已经包含它以防万一我错了),我真的希望你们能帮助,谢谢非常提前。

#include <iostream>
#include <math.h>

using namespace std;

unsigned int modinv(unsigned int u, unsigned int v)
{
    unsigned int inv, u1, u3, v1, v3, t1, t3, q;
    int iter;

    u1 = 1;
    u3 = u;
    v1 = 0;
    v3 = v;

    iter = 1;

    while (v3 != 0)
    {

        q = u3 / v3;
        t3 = u3 % v3;
        t1 = u1 + q * v1;

        u1 = v1; v1 = t1; u3 = v3; v3 = t3;
        iter = -iter;
    }

    if (u3 != 1)
        return 0;
    if (iter < 0)
        inv = v - u1;
    else
        inv = u1;
    return inv;
}

int main()
{ long unsigned int p = 17;
long unsigned int q = 11;
long unsigned int phi = (p-1)*(q-1);
long unsigned int e = 7;
long unsigned int c = 11;
long unsigned int n = p*q;
long unsigned int d = modinv (e,phi);
    {
         cout << fmod (pow (c, d), n);
    }
    return 0;
}

【问题讨论】:

  • 也许 11^n mod 187 是一个不好的例子,因为 11 是主要因素之一(187 = 11 x 17)?因此,对于 n >= 1 的 11^n mod 187,只有 16 个值,重复模式:11 121 22 55 44 110 88 33 176 66 165 132 143 77 99 154 || 11 121 ....所以 11^n mod 187 = 11^(1+((n-1) mod 16)) mod 187。
  • 我已经对其进行了排序:) pow 函数使用的是浮点数而不是自然数,我必须编写自己的模幂运算,结果很好,谢谢

标签: c++ debugging encryption rsa modular-arithmetic


【解决方案1】:

11^23 大约是 2^80。只有不超过 2^53 的整数可以精确地表示为双浮点数。因此 fmod(pow(c, d), n)) 返回一个近似值。这不适合密码学。

添加您可以使用重复平方进行模幂运算。查看 Wikipedia 关于“平方求幂”的文章

【讨论】:

  • 什么是合适的选择?
  • 实现你自己的模幂函数。它相当简单,需要的行数比你的 modinv 少。
  • 所以没有现有的方法可以做到这一点,我必须自己写吗?抱歉,这似乎是一个愚蠢的问题。
  • 是的,您必须自己编写。大概有 14 行。
  • int modExp(int b, int e, int m) { int remainder; int x = 1; while (e != 0) { remainder = e % 2; e= e/2; if (remainder == 1) x = (x * b) % m; b= (b * b) % m; // New base equal b^2 % m } 这行得通,谢谢:)
【解决方案2】:

这篇关于 RSA 的 wiki 文章部分应该会有所帮助:

RSA decryption worked example

注意文章中包含中文余数算法的链接,其中包含欧几里得算法的链接:给定两个素数p和q,求两个整数a和b,使得a p + b q = 1,这也意味着( a p) mod q == 1 和 (b q) mod p == 1。不清楚的是 a 或 b 将是负数,负值将用于余数算法的第一部分(文章声明使用欧几里得算法的值)。例如,如果 a 为负数,则 (a p) mod q == 1,但 ((a+q) p) mod q 也 == 1,因此 a 和 a+q 都可以认为是 p 的倒数数学模 q。

【讨论】:

    猜你喜欢
    • 2017-07-28
    • 2017-02-02
    • 1970-01-01
    • 2016-11-18
    • 2011-01-13
    • 2014-08-21
    • 2016-01-21
    • 2017-04-03
    相关资源
    最近更新 更多