本文原为 山东大学计算机系统原理实验二 的实现开源
鉴于计算机系统原理这个实验评分以加密算法难度为准,而加密算法显然不是计算机系统原理的重点,故开源我的实现以供其他同学参考。
实现分为两个源文件,keygen和cry,keygen负责生成密钥,cry负责加密解密。文末附完整代码。
keygen.c main部分
rsa算法原理不再阐述,它的密钥生成需要两个大素数p和q,以及一个与m互素的e,p,q越大安全性越高,这里附带一组p,q,e,可以改为输入形式,自己寻找大素数输入。
c语言实现高精度不好用(不引用第三方库),所以此处牺牲部分安全性换取高得多的编码便捷度。__int128范围达到1.7e38,38位精度勉强能当半个高精度用,注意部分编译器或机器不支持__int128,可以改为long long,然后减小p,q。
输出中(e,n)为公钥,(d,n)为私钥,是一对,公钥加密能且仅能以私钥解密,反之亦然。(一般的用法是公开公钥,其他人使用公钥加密文件发送,然后你收到后使用私钥解密)
int main()
{
__int128 p = 179424673, q = 3262476787;
//__int128 p = read(), q = read();
__int128 n = p * q;
__int128 m = (p - 1) * (q - 1);
__int128 e = 1628441;
//__int128 e = read();
if (gcd(e, m) != 1)
{
printf("e is not coprime with m\n");
return 0;
}
__int128 d;
__int128 y;
exgcd(e, m, d, y);
d = (d % m + m) % m;
printf("n= ");
print(n);
printf("\n");
printf("e= ");
print(e);
printf("\n");
printf("d= ");
print(d);
return 0;
}
cry.c main部分
同keygen,使用__int128代替高精度。
首先输入操作数,1加密2解密,然后要加(解)密的文件(注意附带后缀),以及密钥(e,n)或(d,n)
注意要解密的文件务必以.rsa为后缀,否则会删除后面四个字符(自行修改)
加密实现原理是把要加密的文件逐字节读取(char正好是一字节),然后逐字节加密,把每个字节加密为一段数字密文,输出到加密文件中,两字节间有空格方便解密时一个个密文读取。
解密就是把每个密文解密为一个字节然后输出到文件中。
int main()
{
printf("input as following:\n1(encry) filename e n\n2(decry) filename d n\n");
int ope;
scanf("%d", &ope);
char s[1000];
scanf("%s", s);
if (ope == 1)
{
__int128 e = read(), n = read();
FILE *fp1 = freopen(s, "r", stdin);
strcat(s, ".rsa");
FILE *fp2 = freopen(s, "w", stdout);
char c = getchar();
while (c != EOF)
{
__int128 x = c;
print(qpow(x, e, n));
putchar(' ');
c = getchar();
}
fclose(fp1);
fclose(fp2);
}
else
{
__int128 d = read(), n = read();
FILE *fp1 = freopen(s, "r", stdin);
s[strlen(s) - 4] = '\0';
FILE *fp2 = freopen(s, "w", stdout);
__int128 x;
while (x = read())
printf("%c", (char)qpow(x, d, n));
fclose(fp1);
fclose(fp2);
}
return 0;
}
完整文件
cry.c
#include <stdio.h>
#include <string.h>
inline __int128 read()
{
__int128 x = 0, f = 1;
char ch;
if ((ch = getchar()) == EOF)
return 0;
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
__int128 qpow(__int128 a, __int128 b, __int128 mod)
{
__int128 ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int main()
{
printf("input as following:\n1(encry) filename e n\n2(decry) filename d n\n");
int ope;
scanf("%d", &ope);
char s[1000];
scanf("%s", s);
if (ope == 1)
{
__int128 e = read(), n = read();
FILE *fp1 = freopen(s, "r", stdin);
strcat(s, ".rsa");
FILE *fp2 = freopen(s, "w", stdout);
char c = getchar();
while (c != EOF)
{
__int128 x = c;
print(qpow(x, e, n));
putchar(' ');
c = getchar();
}
fclose(fp1);
fclose(fp2);
}
else
{
__int128 d = read(), n = read();
FILE *fp1 = freopen(s, "r", stdin);
s[strlen(s) - 4] = '\0';
FILE *fp2 = freopen(s, "w", stdout);
__int128 x;
while (x = read())
printf("%c", (char)qpow(x, d, n));
fclose(fp1);
fclose(fp2);
}
return 0;
}
keygen.c
#include <stdio.h>
#include <string.h>
inline __int128 read()
{
__int128 x = 0, f = 1;
char ch;
if ((ch = getchar()) == EOF)
return 0;
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
__int128 qpow(__int128 a, __int128 b, __int128 mod)
{
__int128 ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
__int128 exgcd(__int128 a, __int128 b, __int128 &x, __int128 &y)
{
if (!b)
{
x = 1;
y = 0;
return a;
}
__int128 d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
__int128 gcd(__int128 a, __int128 b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
__int128 p = 179424673, q = 3262476787;
//__int128 p = read(), q = read();
__int128 n = p * q;
__int128 m = (p - 1) * (q - 1);
__int128 e = 1628441;
//__int128 e = read();
if (gcd(e, m) != 1)
{
printf("e is not coprime with m\n");
return 0;
}
__int128 d;
__int128 y;
exgcd(e, m, d, y);
d = (d % m + m) % m;
printf("n= ");
print(n);
printf("\n");
printf("e= ");
print(e);
printf("\n");
printf("d= ");
print(d);
return 0;
}