RSA加密算法(轻量级版,轻松易懂)(C++实现)

RSA编码实现(简单版)

  • RSA编码
      • 1.判断素数 int IsPrime(int n)
      • 2.选取两个素数void InputPrime(int &p, int &q)
      • 3.计算n和n的欧拉函数 N(int p , int q, int &n,int &Euler_n)
      • 4.求两个数的最大公约数 Greatest Common Divisor (int a, int b)
      • 5.求e E(int Euler_n,int &e)
      • 6.求逆元d void D(int e,int Euler_n ,int &d)
      • 7.对明文m的加密 E_m(int m, int e,int n, int &c )
      • 8.对密文c的解密 D_c(int c, int d, int n, int& After_m)
    • Bob想要收到别人的消息就要先制作公钥和私钥
    • Alice发送密文给Bob
    • Bob解开密文
    • main()函数
  • 整体代码

这个是我学完RSA自己先写的流程版本,注重的是RSA加解密的过程
还有一个更全面的RSA版本的博文,在我的主页里能找到
缺点是
1 明文因该是ASCII形式,要有ASCII转int再转二进制,然后根据n来划分明文二进制串再转成int的过程,这里直接默认明文m是int 数组
2这里的素数p,q是int类型,未选取大素数,较大的素数应该用unsigned long long类型

RSA加密算法(轻量级版,轻松易懂)(C++实现)_第1张图片
RSA加密算法(轻量级版,轻松易懂)(C++实现)_第2张图片

RSA编码

1.判断素数 int IsPrime(int n)

 ·n是素数返回1
 ·n不是素数返回0
//判断素数
 int IsPrime(int n)
{
	 int temp = (int)sqrt(n);
	for (int i = 2; i <= temp; i++)
	{
		if (n % i == 0) return 0;//n不是素数的话返回0
	}
	return 1;//n是素数的话返回1
}

2.选取两个素数void InputPrime(int &p, int &q)

两个素数p,q是手动输入的。
p,q应满足:p为素数,q为素数,p,q互不相等
存在的问题:用do{ }while(); if()else; while(){}都写了这一判断和循环。但是不能避免下面的输入情况:
第一次输入 “12 13”,可以判断出12不等于13,12不是素数;
第二次乃至无穷次输入 “12 13”都可以判断出12 不是素数;
但是当突然输入 13 13时,判断不出两数不能相等。
以上情况是因为三个判断条件“p不等于q”,“p为素数”,“q为素数”的排列是有先后顺序的,而不是并行的。
可能的解决办法:可以用递归来避免(这个方法我没试过,感觉可以),或者用巧妙的if,while,do while的相互嵌套来改正,要是哪位大佬有办法可以在下面留言告诉我一下。

//选取两个素数
void InputPrime(int &p, int &q)
{
	int P, Q;
	cout << "请输入两个不相等的大素数: p,q" << endl;
	cin >> P >> Q;
	
	
		do
		{  
		/*if(P == Q)
			{
				cout << "p,q不能相等,请重新输入两个大素数: p, q" << endl;
				cin >> P >> Q;
			} 

			if(IsPrime(P) != 1)
			{
				cout << P<<"不满足是素数,请重新输入大素数: p" << endl;
				cin >> P;
			} 

			if(IsPrime(Q) != 1)
			{
				cout << Q<< "不满足是素数,请重新输入大素数: q" << endl;
				cin >> Q;
			} 
			*/
		
        /*	do 
			{
				cout << "p,q不能相等,请重新输入两个大素数: p, q" << endl;
				cin >> P >> Q;
			} while (P == Q);

			do 
			{
				cout << P << "不满足是素数,请重新输入大素数: p" << endl;
				cin >> P;
			} while (IsPrime(P) != 1);

			do 
			{
				cout << Q << "不满足是素数,请重新输入大素数: q" << endl;
				cin >> Q;
			} while (IsPrime(Q) != 1);
			*/

			while (IsPrime(Q) != 1)
			{
				cout << Q << "不满足是素数,请重新输入大素数: q" << endl;
				cin >> Q;
			}

			while (IsPrime(P) != 1)
			{
				cout << P << "不满足是素数,请重新输入大素数: p" << endl;
				cin >> P;
			}

			while(P==Q)
			{
				cout << "p,q不能相等,请重新输入两个大素数: p, q" << endl;
				cin >> P >> Q;	
			}


		} while (IsPrime(P) !=1||IsPrime(Q)!=1||Q==P);	
	
	p = P;
	q = Q;
	
}

