RSA對稱加密C++實現

學習物聯網安全,讓自己實現以下非對稱加密算法RSA算法

根據原理進行Coding的時候發現由於太長時間不進行Coding,所以很是手生

於是萬能的百度起來,但是發現網絡上面的代碼過於複雜,不太適合強行Coding,尤其是對於我這種懶得逐句理解的人來說

因爲根據原理簡單的Coding了一下,能夠簡單的實現RSP加解密

當然中間有一點內存空間不對稱導致的亂碼問題,,,,這都是小問題,能看就行

當然我也會把網上大神寫的Code粘在後面

供大家參考

/*
RSA非對稱加密算法
公鑰-私鑰對進行加解密
準備:明文M,公鑰PU={e, n},私鑰PR={d, n}
準備兩個非常大的素數p和q,乘積爲 n = p*q, f(n) = (p-1)*(q-1)
找出一個與互f(n)爲質數的自然數e,1<e<f(n)
計算d, d = 1/e mod f(n)
最終得到公鑰PU = {e, n}, 私鑰PR = {d, n}
加密過程爲 C = M^e mod n
解密過程爲 M = C^d mod n
*/

/*
****************程序流程圖*********************
                   開始
                     |
            隨機獲取兩個素數p與q
                    |
            找出與f(n)互爲質數的自然數e
                    |
                計算獲得d
                    |
            PU={e, n},私鑰={d, n}
                    |
                RSA加密
                    |
                RSA解密
*/
#include <iostream>
#include<math.h>
#include<ctime>
#include<cstdlib>
#include <string>
#include<string.h>
using namespace std;



//將num轉換爲i二進制儲存在bin_num中
int BinaryTransform(int num, int *bin_num){
    int i = 0;
    int mod = 0;

    while (num != 0)
    {
        mod = num%2;
        bin_num[i++] = mod;
        num >> 1;
    }
    
    return i;//返回二進制的位數
}

//輾轉相除法求最大公因數
int Gcd(int a, int b){
    if(b == 0)
        return true;
    return Gcd(b, a%b);
}

//獲取n的互質數 e ,即另外一個數與n的最大公因數爲1
int Gete(int n)
{
    int another = n;//根據RSP算法的要求,e越大,加密效果越好
    int flag = 1;
    while (flag)
    {
       if(Gcd(n, ++another) == 1){
           flag = 0;
       }
    }

    return another;
}

//獲取d, d與e關於f(n)同餘
int Getd(int e, int n){
    return (1/e % n);
}

int Getpq()
{
    srand((unsigned)time(NULL));
    return (10 + rand()%100);//生成一個10-100的隨機數
}

int p, q, n, f, d, e;
void Init_RSA(){
    //生成p, q, f(n), d, e
    p = Getpq();
    q = Getpq();
    n = p*q;
    f = (--p)*(--q);
    d = Getpq();
    e = Gete(d);

    cout<< "p = " << p << endl
         << "q = " << q << endl
         << "n = " << n << endl
         << "f(n) =" << f <<endl
         << "d = " << d << endl
         << "e = " << e <<endl
         << "PU = {" << e << ", " << n <<"}" << endl
         << "PR = {" << d << ", " << n <<"}" << endl;
}

int GetPow(int x, int y)
{
    while(y--){
        x *= x;
    }

    return x;
}

string text;                //加密內容
int Plaintext[100];         //明文
long long Ciphertext[1000]; //密文

//解密 m = c^d(mod n)
void GetPlaintext(int Ciphertext[], int num, int d, int n)
{
    char sp[3];
    char *res;
    int i = 0;
    while (num--)
    {
        int low = GetPow(*Ciphertext, n) % n;//將明文的每一位都進行加密
        sprintf(sp, "%02d", low);//格式化爲兩位
        strcat(res, sp);//拼接起來
    }   

    cout << Ciphertext <<"加密完成, 結果爲:" << res << endl;
    *Ciphertext = {0};
}

