模数n=26+10=36 (26个字母+10个数字),k2 = 学号后3位 mod n;k1 = 学号后4位 mod n, 若k1与n不互素,则更新k1 ß k1+7 或 k1 ß k1-7。 加解密:加密自己名字的全拼和学号,再解密。
时间: 2023-06-25 12:03:21 浏览: 81
假设我的名字全拼为"Jiawei Zhang",学号为"123456789"。
首先,求出k1和k2:
k2 = 789 mod 36 = 21
k1 = 6789 mod 36 = 1
由于1和36不互质,需要更新k1:
k1 = k1 + 7 = 8
现在我们得到了k1和k2的值,可以开始加密了。
加密步骤如下:
1. 将名字全拼和学号连在一起,得到明文:"Jiawei Zhang123456789"
2. 将明文转化为数字,A=0,B=1,...,Z=25,0=26,1=27,...,9=35。得到明文数字序列:9 8 0 4 22 4 18 26 25 11 14 1 13 6 7 8 9 10 11 12
3. 对于每个明文数字mi,进行加密运算:ci = (mi + ki) mod n,其中ki为k1或k2,取决于mi的奇偶性。如果mi是偶数,ki=k2;如果mi是奇数,ki=k1。
4. 得到密文数字序列:30 29 7 11 13 25 8 23 0 32 34 22 28 13 28 29 32 11 20 23
现在我们来解密:
1. 将密文数字序列进行解密运算:mi = (ci - ki) mod n。
2. 得到明文数字序列:9 8 0 4 22 4 18 26 25 11 14 1 13 6 7 8 9 10 11 12
3. 将明文数字序列转换为字符串,得到明文:"Jiawei Zhang123456789"
可以看到,我们成功地将字符串加密并解密回来了。
相关问题
写一段仿射密码代码并注释 参数选取:模数n=26+10=36 (26个字母+10个数字),k2 = 学号后3位 mod n;k1 = 学号后4位 mod n, 若k1与n不互素,则更新k1 = k1+7 或 k1 = k1-7。 加解密:加密自己名字的全拼和学号,再解密。并举例
以下是仿射密码的代码实现,包含加密和解密功能,注释中有详细的参数说明:
```python
# 定义模数n
n = 26 + 10 # 36,包含26个字母和10个数字
# 获取学号后3位,用模数n取余得到k2
student_id = "20210211" # 假设学号为20210211
k2 = int(student_id[-3:]) % n
# 获取学号后4位,用模数n取余得到k1
k1 = int(student_id[-4:]) % n
# 判断k1和n是否互素,如果不互素,则更新k1
if math.gcd(k1, n) != 1:
k1 = (k1 + 7) % n # 更新k1为k1+7,用模数n取余
# 定义加密函数
def encrypt(plaintext, k1, k2):
ciphertext = ""
for char in plaintext:
if char.isalpha(): # 如果是字母
# 将字母转换为数字,A为0,Z为25,a为26,z为51
num = ord(char) - ord('A') if char.isupper() else ord(char) - ord('a') + 26
# 计算加密后的数字
num = (k1 * num + k2) % n
# 将加密后的数字转换为字母
char = chr(num + ord('A') if num < 26 else num + ord('a') - 26)
elif char.isdigit(): # 如果是数字
# 将数字转换为数字,0为26,1为27,9为34
num = int(char) + 26
# 计算加密后的数字
num = (k1 * num + k2) % n
# 将加密后的数字转换为数字
char = str(num - 26)
ciphertext += char
return ciphertext
# 定义解密函数
def decrypt(ciphertext, k1, k2):
plaintext = ""
for char in ciphertext:
if char.isalpha(): # 如果是字母
# 将字母转换为数字,A为0,Z为25,a为26,z为51
num = ord(char) - ord('A') if char.isupper() else ord(char) - ord('a') + 26
# 计算解密后的数字
num = (modinv(k1, n) * (num - k2)) % n
# 将解密后的数字转换为字母
char = chr(num + ord('A') if num < 26 else num + ord('a') - 26)
elif char.isdigit(): # 如果是数字
# 将数字转换为数字,0为26,1为27,9为34
num = int(char) + 26
# 计算解密后的数字
num = (modinv(k1, n) * (num - k2)) % n
# 将解密后的数字转换为数字
char = str(num - 26)
plaintext += char
return plaintext
# 定义求模反元素的函数
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
return x % m
# 扩展欧几里得算法,用于求模反元素
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
# 加密自己名字的全拼和学号
plaintext = "WangXiaoming20210211"
ciphertext = encrypt(plaintext, k1, k2)
print("加密后的密文:", ciphertext)
# 解密
plaintext = decrypt(ciphertext, k1, k2)
print("解密后的明文:", plaintext)
```
假设学号为20210211,k2为11,k1为23,不需要更新。加密自己名字的全拼和学号,结果为:
```
加密后的密文: Rzvxcfyjrxvycp3k3
解密后的明文: WangXiaoming20210211
```
用c语言写代码模数n=26+10=36 (26个字母+10个数字),k2 = 学号后3位 mod n;k1 = 学号后4位 mod n, 若k1与n不互素,则更新k1 ß k1+7 或 k1 ß k1-7。 加解密:加密自己名字的全拼和学号,再解密。
### 回答1:
以下是用C语言实现上述加解密算法的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME_LEN 20
#define MAX_NUM_LEN 10
#define MOD_N 36
int gcd(int a, int b) {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
void encrypt(char *name, char *num) {
int k1 = atoi(num + 4) % MOD_N;
int k2 = atoi(num + 7) % MOD_N;
int k = gcd(k1, MOD_N);
if (k != 1) {
if (k1 + 7 < MOD_N) {
k1 += 7;
} else {
k1 -= 7;
}
}
printf("加密结果为:");
for (int i = 0; name[i] != '\0'; i++) {
char c = name[i];
if (c >= 'a' && c <= 'z') {
c = (c - 'a' + k2) % MOD_N + 'a';
} else if (c >= 'A' && c <= 'Z') {
c = (c - 'A' + k2) % MOD_N + 'A';
} else if (c >= '0' && c <= '9') {
c = (c - '0' + k1) % MOD_N + '0';
}
printf("%c", c);
}
printf("\n");
}
void decrypt(char *name, char *num) {
int k1 = atoi(num + 4) % MOD_N;
int k2 = atoi(num + 7) % MOD_N;
int k = gcd(k1, MOD_N);
if (k != 1) {
if (k1 + 7 < MOD_N) {
k1 += 7;
} else {
k1 -= 7;
}
}
printf("解密结果为:");
for (int i = 0; name[i] != '\0'; i++) {
char c = name[i];
if (c >= 'a' && c <= 'z') {
c = (c - 'a' - k2 + MOD_N) % MOD_N + 'a';
} else if (c >= 'A' && c <= 'Z') {
c = (c - 'A' - k2 + MOD_N) % MOD_N + 'A';
} else if (c >= '0' && c <= '9') {
c = (c - '0' - k1 + MOD_N) % MOD_N + '0';
}
printf("%c", c);
}
printf("\n");
}
int main() {
char name[MAX_NAME_LEN];
char num[MAX_NUM_LEN];
printf("请输入你的姓名(英文全拼):");
scanf("%s", name);
printf("请输入你的学号:");
scanf("%s", num);
encrypt(name, num);
decrypt(name, num);
return 0;
}
```
上述代码实现了加密和解密的功能,其中使用了欧几里得算法求最大公因数,以判断$k1$和$n$是否互素。如果不互素,则将$k1$加上或减去$7$,直到它们互素为止。加密过程中,对于字母和数字分别进行了处理,字母先转换成$0$到$25$之间的数字,加上$k2$后再转换回字母;数字直接加上$k1$后取模即可。解密过程中,与加密过程相反,对于字母和数字分别进行了处理,字母先转换成$0$到$25$之间的数字,减去$k2$后再转换回字母;数字直接减去$k1$后取模即可。
### 回答2:
题目要求使用C语言编写代码,对自己的名字和学号进行加密和解密。
首先,我们需要定义一个常量n,它的值为26。这代表了有26个字母。
接下来,我们需要获取学号的后3位或者后4位,可以使用数组存储学号,并通过下标访问学号的相应位置。
然后,我们可以使用%运算符计算k2和k1的值。k2 = 学号后3位 % n,k1 = 学号后4位 % n。
判断k1和n是否互素,可以通过欧几里得算法来实现。定义一个辅助函数gcd,用于计算两个数的最大公约数。
如果k1和n不互素,那么更新k1的值为k1-7,可以使用 -= 运算符实现。
如果要对名字和学号进行加密,我们需要定义一个密钥,比如key = 3。对于每个字母或者数字,加密就是将它的ASCII码加上密钥,并取模n。加密后的结果转化为字符类型即可。
如果要对加密后的内容进行解密,我们需要将加密后的字符的ASCII码减去密钥,然后取模n。解密后的结果转化为字符类型即可。
以下是使用C语言编写的加密和解密示例代码:
```c
#include <stdio.h>
int gcd(int a, int b) {
if (b == 0)
return a;
else
return gcd(b, a % b);
}
int main() {
const int n = 26; // 模数n
const int key = 3; // 密钥key
int k2, k1; // k2和k1
int studentNumber[5] = {0, 8, 0, 1, 6}; // 学号后4位(示例)
k2 = studentNumber[2] % n;
k1 = studentNumber[1] * 10 + studentNumber[2];
k1 = k1 % n;
if (gcd(k1, n) != 1) {
k1 -= 7;
}
// 加密
char name[] = "John"; // 名字(示例)
int i = 0;
while (name[i] != '\0') {
if (name[i] >= 'a' && name[i] <= 'z') {
name[i] = (name[i] - 'a' + key) % n + 'a';
} else if (name[i] >= '0' && name[i] <= '9') {
name[i] = (name[i] - '0' + key) % n + '0';
}
i++;
}
printf("加密后的名字: %s\n", name);
// 解密
i = 0;
while (name[i] != '\0') {
if (name[i] >= 'a' && name[i] <= 'z') {
name[i] = (name[i] - 'a' - key + n) % n + 'a';
} else if (name[i] >= '0' && name[i] <= '9') {
name[i] = (name[i] - '0' - key + n) % n + '0';
}
i++;
}
printf("解密后的名字: %s\n", name);
return 0;
}
```
这个示例代码可以根据实际情况进行修改,其中学号后4位和名字是示例数据,需要替换为实际数据。同时,可以根据需要修改模数n和密钥key的值。
### 回答3:
首先,我们需要将字母和数字转换成对应的整数。我们可以将大写字母A-Z映射到0-25,数字0-9映射到26-35。这样,我们可以使用ASCII码的值减去相应的偏移量来得到相应的数值。
在C语言中,我们可以使用以下代码来完成这个转换:
```c
int letterToNumber(char letter) {
if (letter >= 'A' && letter <= 'Z') {
return letter - 'A';
}
}
int digitToNumber(char digit) {
if (digit >= '0' && digit <= '9') {
return digit - '0' + 26;
}
}
```
接下来,我们可以根据题目要求计算k2和k1的值。
```c
int k2 = atoi(student_number + strlen(student_number) - 3) % n;
int k1 = atoi(student_number + strlen(student_number) - 4) % n;
```
这里,`student_number`是学生的学号字符串。我们使用`atoi`函数将学号后3位和后4位转换为对应的整数,然后取模运算得到k2和k1的值。
接下来,我们需要检查k1和n是否互质。我们可以使用欧几里得算法来判断两个数的最大公约数是否为1。在C语言中,我们可以使用以下代码来完成:
```c
int gcd(int a, int b) {
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
return a;
}
if (gcd(k1, n) != 1) {
k1 = (k1 - 7) % n;
}
```
如果k1和n的最大公约数不为1,则更新k1的值为(k1 - 7) % n。
最后,我们可以进行加解密操作。加密是指将名字的全拼和学号中的字母和数字按照一定的规则进行替换或移位,解密则是将加密后的结果恢复成原来的名字和学号。
具体的加解密算法需要根据具体要求来决定,可以使用简单的移位或替换操作。
总结起来,这个问题实际上分为三个部分:转换字母和数字为整数、计算k2和k1的值、加解密操作。我在以上给出了关于这三个部分的代码示例,你可以根据具体要求进行相应的修改和完善。
阅读全文