3.计算n和n的欧拉函数 N(int p , int q, int &n,int &Euler_n)

//计算n和n的欧拉函数值
void N(int p , int q, int &n,int &Euler_n)
{
	n = p * q;
	Euler_n = (p - 1) * (q - 1);
}

4.求两个数的最大公约数 Greatest Common Divisor (int a, int b)

//求两个数的最大公约数
int GreatestCommonDivisor(int a, int b) 
{
	int t;
	if (a < b) 
	{
		// 交换两个数,使大数放在a的位置上。
		t = a;
		a = b;
		b = t;
	}
	while (b != 0)
	{
		// 利用辗转相除法,直到b为0为止。
		t = a % b;
		a = b;
		b = t;
	}
	return a;
}

5.求e E(int Euler_n,int &e)

//选取e
void E(int Euler_n,int &e)
{
	e = rand() % (Euler_n - 1) + 1; //e取值是1
	do  // gcd(e,Euler_n)=1  ,e与Euler_n互素,最大公约数=1
	{
	e = rand() % (Euler_n - 1) + 1; //e取值是1
	} while (GreatestCommonDivisor(Euler_n , e)!=1);//当e与Euler_n最大公约数!=1时,循环不断地刷新e的值
}

6.求逆元d void D(int e,int Euler_n ,int &d)

//求逆元d
void D(int e,int Euler_n ,int &d)
{
	int Sign_of_Inverse_Element=0;//判断是否求出逆元的标志:Sign_of_Inverse_Element。当Sign_of_Inverse_Element=1,则求出了逆元
	do
	{
		for (int i = 1; i <Euler_n; i++)
		{
			if ((i * e) % Euler_n == 1)
			{
				Sign_of_Inverse_Element = 1; //Sign_of_Inverse_Element=1时表面求出了逆元d
				d = i;
			}
		}
	} while (Sign_of_Inverse_Element !=1);

}

7.对明文m的加密 E_m(int m, int e,int n, int &c )

这里认为m是由输入字符(ASCII)转成的二进制(Binary)的十进制值

//对于明文m的加密   
void E_m(int m,  int e,int n, int &c  )
{
	   int product = 1;//product表示m自身不断相乘的积  
	   for (int i = 1; i <=e; ++i)//用e来控制m的指数
		{ product = (product *m)%n;   }//注意不要忘记%n  
	   c = product;
}

8.对密文c的解密 D_c(int c, int d, int n, int& After_m)

//对密文c的解密
void D_c(int c, int d, int n, int& After_m)
{
	int product = 1;//product表示c自身不断相乘的积
	for (int i = 1; i <= d; ++i)//用d来控制c的指数
	{product = (product * c) %n;}//注意不要忘记%n
	After_m= product;
}

Bob想要收到别人的消息就要先制作公钥和私钥

//Bob想要收到别人的消息就要先制作公钥和私钥
void Bob_Make_PublicKey_And_PrivateKey(int &p , int &q, int& n,  int& e,int& d)
{
	int p1, q1, n1, Euler_n1, e1, d1;
	//Bob制作公钥的过程
	InputPrime(p1, q1);//选取两个素数
	p = p1;
	q = q1;

	N(p1, q1, n1, Euler_n1); //计算n和  n的欧拉函数值Euler_n
	n = n1;

	E(Euler_n1, e1);//选取e
	e = e1;
    cout << "Bob  (广播发送): “想给我发消息用这个公钥:{ e=" << e1 << ", n=" << n1 << "} ”" << endl;
	
	//Bob制作公钥的过程
	D(e1, Euler_n1, d1);//求逆元d
	d = d1;
	cout << "Bob  (自言自语): “只有我自己知道这个私钥:{ d=" << d1 << ", n=" << n1 << "} ”" << endl<<endl;
	
}

