c語言實現多表代換密碼演算法及求逆元
阿新 • • 發佈:2020-09-06
密文及明文預設長度為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("請輸入正確的功能編號!"); } } }