欧拉函数的应用-RSA加密算法

余生长醉 提交于 2019-12-10 07:16:24

若p和q互质,令n = p*q 则ola(n) = (p-1)*(q-1)

我们知道p和q的值能轻易知道(p-1)*(q-1)的值也就是ola函数的值,但是仅仅知道n是多少,却非常难得到p和q是多少,因为当n很大时,例如有几百位时,它就有非常多的质因数,要暴力穷举很长时间。所以这就保证了RSA加密算法的可靠性。

RSA加密是非对称加密,密钥 由公钥和私钥组成。

公式为:

(明文)^e % n = 密文           其中, e 是一个小于n且与n互质的数。 

(密文)^d % n = 明文                       d = ( 1 + k*ola(n) ) / e         (在此处, k和d都必须是正整数。)                                       

将明文的e次方对n取余后得到密文。

将密文的d次方对n取余后得到明文。

所以 加密用公钥(e, n)  解密用私钥(d, n)   你构造出一个密钥对之后,将公钥发给别人,别人通过公钥加密,在发送给你,你在用公钥解密,就完成了明文加密传输。

所以我们首先要构造两个质数p和q       则  n = p*q    ola(n) =(p-1)* (q-1)

然后随机构造一个小于n并且与n互质的数 e。

得到 e n ola(n) 之后 就剩下d了

d = ( 1 + k*ola(n) ) / e   因为d和k一定是正整数 所以我们可以从1开始枚举k,直到求出的d是一个正整数。

或者是将等式变化为    d*e  - k*ola(n) = 1   由扩展欧几里得求解d。

求出d后就可以对密文进行解密了。

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
typedef long long ll;
using namespace std;  
int e, d, n;
int gcd(int a, int b)
{
	if(b==0) return a;    // 当b等于0时, 结束递归。 
	else return gcd(b,a%b);  // 递归调用gcd(b, a%b) 
}

int exgcd(int a, int b, int& x, int& y){ // 扩展欧几里得 
	if(b==0){
		x = 1;
		y = 0;
		return a;
	}
	exgcd(b,a%b,y,x);
	y = y - a/b*x;
}
int PrimarityTest(int a, int i)  // 判断是不是质数 
{
	for(int j = a; j <= sqrt(i); j++){
		if(i%j==0)
			return 0;  //不是质数 
	}
	return 1;
}

int ModularExponention(int a, int m, int n) // 加密或者解密    
{
	int cipher = 1;         
	//快速幂 
	while(m){
		if(m&1){
			cipher = cipher * a % n;
		}
		m>>=1;
		a = a * a % n;
	} 
	return cipher%n;  
}

int ModularInverse(int a, int b)   //利用扩展欧几里得算法求解 d 
{     
	// d = (k*ola(n) + 1) / e
	// e*d - k*ola(n) = 1
	// 即 a*x - b*y = 1    贝祖等式 
	int x;
//	exgcd(b, a, x, y);
//	int t = a/gcd(a,b);
//	x = (x%t + t) % t;  //求最小整数解 
	for(int i = 1; ; i++){
		if((i*a + 1)%b==0){
			x = (i*a+1)/b;
			break;
		} 
	} 
	return x;
}


void KeyGeneration()  // 随机生成密钥 
{
	int p, q;
	int phi_n;

	do {
		do
			p = rand();
		while (p % 2 == 0);

	} while (!PrimarityTest(2, p));

	do {
		do
			q = rand();
		while (q % 2 == 0);
	} while (!PrimarityTest(2, q));

	n = p * q;  //两个质数     公钥  e n   私钥  d n    加密  明文^e mod n = 密文   
	phi_n = (p - 1) * (q - 1);     // n的欧拉函数值     解密  密文^d mod n = 明文 
	cout<<"n:  "<<n<<"   ola(n):    "<<phi_n<<endl; 
	do
		e = rand() % (phi_n - 2) + 2; // 1 < e < phi_n
	while (gcd(e, phi_n) != 1);  
	cout<<"e:   "<<e<<endl;  
	d = ModularInverse(phi_n, e);  //计算私钥中 d 的值   d = (k*ola(n)+1) / e 
	cout<<"d:   "<<d<<endl;
}

void Encryption(int value, FILE* out)  //加密函数 
{
	int cipher;
	cipher = ModularExponention(value, e, n);
	fprintf(out, "%d ", cipher);   //将密文写入out文件中。 每个密文以空格隔开。 
}

void Decryption(int value, FILE* out)  //解密函数 
{
	int decipher;
	decipher = ModularExponention(value, d, n);
	fprintf(out, "%c", decipher);
}

int main(void)
{
	FILE* inp, * out;
	char filepath[15], filename[100];
	KeyGeneration();  //生成密钥 
	inp = fopen("plain.txt", "r+"); //读写 
	if (inp == NULL) { //改文件不存在 
		printf("Error opening Source File.\n");
		exit(1);
	}

	out = fopen("cipher.txt", "w+");//写读 不存在创建 
	if (out == NULL) {
		printf("Error opening Destination File.\n");
		exit(1);
	}

	// encryption starts    
	while (1) {      // 加密过程,将密文输出到out文件中。 
		char ch = getc(inp);
		if (ch == -1)//到达结尾 
			break;
		int value = toascii(ch);  //得到ch的ASCII码 
		Encryption(value, out);  //调用加密函数 
	}

	fclose(inp);
	fclose(out);

	// decryption starts
	inp = fopen("cipher.txt", "r");  //读入密文 
	if (inp == NULL) {
		printf("Error opening Cipher Text.\n");
		exit(1);
	}

	out = fopen("decipher.txt", "w+");     //解密后存入decipher.txt 
	if (out == NULL) {
		printf("Error opening File.\n");
		exit(1);
	}

	while (1){
		int cip;
		if(fscanf(inp, "%d", &cip) == -1) 
			break;
		Decryption(cip, out); //解密 
	}
	fclose(out);

	return 0;
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!