//解密
void GetCiphertext(int *Plaintext, int num, int d, int n)
{
    char sp[3];
    char *res;
    int i = 0;
    while (num--)
    {
        int low = GetPow(Plaintext[i], n) % n;  //將明文的每一位都進行加密
        sprintf(sp, "%02d", low);               //格式化爲兩位
        strcat(res, sp);                        //拼接起來
    }

    cout << Plaintext << "解密完成, 結果爲:" << res <<endl;
    *Plaintext = {0};
}

int main(int argc, char const *argv[])
{
    int text[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 20};
    if (text != NULL)
    {
        Init_RSA();
        GetPlaintext(text, sizeof(text) / sizeof(text[0]), d, n);
        system("pause");
    }
    
    
    return 0;
}
//另一種方式
#include<bits/stdc++.h>
using namespace std;
int Euler(int n)//歐拉函數 求1到n中有多少個整數與n互質
{
    int rs=1;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            rs*=(i-1);
            n/=i;
            while(n%i==0)
            {
                rs*=(i-1);
                n/=i;
            }
        }
    }
    if(n>1)
        rs*=(n-1);
    return rs;
}
int gcd(int a,int b)//求a,b的最大公約數
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}
int check(int n)//判斷n是不是素數
{
    if(n==1)
        return 0;
    if(n==2)
        return 1;
    for(int i=3;i*i<=n;i=i+2)
    {
        if(n%i==0)
            return 0;
    }
    return 1;
}
int gnerating_primes(int n)//產生小於等於n的第一個素數
{
    if(n%2==0)
        n--;
    for(int i=n;i>1;i=i-2)
    {
        if(check(i)==1)
            return i;
    }
    return -1;//表示沒有小於等於n的素數
}
int multiplicative_inverse_element(int a,int r)//求a對於r的乘法逆元
{
    int rs=1;
    if(check(r)==1)//r是素數 採用費馬小定理
    {
        for(int i=1;i<=r-2;i++)
            rs*=a,rs%=r;
    }else //r不是素數,採用歐拉定理的推論
    {
        int k=Euler(r)-1;
        for(int i=1;i<=k;i++)
            rs*=a,rs%=r;
    }
    return rs;
}
int get_pk(int w)
{
    int pk=2;
    for(pk=2;pk<w;pk++)
    {
        if(gcd(w,pk)==1)
            return pk;
    }
    return pk;
}
int square_multiplication(int x,int c,int r)//平方乘算法,x的c次方%r
{
    string str="";
    while(c)
    {
        str=(char)(c%2+'0')+str;
        c/=2;
    }
    int rs=x;
    int l=str.length();
    for(int i=1;i<l;i++)
    {
        if(str[i]=='0')
            rs=((rs%r)*(rs%r))%r;
        else
            rs=(((rs%r)*(rs%r))%r*x)%r;
    }
    return rs;
}
int main()
{
    int p=47;
    int q=61;

    int r=p*q;//公開模數
    cout<<"r="<<r<<endl;

    int w=Euler(r);//1到r中與r互質的數的個數

    //求得公鑰
    int pk=get_pk(w);
    //pk=167;
    cout<<"公鑰(pk,r):("<<pk<<","<<r<<")"<<endl;

    //求得私鑰
    int sk=multiplicative_inverse_element(pk,w);
    cout<<"私鑰(sk,r):("<<sk<<","<<r<<")"<<endl;

    int M=123456789;//明文
    int K=3;//K位一組

    int temp=1;
    for(int k=1;k<=K;k++)
        temp*=10;
    cout<<"密文:";
    for(int i=1;i<=K;i++)
    {
         cout<<square_multiplication(M%temp,pk,r)<<" ";
         M/=temp;
    }
    cout<<endl;

    return 0;
}
原文鏈接:https://blog.csdn.net/qq_39382769/article/details/88273253
//第三種方式
#include <iostream>
#include <cmath>
#include <cstring>
#include <ctime>
#include <cstdlib>
using namespace std;


int Plaintext[100];//明文
long long Ciphertext[100];//密文
int n, e = 0, d;

