C语言源代码RSA对任意长度的消息进行消息的分割及加密,并完成相关的解密
时间: 2024-01-21 22:17:18 浏览: 75
以下是C语言实现RSA对任意长度消息的分割、加密和解密的源代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// 求最大公因数
int gcd(int a, int b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
// 求模反元素
int modInverse(int a, int m)
{
int m0 = m, t, q;
int x0 = 0, x1 = 1;
if (m == 1)
return 0;
while (a > 1) {
q = a / m;
t = m;
m = a % m, a = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
if (x1 < 0)
x1 += m0;
return x1;
}
// 判断是否为质数
int isPrime(int num)
{
int i;
for (i = 2; i <= sqrt(num); i++) {
if (num % i == 0)
return 0;
}
return 1;
}
int main()
{
int p, q, e, d, n, phi_n, len;
char msg[1000], *enc_msg, *dec_msg;
int *msg_arr, *enc_arr, *dec_arr;
int i, j;
printf("请输入两个质数p和q:");
scanf("%d%d", &p, &q);
n = p * q;
phi_n = (p - 1) * (q - 1);
printf("n=%d, phi(n)=%d\n", n, phi_n);
while (1) {
printf("请输入公钥e(1<e<%d, 且e与phi(n)互质):", phi_n);
scanf("%d", &e);
if (gcd(e, phi_n) == 1)
break;
else
printf("e不合法,请重新输入\n");
}
d = modInverse(e, phi_n);
printf("私钥d=%d\n", d);
printf("请输入要加密的消息:");
scanf(" %[^\n]", msg);
len = strlen(msg);
// 将消息转换为数字数组
msg_arr = (int *)malloc(sizeof(int) * len);
for (i = 0; i < len; i++) {
msg_arr[i] = msg[i];
}
// 对消息进行分块
int block_size = (int)log10(n) / 2;
int num_blocks = ceil((double)len / block_size);
enc_arr = (int *)malloc(sizeof(int) * num_blocks);
for (i = 0; i < num_blocks; i++) {
int block_start = i * block_size;
int block_end = block_start + block_size - 1;
if (block_end >= len)
block_end = len - 1;
int block_len = block_end - block_start + 1;
int block_num = 0;
for (j = 0; j < block_len; j++) {
block_num += msg_arr[block_start + j] * pow(10, block_size - j - 1);
}
enc_arr[i] = (int)pow(block_num, e) % n;
}
// 将加密后的数字数组转换为字符串
enc_msg = (char *)malloc(sizeof(char) * num_blocks * block_size);
for (i = 0; i < num_blocks; i++) {
sprintf(&enc_msg[i * block_size], "%0*d", block_size, enc_arr[i]);
}
printf("加密后的消息:%s\n", enc_msg);
// 对加密后的消息进行解密
dec_arr = (int *)malloc(sizeof(int) * num_blocks);
for (i = 0; i < num_blocks; i++) {
int block_num = atoi(&enc_msg[i * block_size]);
dec_arr[i] = (int)pow(block_num, d) % n;
}
// 将解密后的数字数组转换为字符串
dec_msg = (char *)malloc(sizeof(char) * len);
for (i = 0; i < num_blocks; i++) {
int block_start = i * block_size;
int block_end = block_start + block_size - 1;
if (block_end >= len)
block_end = len - 1;
int block_num = dec_arr[i];
for (j = block_end; j >= block_start; j--) {
dec_msg[j] = block_num % 10;
block_num /= 10;
}
}
printf("解密后的消息:%s\n", dec_msg);
free(msg_arr);
free(enc_arr);
free(dec_arr);
free(enc_msg);
free(dec_msg);
return 0;
}
```
该程序首先读入两个质数p和q,然后计算n=pq和phi(n)=(p-1)(q-1),选择公钥e并计算私钥d。接着,程序读入要加密的消息,并将消息转换为数字数组。该程序将消息分块并对每个块进行加密,然后将加密后的数字块转换为字符串。之后,程序对加密后的消息进行解密,将解密后的数字块转换为字符串。最后,程序输出加密后的消息和解密后的消息。
注意,该程序假设每个ASCII字符都可以表示为一个小于10的整数,因此块大小设置为了log10(n)/2。如果消息中包含较长的字符串,需要增加块大小以便分块。此外,该程序还假设输入的质数p和q足够大,以确保安全性。实际应用时,需要根据需要调整参数以满足安全要求。
阅读全文