RSA算法加解密其实就是两个公式和四个概念,即:互质(素)、欧拉函数、欧拉定理、模反元素(逆元)。这写公式和概念这里不做介绍,详细戳这里:https://blog.csdn.net/weixin_30399871/article/details/98251483
1.明文和密文在 0-n-1 之间,n 是一个正整数
2.分组大小为 k,2k < n ≤ 2k+1
3.选择两个大素数 p 和 q
4.计算乘积 n = pq 和φ(n) = (p-1)(q-1)
5.选择 e,e 大于 1 且小于φ(n),使得 gcd(e, φ(n)) = 1
6.计算 d,满足 **de ≡ 1 mod φ(n) **
7.对每个密钥 k = (n,p,q,d,e),以{e,n}为公开密钥,{d,n}为私有密钥,由于 n = pq,故也可认为{e,p,q}为公开密钥,{d,p,q}为私有密钥,或{e}为公开密钥,{d}为私密钥。
8.加密算法:C = Ek(M) = M^e mod n
9.解密算法:M = Dk© = C^d mod n
10.C:密文 M:明文 E:加密 D:解密
#include
#include
#include
#include
int prime(unsigned long long int a); //素数判断
int gcd(unsigned long long int a, unsigned long long int b);//递归
int rsa(unsigned long long int a, unsigned long long int b, unsigned long long int c); //rsa(e,m,n) rsa(d,c,n)
int qiud(unsigned long long int a, unsigned long long int b);//求d
//unsigned long long int a 解决数值过大问题
int olg(unsigned long long int e, unsigned long long int h); //辗转相除法求d函数
int main() {
int p, q, e, m, a, h, c, n, d; //h:Eular函数
do {
printf("\n");
printf("***************************************************\n");
printf("****************RSA实验****************************\n");
printf("* 1:密码加密 *\n");
printf("* 2:密码解密 *\n");
printf("* 3:退出 *\n");
printf("***************************************************\n");
printf("请输入功能键(1~3):");
scanf_s("%d", &a);
switch (a) {
case 1:
printf("*************RSA密码加密***************************\n");
printf("请输入素数p:");
scanf_s("%ld", &p);
while (prime(p) == 1) {
printf("您输入的数不是素数!请重新输入p:");
scanf_s("%ld", &p);
}
printf("请输入素数q:");
scanf_s("%ld", &q);
while (prime(q) == 1) {//此处用while代替if,if重新输入会导致程序中断
printf("您输入的数不是素数!请重新输入q:");
scanf_s("%ld", &q);
}
n = p * q; //计算n
h = (p - 1) * (q - 1); // 计算Eular函数值φ(n)
printf("请输入e:");
scanf_s("%ld", &e);
while (e<1 || e>h || gcd(e, h) != 1) {
printf("e值输入错误,请重新输入:");
scanf_s("%ld", &e);
}
d = qiud(e, h); // 计算d的值
printf("==================================================\n");
printf("计算得n为:%ld\n", n);
printf("计算得φ(n)为:%ld\n", h);
printf("计算得e为:%ld\n", e);
printf("计算得d为:%ld\n", d);
printf("==================================================\n");
printf("请输入要加密的明文(一个整数):");
scanf_s("%ld", &m)
c = rsa(e, m, n);
printf("加密后的密文C为:%ld", c);
break;
case 2:
printf("*************RSA密码解密***************************\n");
printf("请输入素数p:");
scanf_s("%ld", &p);
while (prime(p) == 1) {
printf("您输入的数不是素数!请重新输入p:");
scanf_s("%ld", &p);
}
printf("请输入素数q:");
scanf_s("%ld", &q);
while (prime(q) == 1) {
printf("您输入的数不是素数!请重新输入q:");
scanf_s("%ld", &q);
}
n = p * q; //计算n
h = (p - 1) * (q - 1); // 计算Eular函数值φ(n)
printf("请输入e:");
scanf_s("%ld", &e);
while (e<1 || e>h || (gcd(e, h) != 1)) {
printf("e值输入错误,请重新输入:");
scanf_s("%ld", &e);
}
//d = qiud(e, h); // 计算d的值,两种算法都可以,自选
d = olg(e, h); //这里改用欧几里得算法求d
printf("==================================================\n");
printf("计算得n为:%ld\n", n);
printf("计算得φ(n)为:%ld\n", h);
printf("计算得e为:%ld\n", e);
printf("计算得d为:%ld\n", d);
printf("==================================================\n");
printf("请输入要解密的密文(一个整数):");
scanf_s("%d", &c)
m = rsa(d, c, n);
printf("解密后的明文m为:%ld", m);
break;
case 3:
exit(0);
default:
printf("功能键输入错误!\n");
}
} while (a != 0);
}
//素(质)数判断:
int prime(unsigned long long int a) {
unsigned long long int i = 2;
if (a == 1) {
return 1;
}
else{
for (i = 2; i < sqrt(a); i++) { //改用平方根函数做
if (a % i == 0)
return 1; // 整除,即不是素数,返回1
}
}
}
//求最大公因数:
int gcd(unsigned long long int a, unsigned long long int b) {
return b != 0 ? gcd(b, a % b) : a;
}
//欧几里得算法求d:(提供两种算法求d,下面还有qiud()函数)
int olg(unsigned long long int e, unsigned long long int h) //h=e*a[0]+r[0] 辗转相除法
{
int i;
int k=1;//计算商的个数
unsigned long long int d;
unsigned long long int a[50] = { 0 }, r[50] = { 0 }, b[50] = { 0 };//a 商 r 余
a[0] = h/e; //取第一个商
r[0] = h%e; //取第一个余数
a[1] = e/r[0];//取第二个商
r[1] = e%r[0];//取第二个余数
for (i=2;;i++)
{
a[i]=r[i-2]/r[i-1];
r[i]=r[i-2]%r[i-1];
if(r[i]==0)
break;
k++;
}
b[0] = a[k];
b[1] = b[0]*a[k-1]+1;
for (i = 2; i <= k; i++)
{
b[i] = a[k-i] * b[i-1] + b[i-2];
}
if ((k-1)%2!=0) // 计算商的时候最后一个余数为零的商除去
d = h-b[k]; //当K-1为奇数时
if ((k-1)%2==0)
d = b[k]; //当k-1为偶数时
return d;
}
//利用i循环自增满足 ab mod φ(n) = 1 的条件得到d
int qiud(unsigned long long int a, unsigned long long int b) {
unsigned long long int i = 1;
for (; ((a * i) % b) != 1;) { // ab mod φ(n) = 1
i++;
}
return i;
}
//RSA函数:
int rsa(unsigned long long int a, unsigned long long int b, unsigned long long int c) {
unsigned long long int i = 1;
while (a != 0) {
i = i * b;
i = i % c;
a--; //*一次 %一次
}
return i;
}
2019-10-6
by 久违