//二進制轉換
int BianaryTransform(int num, int bin_num[])
{

    int i = 0,  mod = 0;

    //轉換爲二進制,逆向暫存temp[]數組中
    while(num != 0)
    {
        mod = num%2;
        bin_num[i] = mod;
        num = num/2;
        i++;
    }

    //返回二進制數的位數
    return i;
}

//反覆平方求冪
long long Modular_Exonentiation(long long a, int b, int n)
{
    int c = 0, bin_num[1000];
    long long d = 1;
    int k = BianaryTransform(b, bin_num)-1;

    for(int i = k; i >= 0; i--)
    {
        c = 2*c;
        d = (d*d)%n;
        if(bin_num[i] == 1)
        {
            c = c + 1;
            d = (d*a)%n;
        }
    }
    return d;
}

//生成1000以內素數
int ProducePrimeNumber(int prime[])
{
    int c = 0, vis[1001];
    memset(vis, 0, sizeof(vis));
    for(int i = 2; i <= 1000; i++)if(!vis[i])
    {
        prime[c++] = i;
        for(int j = i*i; j <= 1000; j+=i)
            vis[j] = 1;
    }

    return c;
}


//歐幾里得擴展算法
int Exgcd(int m,int n,int &x)
{
    int x1,y1,x0,y0, y;
    x0=1; y0=0;
    x1=0; y1=1;
    x=0; y=1;
    int r=m%n;
    int q=(m-r)/n;
    while(r)
    {
        x=x0-q*x1; y=y0-q*y1;
        x0=x1; y0=y1;
        x1=x; y1=y;
        m=n; n=r; r=m%n;
        q=(m-r)/n;
    }
    return n;
}

//RSA初始化
void RSA_Initialize()
{
    //取出1000內素數保存在prime[]數組中
    int prime[5000];
    int count_Prime = ProducePrimeNumber(prime);

    //隨機取兩個素數p,q
    srand((unsigned)time(NULL));
    int ranNum1 = rand()%count_Prime;
    int ranNum2 = rand()%count_Prime;
    int p = prime[ranNum1], q = prime[ranNum2];

    n = p*q;

    int On = (p-1)*(q-1);


    //用歐幾里德擴展算法求e,d
    for(int j = 3; j < On; j+=1331)
    {
        int gcd = Exgcd(j, On, d);
        if( gcd == 1 && d > 0)
        {
            e = j;
            break;
        }

    }

}

//RSA加密
void RSA_Encrypt()
{
    cout<<"Public Key (e, n) : e = "<<e<<" n = "<<n<<'\n';
    cout<<"Private Key (d, n) : d = "<<d<<" n = "<<n<<'\n'<<'\n';

    int i = 0;
    for(i = 0; i < 100; i++)
        Ciphertext[i] = Modular_Exonentiation(Plaintext[i], e, n);

    cout<<"Use the public key (e, n) to encrypt:"<<'\n';
    for(i = 0; i < 100; i++)
        cout<<Ciphertext[i]<<" ";
    cout<<'\n'<<'\n';
}

//RSA解密
void RSA_Decrypt()
{
    int i = 0;
    for(i = 0; i < 100; i++)
        Ciphertext[i] = Modular_Exonentiation(Ciphertext[i], d, n);

    cout<<"Use private key (d, n) to decrypt:"<<'\n';
    for(i = 0; i < 100; i++)
        cout<<Ciphertext[i]<<" ";
    cout<<'\n'<<'\n';
}


//算法初始化
void Initialize()
{
    int i;
    srand((unsigned)time(NULL));
    for(i = 0; i < 100; i++)
        Plaintext[i] = rand()%1000;

    cout<<"Generate 100 random numbers:"<<'\n';
    for(i = 0; i < 100; i++)
        cout<<Plaintext[i]<<" ";
    cout<<'\n'<<'\n';
}

int main()
{
    Initialize();

    while(!e)
        RSA_Initialize();

    RSA_Encrypt();

    RSA_Decrypt();

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章