算法说明: 设明文字母表为: ,密文字母表: ; 引入两个参数 、 ,要求 和 互素,即 ; 加密算法: ; 在解密时,首先需求解 在有限域 上的乘法逆元 ,可用欧几里得算法求解; 解密算法: . 具体要求: (1)取明文空间和密文空间为26个英文字母表,其大小为 ; (2)求出集合 中所有与26互素的数,并从中任取一个,作为 。另外,任取 ;输出 和 ; (3)求出 在有限域 上的乘法逆元 ; (4)从键盘输入一个字符串,长度约为15字符。然后按照a b c d e f g h i j k l m n o p q r s t u v w x y z分别对应0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25的方式,将明文转换为数字序列(不区分大小写,并忽略空格); (5)对第(4)步得到的数字序列逐数字加密,得到密文数字序列; (6)按照第(4)步中的映射方式,将第(5)步得到的数字序列映射为字母序列(即密文),并输出密文; (7)按照第(4)步中的映射方式,将第(6)步得到的密文序列映射为数字序列; (8)按照解密算法,对第(7)步得到的数字序列逐数字解密,得到明文数字序列; (9)按照第(4)步中的映射方式,将第(8)步得到的数字序列映射为字母序列(即明文),并输出。
时间: 2024-01-18 10:03:23 浏览: 144
这是一个基于模运算的加密算法,具体步骤如下:
1. 首先选取两个互素的整数 a 和 b,这里取a=3, b=5。
2. 明文字母表和密文字母表都是26个英文字母。
3. 求出所有与26互素的数,它们是1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25。在这些数中任取一个作为a的逆元,这里取a的逆元为9。另外,任取b=5。
4. 输入一个长度约为15字符的字符串,将明文转换为数字序列,即用0~25表示a~z,不区分大小写,并忽略空格。
5. 对数字序列逐数字加密,即用密文数字 ci = (ai * a + b) % 26 替换明文数字 ai。
6. 将加密后的数字序列映射为字母序列,即用0~25表示a~z,得到密文。
7. 将密文序列映射为数字序列,即用a~z表示0~25。
8. 对数字序列逐数字解密,即用明文数字 ai = ((ci - b) * a^{-1}) % 26 替换密文数字 ci。
9. 将解密后的数字序列映射为字母序列,即用a~z表示0~25,得到明文。
注意,这种加密算法的安全性较低,易受到密码分析的攻击,不适用于需要高度保密性的场合。
相关问题
用C语言设计一个设明文字母表为:p={p0,p1,…,pn-1}密文字母表:c={c0,c1,…,cn-1} 引入两个参数 a、b,要求a和n互素,即gcd(a,n)=1;加密算法:ci=E(Pi)=(a*pi+b)modn在解密时,首先需求解a在有限域Zn上的乘法逆元a-1∈Zn,可用欧几里得算法求解;解密算法:pi=D(ci)=a-1(ci-b)modn(1)取明文空间和密文空间为26个英文字母表,其大小为n=26;(2)求出集合{0,1,2,3,…,25}中所有与26互素的数,并从中任取一个,作为a。另外,任取b∈{0,1,2,3,…,25};输出a和b;(3)求出a在有限域Zn上的乘法逆元a-1∈Zn;(4)从键盘输入一个字符串,长度约为15字符。然后按照a b c d e f g h i j k l m n o p q r s t u v w x y z分别对应0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25的方式,将明文转换为数字序列(不区分大小写,并忽略空格);(5)对第(4)步得到的数字序列逐数字加密,得到密文数字序列;(6)按照第(4)步中的映射方式,将第(5)步得到的数字序列映射为字母序列(即密文),并输出密文;(7)按照第(4)步中的映射方式,将第(6)步得到的密文序列映射为数字序列;(8)按照解密算法,对第(7)步得到的数字序列逐数字解密,得到明文数字序列;(9)按照第(4)步中的映射方式,将第(8)步得到的数字序列映射为字母序列(即明文),并输出。
以下是用C语言实现的代码:
```c
#include <stdio.h>
#include <string.h>
// 求a在有限域Zn上的乘法逆元
int mod_inverse(int a, int n) {
int t, r, q, t1 = 0, t2 = 1, r1 = n, r2 = a;
while (r2 != 0) {
q = r1 / r2;
t = t1 - q * t2;
r = r1 - q * r2;
t1 = t2;
t2 = t;
r1 = r2;
r2 = r;
}
if (t1 < 0) {
t1 += n;
}
return t1;
}
// 加密函数
int encrypt(int p, int a, int b, int n) {
return (a * p + b) % n;
}
// 解密函数
int decrypt(int c, int a, int b, int n) {
int a_inv = mod_inverse(a, n);
return (a_inv * (c - b + n)) % n;
}
int main() {
int n = 26; // 字母表大小为26
int a, b;
int i, j;
// 求与26互素的数作为a
for (i = 1; i < n; i++) {
if (i % 2 == 0 || i % 13 == 0) {
continue;
}
a = i;
break;
}
// 随机选择b
b = 7;
printf("a = %d, b = %d\n", a, b);
// 输入字符串并转换为数字序列
char plaintext[16];
int plaintext_num[16];
printf("请输入明文(长度不超过15个字符):");
fgets(plaintext, 16, stdin);
plaintext[strcspn(plaintext, "\n")] = '\0'; // 去掉换行符
for (i = 0; i < strlen(plaintext); i++) {
if (plaintext[i] >= 'a' && plaintext[i] <= 'z') {
plaintext_num[i] = plaintext[i] - 'a';
} else if (plaintext[i] >= 'A' && plaintext[i] <= 'Z') {
plaintext_num[i] = plaintext[i] - 'A';
} else {
plaintext_num[i] = -1; // 非字母字符对应-1
}
}
// 加密明文数字序列得到密文数字序列
int ciphertext_num[16];
for (i = 0; i < strlen(plaintext); i++) {
if (plaintext_num[i] == -1) {
ciphertext_num[i] = -1; // 非字母字符不加密
} else {
ciphertext_num[i] = encrypt(plaintext_num[i], a, b, n);
}
}
// 将密文数字序列映射为密文
char ciphertext[16];
for (i = 0; i < strlen(plaintext); i++) {
if (ciphertext_num[i] == -1) {
ciphertext[i] = plaintext[i]; // 非字母字符不加密
} else {
ciphertext[i] = 'a' + ciphertext_num[i];
}
}
printf("密文:%s\n", ciphertext);
// 将密文序列映射为数字序列
for (i = 0; i < strlen(plaintext); i++) {
if (ciphertext[i] >= 'a' && ciphertext[i] <= 'z') {
ciphertext_num[i] = ciphertext[i] - 'a';
} else if (ciphertext[i] >= 'A' && ciphertext[i] <= 'Z') {
ciphertext_num[i] = ciphertext[i] - 'A';
} else {
ciphertext_num[i] = -1; // 非字母字符对应-1
}
}
// 解密密文数字序列得到明文数字序列
int plaintext_num2[16];
for (i = 0; i < strlen(plaintext); i++) {
if (ciphertext_num[i] == -1) {
plaintext_num2[i] = -1; // 非字母字符不解密
} else {
plaintext_num2[i] = decrypt(ciphertext_num[i], a, b, n);
}
}
// 将明文数字序列映射为明文
char plaintext2[16];
for (i = 0; i < strlen(plaintext); i++) {
if (plaintext_num2[i] == -1) {
plaintext2[i] = plaintext[i]; // 非字母字符不解密
} else {
plaintext2[i] = 'a' + plaintext_num2[i];
}
}
printf("解密得到的明文:%s\n", plaintext2);
return 0;
}
```
运行程序后,输入明文,即可得到加密后的密文和解密后的明文。
用C语言设明文字母表为:p={p0,p1,…,pn-1}密文字母表:c={c0,c1,…,cn-1} 引入两个参数 a、b,要求a和n互素,即gcd(a,n)=1;加密算法:ci=E(Pi)=(a*pi+b)modn在解密时,首先需求解a在有限域Zn上的乘法逆元a-1∈Zn,可用欧几里得算法求解;解密算法:pi=D(ci)=a-1(ci-b)modn(1)取明文空间和密文空间为26个英文字母表,其大小为n=26;(2)求出集合{0,1,2,3,…,25}中所有与26互素的数,并从中任取一个,作为a。另外,任取b∈{0,1,2,3,…,25};输出a和b;(3)求出a在有限域Zn上的乘法逆元a-1∈Zn;(4)从键盘输入一个字符串,长度约为15字符。然后按照a b c d e f g h i j k l m n o p q r s t u v w x y z分别对应0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25的方式,将明文转换为数字序列(不区分大小写,并忽略空格);(5)对第(4)步得到的数字序列逐数字加密,得到密文数字序列;(6)按照第(4)步中的映射方式,将第(5)步得到的数字序列映射为字母序列(即密文),并输出密文;(7)按照第(4)步中的映射方式,将第(6)步得到的密文序列映射为数字序列;(8)按照解密算法,对第(7)步得到的数字序列逐数字解密,得到明文数字序列;(9)按照第(4)步中的映射方式,将第(8)步得到的数字序列映射为字母序列(即明文),并输出。
以下是实现该加密解密算法的C语言代码:
```c
#include <stdio.h>
#include <ctype.h>
int gcd(int a, int b) { // 求最大公约数
int t;
while (b != 0) {
t = b;
b = a % b;
a = t;
}
return a;
}
int mod(int a, int b) { // 模运算,确保结果在[0, b)范围内
int r = a % b;
return r < 0 ? r + b : r;
}
int mod_inverse(int a, int n) { // 求a在Zn上的乘法逆元
int t, r = n, new_t = 1, new_r = a;
int q, tmp;
while (new_r != 0) {
q = r / new_r;
tmp = new_t;
new_t = t - q * new_t;
t = tmp;
tmp = new_r;
new_r = r - q * new_r;
r = tmp;
}
if (r > 1) {
return -1; // a在Zn上没有乘法逆元
}
if (t < 0) {
t = t + n;
}
return t;
}
int main() {
int p[26] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; // 明文字母表
int c[26]; // 密文字母表
int a, b, n = 26;
int i, j, k;
char str[16]; // 输入的字符串
int len; // 字符串长度
int plain[16], cipher[16]; // 明文和密文对应的数字序列
// 随机选择a和b
for (a = 1; gcd(a, n) != 1; a++);
b = rand() % n;
// 生成密文字母表
for (i = 0; i < n; i++) {
c[i] = mod(a * p[i] + b, n);
}
// 输出a和b
printf("a = %d, b = %d\n", a, b);
// 输入字符串并转换为数字序列
printf("请输入要加密的字符串:");
fgets(str, 16, stdin);
len = strlen(str);
j = 0;
for (i = 0; i < len; i++) {
if (isalpha(str[i])) { // 忽略非字母字符
plain[j++] = tolower(str[i]) - 'a';
}
}
// 加密
for (i = 0; i < j; i++) {
cipher[i] = c[plain[i]];
}
// 输出密文
printf("加密后的字符串:");
for (i = 0; i < j; i++) {
putchar(cipher[i] + 'a');
}
putchar('\n');
// 解密
a = mod_inverse(a, n);
if (a == -1) { // a在Zn上没有乘法逆元
printf("解密失败:a在Zn上没有乘法逆元!\n");
return 0;
}
for (i = 0; i < j; i++) {
plain[i] = mod(a * (cipher[i] - b), n);
}
// 输出明文
printf("解密后的字符串:");
for (i = 0; i < j; i++) {
putchar(plain[i] + 'a');
}
putchar('\n');
return 0;
}
```
阅读全文