Alice发送密文给Bob

//Alice发送密文给Bob
void Alice_Send_Ciphertext_to_Bob(int n, int e, int C[])//全局变量C[]
{
	int M2[Size], C2[Size];
	//Alice对明文M[]加密
	cout << "Alice(自言自语):“我要发送给Bob的明文:";
	for (int i = 0; i < Size; i++)
	{
		M2[i] = rand() % n;//为了简要输入输出,这里就随机生成明文串的值
		E_m(M2[i], e, n, C2[i]);//加密
		C[i] = C2[i];
		cout << M2[i] << "  ";
		if (i == Size - 1) { cout <<" ”"<< endl; }
	}
	//Alice发送密文给Bob
	cout << "Alice(信道发送):“我要发送给Bob的密文:";
	for (int i = 0; i < Size; i++)
	{
		cout << C[i] << "  ";
		if (i == Size - 1) { cout << " ”" << endl<<endl; }
	}
}

Bob解开密文

//Bob解开密文
void Bob_Decode_Ciphertext_From_Alice( int n,  int d,int C[])////全局变量C[]
{	
	
	int  After_M3[Size];
	//Bob收到的密文
	cout << "Bob  (信道接收):  “Alice给我的密文:   ";
	for (int i = 0; i < Size; i++)
	{
		cout << C[i] << "  ";
		if (i == Size - 1) { cout << " ”" << endl; }
	}

	//Bob解密后得到的明文
	cout << "Bob  (自言自语):  “解 密后的明文为:   ";
	for (int i = 0; i < Size; i++)
	{
		D_c(C[i], d, n, After_M3[i]);
		cout << After_M3[i] << "  ";
		if (i == Size - 1) { cout <<" ”"<< endl; }
	}
}

main()函数

前面这么多函数就是为了main()简洁啊!!!!

int main()
{
	int p, q ;
	int d;

    //攻击者只知道下面这些全局变量。这些全局变量是在广播或者信道中传播的
	int n, e;//公钥
	int C[Size];//密文串

	Bob_Make_PublicKey_And_PrivateKey(p, q, n, e, d);
	Alice_Send_Ciphertext_to_Bob(n, e, C);
	Bob_Decode_Ciphertext_From_Alice(n, d, C);

}

