C语言实现rsa加密
0x00 RSA简介
RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
0x01 RSA原理
原文连接
这次轮到RSA加密算法了。RSA加密过程相对DES和MD5要简单很多,但作为现在还在使用的加密算法之一,它还是有需要认真思索的地方哒~
首先是密钥对的生成:
(1)选取两个大素数p和q(目前两个数的长度都接近512bit是安全的)
(2)计算乘积n=p*q,Φ(n)=(p-1)(q-1),其中Φ(n)为n的欧拉函数(因为两素数乘积的欧拉函数等于两数分别减一后的乘积)
(3)随机选取整数e(1<e<Φ(n))作为公钥d,要求满足e与Φ(n)的最大公约数为1,即两者互素
(4)用Euclid扩展算法计算私钥d,已满足d * e ≡ 1 (mod Φ(n)),即d ≡ e^(-1) (mod
Φ(n))。则e与n是公钥,d是私钥注意:e与n应公开,两个素数p和q不再需要,可销毁,但绝不可泄露。
加密过程:
将接收到的明文转换成特定的编码方式。如p=43,q=59,e=13,明文为cybergreatwall,按照英文字母表的顺序a=00,b=01,… ,z=25进行编码后为022401041706001922001111。
现在可以加密了~~ ci ≡ mi^e (mod n)
0x02 中国剩余定理(CRT)
(abc)%n = ((a%n)(b%n)(c%n))%n
使用该定理可有效避免数值溢出。
0x03 C语言代码实现
#include <stdio.h>
#include <string.h>
//最大公约数。
int gcd(int x,int y){
if(y)
return gcd(y, x%y);
else
return x;
}
//求e关于(p-1)(q-1)的逆元d:私钥
int extend(int e, int fhla){
for(int d=2; d<fhla; d++){ // 1<d<fhla
if(e*d%fhla==1){
return d;
}
}
}
//加密
int c[100]; //用于存储密文
int len;
void encrypt(int e, int n){
char plaintext[100];
printf("请输入明文:");
scanf("%s", plaintext);
len = strlen(plaintext);//获取输入的明文长度。
int ascll[len]; //ascll用于存储明文的ascll转换码
//将字母转换成ascll编码
for(int i=0; i<len; i++) {
ascll[i] = plaintext[i]; //将字母转换成数字
}
printf("\n") ;
printf("开始加密--------------------------------------\n");
int temp = 1;
for(int i=0; i<len; i++){
for(int j=0;j<e;j++){
temp = temp * ascll[i] %n; // 根据剩余定理 (a*b)%n = ((a%n)*(b%n))%n
}
c[i] = temp;
temp = 1;
}
printf("加密的密文为:");
for(int i=0;i<len;i++){
printf("%d",c[i]);
}
printf("\n加密结束--------------------------------------\n");
}
//解密函数
void decrypto(int d, int n) {
int de_plaintext[len];
int temp = 1;
char de_ascll[len];
for(int i=0; i<len; i++){
for(int j=0;j<d;j++){
temp = temp*c[i]%n;
}
de_plaintext[i] = temp;
temp = 1;
}
printf("解密开始--------------------------------------\n");
printf("解密后的符号明文为:");
for(int i=0;i<len;i++){
de_ascll[i] = de_plaintext[i];
printf("%c", de_ascll[i]);
}
printf("\n解密结束--------------------------------------\n");
}
int main(){
int p,q,e,d,n,flha;
p = 149;
q = 211;
n = p*q;
flha = (p-1)*(q-1);
if (gcd(p,q) == 1){
printf("p,q互质\n");
e = 12493;
if (gcd(e,flha) == 1){
printf("e 的选择符合要求\n");
d = extend(e,flha);
printf("公钥为:(e,n) = (%d,%d),请公开!\n",e,n);
printf("密钥为:(d,n) = (%d,%d),不能公开!\n",d,n);
printf("\n\n--------------------------------------\n");
encrypt(e,n);
printf("\n请输入正确的密钥,密钥正确将解密上面的密文:");scanf("%d",&d);
decrypto(d,n);
}else
printf("e 的选择不符合要求\n");
}else
printf("p,q不是质数!");
return 0;
}