若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;
}
来源:CSDN
作者:季一
链接:https://blog.csdn.net/GD_ONE/article/details/103464093