概述
题目描述
写一个程序实现2*2 Hill密码的加解密算法
遇到的问题
加密过程写的很顺利,因为是2*2矩阵,一些本应该用矩阵乘法计算的东西也直接被我简化成用算式表示了。
在写解密过程是遇到了问题,矩阵求逆的部分不太会做。跟着书上前面的例题看了一下。书上说对于2*2的矩阵,求其行列式。如果矩阵A有非零的行列式,则这个矩阵的逆如下计算:[A^(-1)]ij = (det A)^(-1) * (-1)^(i+j) * (Dij), 其中(Dij)是将矩阵去掉第j行和第i列后的子行列式的值,det(A)是A的行列式,而(det A)^(-1)是det(A) mod 26的逆。
然后举了个例子,矩阵A = 5 8 17 3; det A = (5 * 3) - (8 * 17) = -121 mod 26 = 9
因为9*3 = 27 mod 26 = 1,可得到9^(-1) mod 26 = 3
因此,A^(-1) mod 26 = 3 * (3, -8, -17, 5) = 3 * (3, 18, 9, 5) = (9, 54, 27, 15) = (9, 2, 1, 15)
啊对就这里。最开始我怎么都没看明白,后面去问别人人给我说就是对其中的每一个元素mod 26而已我才发现。wow这真是厉害极了。知道这个规律之后这也就好求逆了。
编写的代码如下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 60
int main()
{
int K1[2][2] = {0}, K2[2][2] = {0};
int Temp1[2] = {0}, Temp2[2] = {0};
char P[MAX] = {0}, C[MAX] = {0};
int T1[MAX] = {0}, T2[MAX] = {0};
int len, flag=0, temp, temp1, i, j, num=0;
printf("======= Hill 密码 =======nn");
printf("请输入秘钥的值:n");
for(i=0; i<2; i++)
{
for(j=0; j<2; j++)
{
scanf("%d", &K1[i][j]);
}
}
printf("n1. 加密t 2. 解密n请选择:");
scanf("%d", &num);
if(num == 1)
{
printf("请输入明文:n");
scanf("%s", P);
len = strlen(P);
// 当长度为奇数时补齐一位
if(len % 2 == 1)
{
P[len] = 'a';
len = strlen(P);
flag = 1;
}
// 将大写转成小写,并赋值给T1数组
for(i=0; i<len; i++)
{
if(P[i] >= 'A' && P[i] <= 'Z')
{
P[i] = P[i] + 32;
}
T1[i] = P[i] - 'a';
}
// 得到加密后结果,存储在T2中
for(i=0; i<len; i+=2)
{
Temp1[0] = T1[i];
Temp1[1] = T1[i + 1];
// Temp2存储密文int值
Temp2[0] = (Temp1[0] * K1[0][0] + Temp1[1] * K1[1][0]) % 26;
Temp2[1] = (Temp1[0] * K1[0][1] + Temp1[1] * K1[1][1]) % 26;
T2[i] = Temp2[0];
T2[i + 1] = Temp2[1];
}
if(flag == 1)
{
len = len - 1;
}
printf("加密结果为:n");
for(i=0; i<len; i++)
{
C[i] = T2[i] + 'a';
printf("%c ", C[i]);
}
printf("n");
}
else if(num == 2)
{
printf("请输入密文:");
scanf("%s", C);
len = strlen(C);
// 当长度为奇数时补齐一位
if(len % 2 == 1)
{
C[len] = 'a';
len = strlen(C);
flag = 1;
}
for(i=0; i<len; i++)
{
if(C[i] >= 'A' && C[i] <= 'Z')
{
C[i] = C[i] + 32;
}
T2[i] = C[i] - 'a';
}
// 求K的逆
temp = -1;
for(i=1; temp < 0; i++)
{
temp = (K1[0][0] * K1[1][1] - K1[0][1] * K1[1][0]) + 26 * i;
}
i = 1;
while(1)
{
if((temp * i) % 26 == 1)
{
temp1 = i;
break;
}
else
{
i++;
}
}
K2[0][0] = K1[1][1] * temp1;
K2[0][1] = (((-1 * K1[0][1]) + 26) * temp1) % 26;
K2[1][0] = (((-1 * K1[1][0]) + 26) * temp1) % 26;
K2[1][1] = K1[0][0] * temp1;
// printf(" %d %d %d %d %d %dn",temp, temp1, K2[0][0], K2[0][1], K2[1][0], K2[1][1]);
// system("pause");
// printf(" %d %d %d %d %d %dn",temp, temp1, K2[0][0]%26, K2[0][1]%26, K2[1][0]%26, K2[1][1]%26);
// system("pause");
// 得到解密后结果,存储在T2中
for(i=0; i<len; i+=2)
{
Temp2[0] = T2[i];
Temp2[1] = T2[i + 1];
// Temp1存储明文int值
Temp1[0] = (Temp2[0] * K2[0][0] + Temp2[1] * K2[1][0]) % 26;
Temp1[1] = (Temp2[0] * K2[0][1] + Temp2[1] * K2[1][1]) % 26;
T1[i] = Temp1[0];
T1[i + 1] = Temp1[1];
}
if(flag == 1)
{
len = len - 1;
}
printf("解密结果为:n");
for(i=0; i<len; i++)
{
P[i] = T1[i] + 'a';
printf("%c ", P[i]);
}
printf("n");
}
else
{
printf("error!");
exit(0);
}
return 0;
}
附带测试数据:
输入数组: 9 4 5 7
明文: meetmeattheusualplaceatthenratherthaneightoclock
密文: yybtyyrdyvgacedzihkokqgbfeuprdfeotlchcywcfgsnmqa
最后
以上就是傲娇时光为你收集整理的Hill密码的加密与解密(C语言)题目描述遇到的问题的全部内容,希望文章能够帮你解决Hill密码的加密与解密(C语言)题目描述遇到的问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复