密文及明文默认长度为4的倍数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int ex_gcd(int a,int b,int &x,int &y) //扩展欧几里得
{
if(b==0)
{
x=1;
y=0;
return a;
}
int r=ex_gcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return r;
}
int re_yuan(int a,int b) //求a的逆元x
{
int d,x,y;
d=ex_gcd(a,b,x,y);
return (x%b+b)%b;
}
void IuputAre_A(int A[][4]) //A与A^-1的输入
{
for (int i = 0; i < 4;i++)
for (int j = 0; j < 4; j++)
scanf("%d", &A[i][j]);
}
void InputB(int B[]) //B输入
{
for (int i = 0; i < 4;i++)
scanf("%d", &B[i]);
}
bool checkA(int A[][4],int re_A[][4]) //验证密钥的正确性(即A*A^-1=E)
{
for (int i = 0; i < 4;i++)
{
for (int j = 0; j < 4;j++)
{
int sum = A[i][0]*re_A[0][j]+A[i][1]*re_A[1][j]+A[i][2]*re_A[2][j]+A[i][3]*re_A[3][j];
//printf("\n%f %f %f %f %f %f %f %f \n",A[i][0],re_A[0][j],A[i][1],re_A[1][j],A[i][2],re_A[2][j],A[i][3],re_A[3][j]);
//printf("sum is %f\n", sum);
//printf("sum is %d\n", sum%26);
if(i==j)
{
if(sum%26!=1)
return 0;
}else
{
if(sum%26!=0)
return 0;
}
}
}
return 1;
}
void Encrypt(int A[][4],char Enstring[],int StrLen,int B[]) //加密函数,参数为 A,要加密的明文,明文长度,B
{
char M[StrLen/4][4];
for (int i = 0; i < StrLen;i++)
{
Enstring[i] -= 65;
}
for (int i = 0; i < StrLen / 4; i++) //求Ci
{
for (int j = 0; j < 4; j++)
{
M[i][j] = (Enstring[i * 4] * A[j][0] + Enstring[i * 4 + 1] * A[j][1] + Enstring[i * 4 + 2] * A[j][2] + Enstring[i * 4 + 3] * A[j][3] + B[j]) % 26;
}
}
for (int i = 0; i < StrLen/4;i++) //数字对应字母
{
for(int j=0;j<4;j++)
{
if(M[i][j]<0)
M[i][j] += 26;
Enstring[i*4+j] = M[i][j]+65;
}
}
}
void Decrypt(int re_A[][4],char Destring[],int StrLen,int B[]) //解密函数,参数为 A^-1,要解密的密文,密文长度,B
{
char M[StrLen/4][4];
for (int i = 0; i < StrLen;i++)
{
Destring[i] -= 65;
}
for (int i = 0; i < StrLen / 4;i++) //英文字母和十进制数对应
{
for (int j = 0; j < 4;j++)
{
Destring[i * 4 + j] -= B[j];
}
}
for (int i = 0; i < StrLen / 4;i++) //求Mi
{
for (int j = 0; j < 4;j++)
{
M[i][j] = (Destring[i * 4] * re_A[j][0] + Destring[i * 4 + 1] * re_A[j][1] + Destring[i * 4 + 2] * re_A[j][2] + Destring[i * 4 + 3] * re_A[j][3] ) % 26;
}
}
for (int i = 0; i < StrLen/4;i++) //数字对应字母
{
for(int j=0;j<4;j++)
{
if(M[i][j]<0)
M[i][j] += 26;
Destring[i*4+j] = M[i][j]+65;
}
}
}
int main(){
int A[4][4], B[4],re_A[4][4];
{ //A、B、A^-1的输入
printf("请输入加密密钥密钥(A,B)和解密密钥A^-1 (分组为4):\nA:");
IuputAre_A(A); //A的输入
printf("\nB:");
InputB(B); //B的输入
printf("\nA^-1:");
IuputAre_A(re_A); //A^-1的输入
}
while(1){ //验证密钥的正确性(即A*A^-1=E),若不正确则提示再次输入
if(!checkA(A,re_A)){
system("cls");
printf("请输入正确的A和A^-1!\nA:");
IuputAre_A(A);
printf("A^-1:");
IuputAre_A(re_A);
continue;
}
break;
}
while(1){
printf("\n请输入功能序号:\n0.加密\n1.解密\n2.求逆元\n3.退出程序\n");
int FunType;
scanf("%d", &FunType);
if(FunType==3)
{
return 0;
}
else if(FunType==0) //功能0.加密
{
char EnString[1000];
printf("请输入待加密明文(长度为四的倍数):");
scanf("%s", EnString);
int StrLen = strlen(EnString);
Encrypt(A, EnString, StrLen, B);
printf("加密后的密文是:%s\n", EnString);
}
else if(FunType==1) //功能1.解密
{
char DeString[1000];
printf("请输入待解密密文(长度为四的倍数):");
scanf("%s", DeString);
int StrLen = strlen(DeString);
if(StrLen%4!=0) //对长度不是4的倍数的明文的处理,
{
for (int i = 0; i < (StrLen % 4); i++)
{
DeString[StrLen + i] = ' ';
}
StrLen += 4 - StrLen % 4;
DeString[StrLen] = 0; //字符串以0结尾
}
Decrypt(re_A, DeString, StrLen, B);
printf("解密后的明文是:%s\n", DeString);
}
else if(FunType==2) //功能2.求逆元
{
int a, m;
printf("a:");
scanf("%d", &a);
printf("m:");
scanf("%d", &m);
printf("\n%d模%d 的逆元为:%d\n", a, m, re_yuan(a, m));
}
else
{
printf("请输入正确的功能编号!");
}
}
}