C++实现RSA加j解密算法(含源码和运行结果)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、算法

实验目标:实现RSA加密算法,根据已知明文计算出RSA的加密密文,并解密。
实验算法:
1、 选择一对不同的、足够大的素数p,q。
2、 计算n=pq。
3、 计算Euler(n)=(p-1)(q-1),同时对p, q严加保密,不让任何人知道。
4、 找一个与Euler(n)互质的数e,且1<e<Euler(n)。
5、 计算d,使得de≡1 mod f(n)。这个公式也可以表达为d ≡e-1 mod f(n)
*这里要解释一下,≡是数论中表示同余的符号。公式中,≡符号的左边必须和符号右边同余,也就是两边模运算结果相同。显而易见, 不管f(n)取什么值,符号右边1 mod f(n)的结果都等于1;符号的左边d与e的乘积做模运算后的结果也必须等于1。这就需要计算出d的值,让这个同余等式能够成立。*本实验采用平方乘算法。
6、 公钥KU=(e,n),私钥KR=(d,n)。
7、 加密时,先将明文变换成0至n-1的一个整数M。若明文较长,可先分割成适当的组,然后再进行交换。

二、源码

1.加密

#include<bits/stdc++.h>
#include <iostream> 
#include <stdlib.h>
#include <time.h>
#include <math.h>
//#include <cstddef.h>
using namespace std; 


/*使用三个rand()生成伪随机数组合生成一个奇数随机数,作为伪素数 
**系统时间为种子 
**并返回生成的这个大奇数 
*/ 
unsigned int ProduceRandomOdd(){//UINT无符号整形,各伪随机数放在RandomArray数组中 
    time_t t;//c++时间类型 
    unsigned int RandomNumber;//记录随机数 
	do{
		srand((unsigned)time(&t));//srand(seed)用于给rand()函数设定种子,此处用系统时间
		//生成 
        RandomNumber=(rand()<<3); 
        cout<<RandomNumber<<endl;
	}while(RandomNumber%2==0||RandomNumber<100000000); 
	//返回   
	return RandomNumber;
}

//模重复平方算法求(b^n)%m
size_t repeatMod(size_t base, size_t n, size_t mod){
    size_t a = 1;
    while(n){
        if(n&1){
            a=(a*base)%mod;
        }
        base=(base*base)%mod;
        n=n>>1;
    }
    return a;
}

//Miller-Rabin素数检测
bool rabinmiller(size_t n, size_t k){
	
    int s=0;
    int temp=n-1;    
	
	//将n-1表示为(2^s)*t  
    while ((temp&0x1)==0&&temp){
        temp=temp>>1;
        s++;
    }   
    size_t t = temp;
    
	//判断k轮误判概率不大于(1/4)^k
    while(k--){
        srand((unsigned)time(0));
        size_t b = rand()%(n-2)+2; //生成一个b(2≤a ≤n-2)

        size_t y = repeatMod(b,t,n); 
        if (y == 1 || y == (n-1))
            return true;
        for(int j = 1; j<=(s-1) && y != (n-1); ++j){
            y = repeatMod(y,2,n);
            if (y == 1)
                return false;
        }
        if (y != (n-1))
            return false;
    }
    return true;
}


