【问题标题】:Is there a reason this is wrong?这是错误的原因吗?
【发布时间】:2023-03-22 02:55:02
【问题描述】:
#include <iostream>
#include <bits/stdc++.h>
#include <numeric>

using namespace std;

int
gcd (int a, int b)
{
  if (a == 0)
    return b;
  return gcd (b % a, a);
}

int
phi (unsigned int n)
{
  unsigned int result = 1;
  for (int i = 2; i < n; i++)
    if (gcd (i, n) == 1)
      result++;
  return result;
}

int
gen_priv_n (int p1, int p2)
{
  int n = phi (p1) * phi (p2);
  return n;
}

int
gen_pub_n (int p1, int p2)
{
  int n = (p1 * p2);
  return n;
}

int
gen_priv_key (int n, int e)
{
  int x = (phi (e) * n + 1) / e;
  return x;
}

int
encrypt (int n, int e, int data)
{
  int crypt_data = int (pow (data, e)) % n;
  return crypt_data;
}

int
decrypt (int c, int d, int n)
{
  int data = int (pow (c, d)) % n;
  return data;
}

int
main ()
{
  int ph1 = 53;
  int ph2 = 59;
  int e = 3;
  int message = 89;
  
  int pub_n = gen_pub_n (ph1, ph2);
  cout << "PUBN " << pub_n << "\n";
  int priv_n = gen_priv_n (ph1, ph2);
  cout << "PRIVN " << priv_n << "\n";
  int d = gen_priv_key (gen_priv_n (ph1, ph2), e);
  cout << "PRIVKEY " << d << "\n";
  int c = encrypt (pub_n, e, message);
  cout << "ENCRYPTED " << c << "\n";
  int data = decrypt (c, d, pub_n);
  cout << "MESSAGE " << data;
}

PUBN、PRIVN、PRIVKEY 和 ENCRYPTED 都返回预期的数字,但是,解密函数应该返回 89(消息变量),但没有返回。我假设操作代码顺序存在算术错误,但我不确定。可以指出问题吗?

变量的结果是:

  • PUBN 3127
  • PRIVN 3016
  • PRIVKEY 2011
  • 加密 1394
  • MESSAGE -763

【问题讨论】:

  • 去掉非标准的bits 标头和using namespace std;。已经有一个gcd C++ 函数,并且在程序中包含所有这些内容将很容易让程序的行为与预期不同。
  • 看起来pow(1394, 2011) 远远超出了int 可以存储的范围。您需要在进行指数计算时继续应用模数以避免溢出。
  • 至于什么是错误的,假设它应该是基于整数的程序被破坏了。它被破坏了,因为你使用了一个浮点函数pow,一旦你这样做了,所有关于基于整数的程序将产生什么结果的赌注都没有了。如果您在 pow 函数中使用了较小的值,情况也是如此。
  • @NathanPierson 我该怎么做?使用 for 循环?
  • 如果你想玩密码学,开始学习 GNU/GMP

标签: c++ encryption cryptography public-key-encryption


【解决方案1】:

解密(和加密)功能被破坏,因为它 (a) 超出了 int 的平台表示,并且 (b) 首先不必要地使用了 pow

在您的简单示例中,您应该使用一种称为 模链 的技术。这其中的症结如下。

(a * b) % n == ((a % n) * (b % n)) % n

在您的情况下,您正在执行简单的幂运算。这意味着,例如 a^2 % n 将是:

(a * a) % n = ((a % n) * (a % n)) % n

同样,a^3 % n 是:

(a * a * a) % n = (((a % n) * (a % n)) % n) * (a % n)) % n

只要没有乘积项对超过您的平台表示(并且在您的情况下没有),使用模链可以计算否则将是非常大的乘积计算模数 N。

执行此操作的整数pow 的简单版本如下:

int int_pow_mod(int c, int d, int n)
{
    int res = 1;

    // may as well only do this once
    c %= n;

    // now loop.
    for (int i=0; i<d; ++i)
        res = (res * c) % n;

    return res;
}

明白,这不是灵丹妙药。你可以很容易地设计一个c,它仍然生产出超过INT_MAX的产品,但在你的情况下,由于你选择了起始材料,这不会发生。一个通用的解决方案将使用这个 with 一个允许超过平台int 表示的大型库。无论如何,这样做应该可以满足您的需求,如下所示:

#include <iostream>
using namespace std;

unsigned int gcd(unsigned int a, unsigned int b)
{
    if (a == 0)
        return b;
    return gcd(b % a, a);
}

int phi(unsigned int n)
{
    unsigned int result = 1;
    for (unsigned int i = 2; i < n; i++)
        if (gcd(i, n) == 1)
            result++;
    return result;
}

int gen_priv_n(int p1, int p2)
{
    int n = phi(p1) * phi(p2);
    return n;
}

int gen_pub_n(int p1, int p2)
{
    int n = (p1 * p2);
    return n;
}

int gen_priv_key(int n, int e)
{
    int x = (phi(e) * n + 1) / e;
    return x;
}

int int_pow_mod(int c, int d, int n)
{
    int res = 1;

    // may as well only do this once
    c %= n;

    // now loop.
    for (int i=0; i<d; ++i)
        res = (res * c) % n;

    return res;
}

int encrypt(int n, int e, int data)
{
    int crypt_data = int_pow_mod(data, e, n);
    return crypt_data;
}


int decrypt(int c, int d, int n)
{
    int data = int_pow_mod(c, d, n);
    return data;
}

int main()
{
    int ph1 = 53;
    int ph2 = 59;
    int e = 3;
    int message = 89;

    int pub_n = gen_pub_n(ph1, ph2);
    cout << "PUBN " << pub_n << "\n";
    int priv_n = gen_priv_n(ph1, ph2);
    cout << "PRIVN " << priv_n << "\n";
    int d = gen_priv_key(gen_priv_n(ph1, ph2), e);
    cout << "PRIVKEY " << d << "\n";
    int c = encrypt(pub_n, e, message);
    cout << "ENCRYPTED " << c << "\n";
    int data = decrypt(c, d, pub_n);
    cout << "MESSAGE " << data;
}

输出

PUBN 3127
PRIVN 3016
PRIVKEY 2011
ENCRYPTED 1394
MESSAGE 89

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多