//这个main()函数也能运行,是一开始的版本,变量繁琐且不能体现Alice和Bob的交流过程中主要的变量
/*
int main()
{
	int p, q,n, Euler_n,e,d;
	int M[Size];//明文串
	int C[Size];//密文串
	int After_M[Size]; //解密后的明文
	
	InputPrime( p,  q);//选取两个素数
	N(p, q, n, Euler_n); //计算n和  n的欧拉函数值->Euler_n
	E(Euler_n,  e);//选取e
	D(e, Euler_n, d);//求逆元d

	//生成明文并加密
	cout << "明文为:";
	for (int i = 0; i < Size; i++)
	{
		M[i] = rand() % n;//为了简要输入输出,这里就随机生成明文串的值
		E_m(M[i], e, n, C[i]);//加密
		cout <

整体代码

#include
using namespace std;
#define Size 10//明文串大小

//判断素数
 int IsPrime(int n)
{
	 int temp = (int)sqrt(n);
	for (int i = 2; i <= temp; i++)
	{
		if (n % i == 0) return 0;//n不是素数的话返回0
	}
	return 1;//n是素数的话返回1
}

//选取两个素数
void InputPrime(int &p, int &q)
{
	int P, Q;
	cout << "请输入两个不相等的大素数: p,q" << endl;
	cin >> P >> Q;
	
	
		do
		{  
		/*if(P == Q)
			{
				cout << "p,q不能相等,请重新输入两个大素数: p, q" << endl;
				cin >> P >> Q;
			} 

			if(IsPrime(P) != 1)
			{
				cout << P<<"不满足是素数,请重新输入大素数: p" << endl;
				cin >> P;
			} 

			if(IsPrime(Q) != 1)
			{
				cout << Q<< "不满足是素数,请重新输入大素数: q" << endl;
				cin >> Q;
			} 
			*/
		/*	do 
			{
				cout << "p,q不能相等,请重新输入两个大素数: p, q" << endl;
				cin >> P >> Q;
			} while (P == Q);

			do 
			{
				cout << P << "不满足是素数,请重新输入大素数: p" << endl;
				cin >> P;
			} while (IsPrime(P) != 1);

			do 
			{
				cout << Q << "不满足是素数,请重新输入大素数: q" << endl;
				cin >> Q;
			} while (IsPrime(Q) != 1);
			*/

			while (IsPrime(Q) != 1)
			{
				cout << Q << "不满足是素数,请重新输入大素数: q" << endl;
				cin >> Q;
			}

			while (IsPrime(P) != 1)
			{
				cout << P << "不满足是素数,请重新输入大素数: p" << endl;
				cin >> P;
			}

			while(P==Q)
			{
				cout << "p,q不能相等,请重新输入两个大素数: p, q" << endl;
				cin >> P >> Q;	
			}


		} while (IsPrime(P) !=1||IsPrime(Q)!=1||Q==P);	
	
	p = P;
	q = Q;
	
}

//计算n和n的欧拉函数值
void N(int p , int q, int &n,int &Euler_n)
{
	n = p * q;
	Euler_n = (p - 1) * (q - 1);
}

//求两个数的最大公约数
int GreatestCommonDivisor(int a, int b) 
{
	int t;
	if (a < b) 
	{
		// 交换两个数,使大数放在a的位置上。
		t = a;
		a = b;
		b = t;
	}
	while (b != 0)
	{
		// 利用辗转相除法,直到b为0为止。
		t = a % b;
		a = b;
		b = t;
	}
	return a;
}

//选取e
void E(int Euler_n,int &e)
{
	e = rand() % (Euler_n - 1) + 1; //e取值是1
	do  // gcd(e,Euler_n)=1  ,e与Euler_n互素,最大公约数=1
	{
	e = rand() % (Euler_n - 1) + 1; //e取值是1
	} while (GreatestCommonDivisor(Euler_n , e)!=1);//当e与Euler_n最大公约数!=1时,循环不断地刷新e的值
}

//求逆元d
void D(int e,int Euler_n ,int &d)
{
	int Sign_of_Inverse_Element=0;//判断是否求出逆元的标志:Sign_of_Inverse_Element。当Sign_of_Inverse_Element=1,则求出了逆元
	do
	{
		for (int i = 1; i <Euler_n; i++)
		{
			if ((i * e) % Euler_n == 1)
			{
				Sign_of_Inverse_Element = 1; //Sign_of_Inverse_Element=1时表面求出了逆元d
				d = i;
			}
		}
	} while (Sign_of_Inverse_Element !=1);

}

//对于明文m的加密   (这里认为m是由输入字符转成的二进制的十进制值)
void E_m(int m,  int e,int n, int &c  )
{
	   int product = 1;//product表示m自身不断相乘的积  
	   for (int i = 1; i <=e; ++i)//用e来控制m的指数
		{ product = (product *m)%n;   }//注意不要忘记%n  
	   c = product;
}

//对密文c的解密
void D_c(int c, int d, int n, int& After_m)
{
	int product = 1;//product表示c自身不断相乘的积
	for (int i = 1; i <= d; ++i)//用d来控制c的指数
	{product = (product * c) %n;}//注意不要忘记%n
	After_m= product;
}