unsigned int Euler(unsigned int n)//欧拉函数 求1到n中有多少个整数与n互质
{
    unsigned int rs=1;
    for(unsigned 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;
}
unsigned int gcd(unsigned int a,unsigned int b)//求a,b的最大公约数
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}
unsigned int check(unsigned 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;
}
unsigned int gnerating_primes(unsigned int n)//产生小于等于n的第一个素数
{
    if(n%2==0)
        n--;
    for(unsigned int i=n;i>1;i=i-2)
    {
        if(check(i)==1)
            return i;
    }
    return -1;//表示没有小于等于n的素数
}
unsigned int multiplicative_inverse_element(unsigned int a,unsigned int r)//求a对于r的乘法逆元
{
    unsigned int rs=1;
    if(check(r)==1)//r是素数 采用费马小定理
    {
        for(unsigned int i=1;i<=r-2;i++)
            rs*=a,rs%=r;
    }else //r不是素数,采用欧拉定理的推论
    {
        unsigned int k=Euler(r)-1;
        for(unsigned int i=1;i<=k;i++)
            rs*=a,rs%=r;
    }
    return rs;
}
unsigned int get_pk(int w)
{
    unsigned int pk=2;
    for(pk=2;pk<w;pk++)
    {
        if(gcd(w,pk)==1)
            return pk;
    }
    return pk;
}
unsigned int square_multiplication(unsigned int x,unsigned int c,unsigned int r)//平方乘算法,x的c次方%r
{
    string str="";
    while(c)
    {
        str=(char)(c%2+'0')+str;
        c/=2;
    }
    unsigned int rs=x;
    unsigned int l=str.length();
    for(unsigned 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()
{
	size_t k=20;//进行20轮测试 
	unsigned int RandomOdd_1; 
	unsigned int RandomOdd_2;
	bool flag_1;
	bool flag_2;
	//直至找到过关的伪素数 
	do{
		RandomOdd_1=ProduceRandomOdd();
		//cout<<RandomOdd<<endl;
		flag_1=rabinmiller(RandomOdd_1,k);
	}while(flag_1==false);
	
	//cout<<"=========================="<<endl;
	cout<<"生成的第一个大素数为:" <<RandomOdd_1;
	
	do{
		RandomOdd_2=ProduceRandomOdd();
		//cout<<RandomOdd<<endl;
		flag_2=rabinmiller(RandomOdd_2,k);
	}while(flag_2==false||RandomOdd_2==RandomOdd_1);
	
	//cout<<"=========================="<<endl;
	cout<<"生成的第二个大素数为:" <<RandomOdd_2;
	
	
    int p=RandomOdd_1;
    int q=RandomOdd_2;
	
    unsigned int r=p*q;//公开模数
    cout<<"r="<<r<<endl;

    unsigned int w=Euler(r);//1到r中与r互质的数的个数

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

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

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

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

    return 0;
}

2.解密

#include<bits/stdc++.h>
using namespace std;
unsigned int Euler(unsigned int n)//欧拉函数 求1到n中有多少个整数与n互质
{
    unsigned int rs=1;
    for(unsigned 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;
}
unsigned int gcd(unsigned int a,unsigned int b)//求a,b的最大公约数
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}
unsigned int check(unsigned 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;
}
unsigned int gnerating_primes(unsigned int n)//产生小于等于n的第一个素数
{
    if(n%2==0)
        n--;
    for(unsigned int i=n;i>1;i=i-2)
    {
        if(check(i)==1)
            return i;
    }
    return -1;//表示没有小于等于n的素数
}
unsigned int multiplicative_inverse_element(unsigned int a,unsigned int r)//求a对于r的乘法逆元
{
    unsigned int rs=1;
    if(check(r)==1)//r是素数 采用费马小定理
    {
        for(unsigned int i=1;i<=r-2;i++)
            rs*=a,rs%=r;
    }else //r不是素数,采用欧拉定理的推论
    {
        unsigned int k=Euler(r)-1;
        for(unsigned int i=1;i<=k;i++)
            rs*=a,rs%=r;
    }
    return rs;
}
unsigned int get_pk(int w)
{
    unsigned int pk=2;
    for(pk=2;pk<w;pk++)
    {
        if(gcd(w,pk)==1)
            return pk;
    }
    return pk;
}
unsigned int square_multiplication(unsigned int x,unsigned int c,unsigned int r)//平方乘算法,x的c次方%r
{
    string str="";
    while(c)
    {
        str=(char)(c%2+'0')+str;
        c/=2;
    }
    unsigned int rs=x;
    unsigned int l=str.length();
    for(unsigned 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()
{
    unsigned int p=991;
    unsigned int q=997;
    
    cout<<"生成的第一个大素数为:" <<p<<endl;
	cout<<"生成的第二个大素数为:" <<q<<endl;
	
    unsigned int r=p*q;//公开模数
    cout<<"r="<<r<<endl;

    unsigned int w=Euler(r);//1到r中与r互质的数的个数

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

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

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

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

    cout<<"解密得到的明文:"<<M<<endl;
    return 0;
}

}

三、运行结果

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值