LegendSaber 发表于 2021-10-24 13:13

RSA算法的C语言实现

本帖最后由 LegendSaber 于 2021-10-24 13:17 编辑

   想要实现RSA算法,就需要使用Miller-Rabin概率素性检验算法和扩展Euclid算法
以下是Miller-Rabin概率素性检验算法的实现
#include <cstdio>
#include <stack>
#include <cmath>

using namespace std;

typedef unsigned long long int ll;

bool isPrime(ll a, ll n);

int main()
{
      bool bIsPrime = true;
      double p = 0;
      ll s = 0, n = 0, a = 0, i = 0;
      
      printf("请输入概率p和要检测的素数n:");
      scanf("%lf %d", &p, &n);
      
      s = log(1 / (1 - p)) / log(2);
      
      for (i = 1; i <= s && i < n; i++)
      {
                if (!isPrime(i, n))      bIsPrime = false;
      }
      
      if (bIsPrime) printf("%ld is a prime\n", n);
      else printf("%ld is not a prime\n", n);
      return 0;      
}

bool isPrime(ll a, ll n)
{
      ll tmp = n - 1;
      ll d = 1;
      stack<ll> s;
      ll x = 0;
      
      while (tmp)
      {
                s.push(tmp % 2);
                tmp /= 2;
      }

      while (!s.empty())
      {
                x = d;
                d = (d * d) % n;
                if (d == 1 && x != 1 && x != n - 1) return false;
                if (s.top() == 1) d = (d * a) % n;
                s.pop();
      }
      
      if (d != 1) return false;
      return true;
}

接着是扩展Euclid的算法实现
#include <cstdio>
#include <stack>
#include <cmath>

using namespace std;

typedef unsigned long long int ll;

bool isPrime(ll a, ll n);

int main()
{
      bool bIsPrime = true;
      double p = 0;
      ll s = 0, n = 0, a = 0, i = 0;
      
      printf("请输入概率p和要检测的素数n:");
      scanf("%lf %d", &p, &n);
      
      s = log(1 / (1 - p)) / log(2);
      
      for (i = 1; i <= s && i < n; i++)
      {
                if (!isPrime(i, n))      bIsPrime = false;
      }
      
      if (bIsPrime) printf("%ld is a prime\n", n);
      else printf("%ld is not a prime\n", n);
      return 0;      
}

bool isPrime(ll a, ll n)
{
      ll tmp = n - 1;
      ll d = 1;
      stack<ll> s;
      ll x = 0;
      
      while (tmp)
      {
                s.push(tmp % 2);
                tmp /= 2;
      }

      while (!s.empty())
      {
                x = d;
                d = (d * d) % n;
                if (d == 1 && x != 1 && x != n - 1) return false;
                if (s.top() == 1) d = (d * a) % n;
                s.pop();
      }
      
      if (d != 1) return false;
      return true;
}

最后给出RSA算法的实现
#include <cstdio>
#include <stack>
#include <cmath>
#include <cstdlib>

using namespace std;

typedef unsigned long long int ll;

bool isPrime(ll a, ll n);      //判断是否为素数
ll ex_gcd(ll a, ll b, ll &x1, ll &y1);      //扩展欧几里得算法
ll quick_cal(ll a, ll b, ll n);      //快速指数算法
ll getRandomNumber();      //用来随机选取两个素数
ll gcd(ll a, ll b);

int main()
{
      ll m = 1900, c = 0;
      ll p = 0, q = 0, n = 0, d = 0, n_1 = 0;
      ll x = 0, y = 0, e = 0;
      
      p = getRandomNumber();

      q = getRandomNumber();
      
      n = p * q;
      n_1 = (p - 1) * (q - 1);
      
      for (int i = 2; i < n_1; i++)
      {
                if (gcd(n_1, i) == 1 && ex_gcd(i, n_1, x, y) == 1 && x < n_1)
                {
                        e = i;
                        d = x;
                }
      }
      
      printf("RSA加密前的数据:%ld\n", m);
      c = quick_cal(m, e, n);
      printf("RSA加密后的数据:%ld\n", c);
      m = quick_cal(c, d, n);
      printf("RSA解密后的数据:%ld\n", m);
      
      return 0;
}

ll quick_cal(ll a, ll b, ll n)
{
      ll d = 1;
      ll tmp = b;
      stack<ll> s;
      
      while (tmp)
      {
                s.push(tmp % 2);
                tmp /= 2;
      }
      
      while (!s.empty())
      {
                d = (d * d) % n;
                if (s.top() == 1) d = (d * a) % n;
                s.pop();
      }
      
      return d;
}

ll getRandomNumber()
{
      ll number = rand() % 1000;
      
      while (number < 100 || !isPrime(95, number)) number = rand() % 1000;
      
      return number;
}

ll ex_gcd(ll a, ll b, ll &x1, ll &y1)
{
      if (b == 0)
      {
                x1 = 1;
                y1 = 0;
               
                return a;
      }
      
      ll x2, y2;
      ll d = ex_gcd(b, a % b, x2, y2);
      
      x1 = y2;
      y1 = x2 - (a / b) * y2;
      
      return d;
}

bool isPrime(ll a, ll n)
{
      ll tmp = n - 1;
      ll d = 1;
      stack<ll> s;
      ll x = 0;
      
      while (tmp)
      {
                s.push(tmp % 2);
                tmp /= 2;
      }

      while (!s.empty())
      {
                x = d;
                d = (d * d) % n;
                if (d == 1 && x != 1 && x != n - 1) return false;
                if (s.top() == 1) d = (d * a) % n;
                s.pop();
      }
      
      if (d != 1) return false;
      return true;
}

ll gcd(ll a, ll b)
{
      return b == 0 ? a : gcd(b, a % b);
}

运行结果如下

flyingdancex 发表于 2021-10-24 14:03

现在实际应用基本都用openssl,不过学习和研究算法还得自己动手{:1_921:}

daishen 发表于 2021-10-24 19:51

看着,想着,好容易,实现却好难,
页: [1]
查看完整版本: RSA算法的C语言实现