//Bob想要收到别人的消息就要先制作公钥和私钥
void Bob_Make_PublicKey_And_PrivateKey(int &p , int &q, int& n,  int& e,int& d)
{
	int p1, q1, n1, Euler_n1, e1, d1;
	//Bob制作公钥的过程
	InputPrime(p1, q1);//选取两个素数
	p = p1;
	q = q1;

	N(p1, q1, n1, Euler_n1); //计算n和  n的欧拉函数值Euler_n
	n = n1;

	E(Euler_n1, e1);//选取e
	e = e1;
    cout << "Bob  (广播发送): “想给我发消息用这个公钥:{ e=" << e1 << ", n=" << n1 << "} ”" << endl;
	
	//Bob制作公钥的过程
	D(e1, Euler_n1, d1);//求逆元d
	d = d1;
	cout << "Bob  (自言自语): “只有我自己知道这个私钥:{ d=" << d1 << ", n=" << n1 << "} ”" << endl<<endl;
	
}

//Alice发送密文给Bob
void Alice_Send_Ciphertext_to_Bob(int n, int e, int C[])//全局变量C[]
{
	int M2[Size], C2[Size];
	//Alice对明文M[]加密
	cout << "Alice(自言自语):“我要发送给Bob的明文:";
	for (int i = 0; i < Size; i++)
	{
		M2[i] = rand() % n;//为了简要输入输出,这里就随机生成明文串的值
		E_m(M2[i], e, n, C2[i]);//加密
		C[i] = C2[i];
		cout << M2[i] << "  ";
		if (i == Size - 1) { cout <<" ”"<< endl; }
	}
	//Alice发送密文给Bob
	cout << "Alice(信道发送):“我要发送给Bob的密文:";
	for (int i = 0; i < Size; i++)
	{
		cout << C[i] << "  ";
		if (i == Size - 1) { cout << " ”" << endl<<endl; }
	}
}

//Bob解开密文
void Bob_Decode_Ciphertext_From_Alice( int n,  int d,int C[])////全局变量C[]
{	
	
	int  After_M3[Size];
	//Bob收到的密文
	cout << "Bob  (信道接收):  “Alice给我的密文:   ";
	for (int i = 0; i < Size; i++)
	{
		cout << C[i] << "  ";
		if (i == Size - 1) { cout << " ”" << endl; }
	}

	//Bob解密后得到的明文
	cout << "Bob  (自言自语):  “解 密后的明文为:   ";
	for (int i = 0; i < Size; i++)
	{
		D_c(C[i], d, n, After_M3[i]);
		cout << After_M3[i] << "  ";
		if (i == Size - 1) { cout <<" ”"<< endl; }
	}
}


int main()
{
	int p, q ;
	int d;

    //攻击者只知道下面这些全局变量。这些全局变量是在广播或者信道中传播的
	int n, e;//公钥
	int C[Size];//密文串

	Bob_Make_PublicKey_And_PrivateKey(p, q, n, e, d);
	Alice_Send_Ciphertext_to_Bob(n, e, C);
	Bob_Decode_Ciphertext_From_Alice(n, d, C);

}

//这个main()函数也能运行,是一开始的版本,繁琐且不能体现Alice和Bob的交流过程
/*
int main()
{
	int p, q,n, Euler_n,e,d;
	int M[Size];//明文串
	int C[Size];//密文串
	int After_M[Size]; //解密后的明文
	
	InputPrime( p,  q);//选取两个素数
	N(p, q, n, Euler_n); //计算n和  n的欧拉函数值->Euler_n
	E(Euler_n,  e);//选取e
	D(e, Euler_n, d);//求逆元d

	//生成明文并加密
	cout << "明文为:";
	for (int i = 0; i < Size; i++)
	{
		M[i] = rand() % n;//为了简要输入输出,这里就随机生成明文串的值
		E_m(M[i], e, n, C[i]);//加密
		cout <


你可能感兴趣的:(RSA,C++实现,c++,rsa)