写在前沿的话:
C语言断断续续的学了不少,但还是对结构体、指针、数据结构等了解甚少,所以只能用最基本的循环这些来写,比较繁杂,能力有限,还请谅解,十分欢迎大家批评指正,若有好的优化算法,也欢迎大家交流。第一次写文章,就这样吧。
恺撒密码
//恺撒密码
#include <stdio.h>
void CasesarPassward(char *, int );
int main(void)
{
printf("\n******恺撒密码******\n");
while(1)
{
printf("\n请输入功能序号:\n0.加密\n1.解密\n2.退出程序\n选择功能:");
int function;
char ch[1000] = "\0";
char solve[1000] = "\0";
scanf("%d", &function);
fflush(stdin);
switch(function)
{
case 0:
printf("请输入明文:");
gets(ch);
CasesarPassward(ch, function);
break;
case 1:
printf("请输入密文:");
gets(solve);
CasesarPassward(solve, function);
break;
case 2 :
return 0;
break;
default:
printf("请输入正确的功能编号!");
break;
}
}
}
void CasesarPassward(char ch[],int function)
{
int i = 0;
int key = 3;
if(function == 0)
{
while(ch[i] != '\0')
{
if((ch[i] >= 'a') && (ch[i] <= 'z'))
{
ch[i] ='a' + (((ch[i] - 'a') + key) % 26);
}
if((ch[i] >= 'A') && (ch[i] <= 'Z'))
{
ch[i] ='A' + (((ch[i] - 'A') + key) % 26);
}
i++;
}
printf("密文为:%s\n", ch);
}
else if(function == 1)
{
while(ch[i] != '\0')
{
if((ch[i] >= 'a') && (ch[i] <= 'z'))
{
ch[i] ='a' + (((ch[i] - 'a') - key) % 26);
}
if((ch[i] >= 'A') && (ch[i] <= 'Z'))
{
ch[i] ='A' + (((ch[i] - 'A') - key) % 26);
}
i++;
}
printf("明文为:%s\n", ch);
}
}
移位变换
//移位变换
#include <stdio.h>
void ShiftTransformation(char *, int, int);
int main(void)
{
printf("\n******位移变换******\n");
while(1)
{
printf("\n请输入功能序号:\n0.加密\n1.解密\n2.退出程序\n选择功能:");
int key;
int function;
char ch[1000] = "\0";
char solve[1000] = "\0";
scanf("%d", &function);
printf("\n请输入密钥:\n");
scanf("%d", &key);
fflush(stdin);
switch(function)
{
case 0:
printf("请输入明文:");
gets(ch);
ShiftTransformation(ch, function, key);
break;
case 1:
printf("请输入密文:");
gets(solve);
ShiftTransformation(solve, function, key);
break;
case 2 :
return 0;
break;
default:
printf("请输入正确的功能编号!");
break;
}
}
}
void ShiftTransformation(char ch[], int function, int key) //移位变换
{
int i = 0;
if(function == 0)
{
while(ch[i] != '\0')
{
if((ch[i] >= 'a') && (ch[i] <= 'z'))
{
ch[i] ='a' + (((ch[i] - 'a') + key) % 26);
}
if((ch[i] >= 'A') && (ch[i] <= 'Z'))
{
ch[i] ='A' + (((ch[i] - 'A') + key) % 26);
}
i++;
}
printf("密文为:%s\n", ch);
}
else if(function == 1)
{
while(ch[i] != '\0')
{
if((ch[i] >= 'a') && (ch[i] <= 'z'))
{
ch[i] ='a' + (((ch[i] - 'a') - key) % 26);
}
if((ch[i] >= 'A') && (ch[i] <= 'Z'))
{
ch[i] ='A' + (((ch[i] - 'A') - key) % 26);
}
i++;
}
printf("明文为:%s\n", ch);
}
}
仿射变换
//仿射变换
//security vlxijh
//THE NATIONAL SECURITY AGENCY
//edsgickxhuklzveqzvkxwkzukvcuh
#include <stdio.h>
#include <string.h>
void AffineTransformation(char *, int, int, int);
int GCD(int);
int mod_invese(int d, int n);
void solve_function(char *);
int main(void)
{
printf("\n******仿射变换******\n");
while(1)
{
printf("\n请输入功能序号:\n0.加密\n1.解密\n2.解函数\n3.退出程序\n选择功能:");
int function;
int a = 0;
int b = 0;
char x[4] = "\0";
char ch[1000] = "\0";
char solve[1000] = "\0";
scanf("%d", &function);
switch(function)
{
case 0:
printf("请输入加密所用的密钥:(0<=a,b<=25)\n");
scanf("%d,%d", &a, &b);
while(GCD(a) != 1)
{
printf("请重新输入密钥:\n");
printf("请输入加密所用的密钥:(0<=a<=25)\n");
scanf("%d", &a);
}
fflush(stdin);
printf("请输入明文:");
gets(ch);
AffineTransformation(ch, a, b, function);
break;
case 1:
printf("请输入解密所用的密钥:(0<=a,b<=25)\n");
scanf("%d,%d", &a, &b);
while(GCD(a) != 1)
{
printf("请重新输入密钥:\n");
printf("请输入解密所用的密钥:(0<=a<=25)\n");
scanf("%d", &a);
}
fflush(stdin);
printf("请输入待解密密文:");
gets(solve);
AffineTransformation(solve, a, b, function);
break;
case 2:
printf("请输入方程系数:x,y,m,n:\n");
fflush(stdin);
gets(x);
solve_function(x);
break;
case 3:
return 0;
break;
default:
printf("请输入正确的功能编号!");
break;
}
}
}
void AffineTransformation(char ch[], int a, int b, int function) //仿射变换
{
int i = 0;
if(function == 0) //加密
{
while(ch[i] != '\0')
{
if((ch[i] >= 'a') && (ch[i] <= 'z'))
{
ch[i] = 'a' + (((ch[i] - 'a') * a + b) % 26);
}
if((ch[i] >= 'A') && (ch[i] <= 'Z'))
{
ch[i] = 'A' + (((ch[i] - 'A') * a + b) % 26);
}
i++;
}
printf("密文为:%s", ch);
}
else if(function ==1) //解密
{
while(ch[i] != '\0')
{
if((ch[i] >= 'a') && (ch[i] <= 'z'))
{
if((ch[i] - 'a' - b) < 0)
ch[i] = 'a' + ((ch[i] - 'a' - b) * mod_invese(a, 26)) % 26 + 26;//计算机 n%m=n-m(n/m);(负数时向上取整)
else
ch[i] = 'a' + ((ch[i] - 'a' - b) * mod_invese(a, 26)) % 26;
}
if((ch[i] >= 'A') && (ch[i] <= 'Z'))
{
if((ch[i] - 'A' - b) < 0)
ch[i] = 'A' + ((ch[i] - 'A' - b) * mod_invese(a, 26)) % 26 + 26;
else
ch[i] = 'A' + ((ch[i] - 'A' - b) * mod_invese(a, 26)) % 26;
}
i++;
}
printf("明文为:%s", ch);
}
}
int GCD(int a) //判断互素
{
int number = 26;
int r = a % number;
int flag = 0;
while(r != 0)
{
a = number;
number = r;
r = a % number;
}
if(number != 1)
{
return flag;
}
else
{
return flag + 1;
}
}
int mod_invese(int d,int n)//求d模n的逆,n 为正整数
{
int a;//被除数
int b;//除数
int q;//商
int r;
int u = 0;
int v = 1;
int t;
a = n;
b = (d >= 0) ? (d % n) : - (d % n);//规定正负数mod(n)都取正;
while(b != 0)
{
q = (int) a / b;
r = a - b * q;
a = b;
b = r;
t = v;
v = u - q * v;
u = t;//把每次没有进行运算的v的值给u
}//辗转相除,直到余数b=0,跳出循环
if(a != 1) return 0;
return((u < 0) ? u + n : u);//返回的值都是mod(n)后的值,使得最后的值是正数;
}
void solve_function(char x[])
{
int i, j;
int a, b; //所要求解的变量
int flag = 0;
int time = 1;
int k_1 = 0, k_2 = 0;
int length;
length = strlen(x);
int vary[length];
memset(vary,0,sizeof(vary));
for(i = 0; i < length; i++)
{
if(x[i] >= 'a' && x[i] <= 'z')
{
vary[i] = x[i] - 'a';
}
if(x[i] >= 'A' && x[i] <= 'Z')
{
vary[i] = x[i] - 'A';
}
}
while(flag != 2)
{
k_1 = 0 ;
for(i = 0; i < time; i++)
{
k_2 = 0;
for(j=0; j < time; j++)
{
k_2++;
if(((vary[2] + 26 * k_1 - vary[3] - 26 * k_2) % (vary[0] - vary[1])) == 0)
flag++;
if(((vary[1] * (vary[2] + 26 * k_1) - vary[0] * (vary[3] + 26 * k_2)) % (vary[1] - vary[0])) == 0)
flag++;
if(flag == 2)
break;
}
k_1++;
}
time++;
}
a = ((vary[2] + 26 * k_1 - vary[3] - 26 * k_2) / (vary[0] - vary[1]));
b = ((vary[1] * (vary[2] + 26 * k_1) - vary[0] * (vary[3] + 26 * k_2)) / (vary[1] - vary[0]));
while(b < 0)
{
b = b + 26;
}
// b = b % 26;
// a = a + 26;
printf("k1=%d\n",k_1);
printf("k2=%d\n",k_2);
printf("密钥a = %d\n", a);
printf("密钥b = %d\n", b);
}
多表代换
//多表代换密码
// YOUR PIN NO IS FOUR ONE TWO SIX
// A = 11 2 19 5 23 25 20 7 17
// A^-1 = 10 23 7 15 9 22 5 9 21
// B = 0 0 0
// PLEASE SEND ME THE BOOK MY CREDIT CARD NO IS SIX ONE TWO ONE THREE EIGHT SIX ZERO ONE SIX EIGHT FOUR NINE SEVEN ZERO TWO
// A = 3 13 21 9 15 10 6 25 10 17 4 8 1 23 7 2
// A^-1 = 23 13 20 5 0 10 11 26 9 11 15 22 9 22 6 25
// B = 1 21 8 17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#define SIZE 2
int GCD(int a);
void fun(char *str);
void Input_B(int B[]);
void Iuput_A(int A[][SIZE]);
int mod_invese(int d, int n);
int getA(int arcs[SIZE][SIZE], int n);
void A_NI_Mod(int ans[SIZE][SIZE], int det);
void Change_To_Number(char *str, int StrLen);
void solve_function(char encode[], char decode[]);
void getAStart(int arcs[SIZE][SIZE], int n, int ans[SIZE][SIZE]);
void Encrypt(int A[][SIZE], char Enstring[], int StrLen, int B[]);
void Decrypt(int A_inverse[][SIZE], char Destring[], int StrLen, int B[]);
int main(void)
{
int A[SIZE][SIZE];
int B[SIZE];
int astar[SIZE][SIZE];
int A_inverse[SIZE][SIZE];
printf("\n******多表代换******\n");
while (1)
{
printf("\n\n请输入功能序号:\n0.加密\n1.解密\n2.矩阵密钥\n3.求逆矩阵\n4.退出程序\n选择功能:");
int i = 0, j = 0, flag = 0;
int DET;
int StrLen;
int function;
char encode[100] = "\0";
char decode[100] = "\0";
char ch[1000] = "\0";
char solve[1000] = "\0";
scanf("%d", &function);
fflush(stdin);
switch (function)
{
case 0:
printf("\n请输入待加密明文(长度为%d的倍数):", SIZE);
gets(ch);
fun(ch);
printf("\n请输入加密密钥密钥(A,B)(分组为%d):\nA:", SIZE);
Iuput_A(A); // A的输入
printf("\nB:");
Input_B(B); // B的输入
StrLen = strlen(ch);
Encrypt(A, ch, StrLen, B);
printf("\n加密后的密文是:");
for (i = 0; i < StrLen; i++)
{
printf("%c", ch[i]);
flag++;
if (flag % SIZE == 0)
printf(" ");
}
break;
case 1:
printf("\n请输入待解密密文(长度为%d的倍数):", SIZE);
gets(solve);
fun(solve);
printf("\n请输入解密密钥A^-1 (分组为%d):\n", SIZE);
printf("\nA^-1:");
Iuput_A(A_inverse); // A^-1的输入
printf("\nB:");
Input_B(B); // B的输入
StrLen = strlen(solve);
if (StrLen % SIZE != 0) //对长度不是4的倍数的明文的处理,
{
for (int i = 0; i < (StrLen % SIZE); i++)
{
solve[StrLen + i] = ' ';
}
StrLen = StrLen + SIZE - StrLen % SIZE;
solve[StrLen] = 0; //字符串以0结尾
}
Decrypt(A_inverse, solve, StrLen, B);
printf("\n解密后的明文是:");
for (i = 0; i < StrLen; i++)
{
printf("%c", solve[i]);
flag++;
if (flag % SIZE == 0)
printf(" ");
}
break;
case 2:
printf("\n请输入已知明文:\n");
gets(encode);
printf("\n请输入已知密文:\n");
gets(decode);
solve_function(encode, decode);
break;
case 3:
printf("\n请输入矩阵A:");
Iuput_A(A);
DET = getA(A, SIZE);
printf("\n矩阵A的值为:%d\n", DET);
getAStart(A, SIZE, astar);
printf("\n代数余子式A*为:\n");
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
printf("%d\t", astar[i][j]);
}
printf("\n");
}
printf("\n矩阵逆为:\n");
A_NI_Mod(astar, DET);
break;
case 4:
return 0;
break;
default:
printf("\n请输入正确的功能编号!\n");
break;
}
}
}
void Change_To_Number(char *str, int StrLen) //转换成ASCII码
{
int i;
for (int i = 0; i < StrLen; i++)
{
if (str[i] >= 'a' && str[i] <= 'z')
str[i] -= 'a';
if (str[i] >= 'A' && str[i] <= 'Z')
str[i] -= 'A';
// printf("str[%d]=%d\t",i,str[i]);
}
}
void Iuput_A(int A[][SIZE]) // A与A^-1的输入
{
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++)
scanf("%d", &A[i][j]);
}
void Input_B(int B[]) // B输入
{
for (int i = 0; i < SIZE; i++)
scanf("%d", &B[i]);
}
void Encrypt(int A[][SIZE], char Enstring[], int StrLen, int B[]) //加密函数,参数为 A,要加密的明文,明文长度,B
{
int n;
int M[StrLen / SIZE][SIZE];
memset(M, 0, sizeof(M));
Change_To_Number(Enstring, StrLen); //转换成ASCII码
for (int i = 0; i < StrLen / SIZE; i++) //求Ci
{
for (int j = 0; j < SIZE; j++)
{
for (n = 0; n < SIZE; n++)
{
M[i][j] = M[i][j] + Enstring[i * SIZE + n] * A[j][n];
}
M[i][j] = (M[i][j] + B[j]) % 26;
}
}
for (int i = 0; i < StrLen / SIZE; i++) //数字对应字母
{
for (int j = 0; j < SIZE; j++)
{
if (M[i][j] < 0)
M[i][j] = M[i][j] + 26;
Enstring[i * SIZE + j] = M[i][j] + 'A';
}
}
}
void Decrypt(int A_inverse[][SIZE], char Destring[], int StrLen, int B[]) //解密函数,参数为 A^-1,要解密的密文,密文长度,B
{
int n;
int M[StrLen / SIZE][SIZE];
memset(M, 0, sizeof(M));
Change_To_Number(Destring, StrLen); //英文字母和十进制数对应
for (int i = 0; i < StrLen / SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
Destring[i * SIZE + j] -= B[j];
}
}
for (int i = 0; i < StrLen / SIZE; i++) //求Mi
{
for (int j = 0; j < SIZE; j++)
{
for (n = 0; n < SIZE; n++)
{
M[i][j] = M[i][j] + Destring[i * SIZE + n] * A_inverse[j][n];
}
// printf("\nM[%d][%d]=%d\t",i,j,M[i][j]);
M[i][j] = M[i][j] % 26;
// printf("\nM[%d][%d]=%d\t",i,j,M[i][j]);
}
}
for (int i = 0; i < StrLen / SIZE; i++) //数字对应字母
{
for (int j = 0; j < SIZE; j++)
{
if (M[i][j] < 0)
M[i][j] = M[i][j] + 26;
Destring[i * SIZE + j] = M[i][j] + 'A';
}
}
}
void fun(char *str) //删除字符串中的空格
{
char *str_c = str;
int i, j = 0;
for (i = 0; str[i] != '\0'; i++)
{
if (str[i] != ' ')
str_c[j++] = str[i];
}
str_c[j] = '\0';
str = str_c;
}
int getA(int arcs[SIZE][SIZE], int n) //按第一行展开计算|A|
{
if (n == 1)
{
return arcs[0][0];
}
int ans = 0;
int temp[SIZE][SIZE];
int i, j, k;
for (i = 0; i < n; i++)
{
for (j = 0; j < n - 1; j++)
{
for (k = 0; k < n - 1; k++)
{
temp[j][k] = arcs[j + 1][(k >= i) ? k + 1 : k];
}
}
int t = getA(temp, n - 1);
if (i % 2 == 0)
{
ans += arcs[0][i] * t;
}
else
{
ans -= arcs[0][i] * t;
}
}
return ans;
}
void getAStart(int arcs[SIZE][SIZE], int n, int ans[SIZE][SIZE]) //计算每一行每一列的每个元素所对应的余子式,组成A*
{
if (n == 1)
{
ans[0][0] = 1;
return;
}
int i, j, k, t;
int temp[SIZE][SIZE];
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
for (k = 0; k < n - 1; k++)
{
for (t = 0; t < n - 1; t++)
{
temp[k][t] = arcs[k >= i ? k + 1 : k][t >= j ? t + 1 : t];
}
}
ans[j][i] = getA(temp, n - 1);
if ((i + j) % 2 == 1)
{
ans[j][i] = -ans[j][i];
}
}
}
}
int mod_invese(int d, int n) //求d模n的逆,n 为正整数
{
int a; //被除数
int b; //除数
int q; //商
int r;
int u = 0;
int v = 1;
int t;
a = n;
b = (d >= 0) ? (d % n) : -(d % n); //规定正负数mod(n)都取正;
while (b != 0)
{
q = (int)a / b;
r = a - b * q;
a = b;
b = r;
t = v;
v = u - q * v;
u = t; //把每次没有进行运算的v的值给u
} //辗转相除,直到余数b=0,跳出循环
if (a != 1)
return 0;
return ((u < 0) ? u + n : u); //返回的值都是mod(n)后的值,使得最后的值是正数;
}
void A_NI_Mod(int ans[SIZE][SIZE], int det) //求A逆
{
int i, j;
int a_ni[SIZE][SIZE];
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
a_ni[i][j] = (mod_invese(det, 26) * ans[i][j]) % 26;
if (a_ni[i][j] <= 0)
{
a_ni[i][j] += 26;
}
printf("%d\t", a_ni[i][j]);
}
printf("\n");
}
}
int GCD(int a) //判断互素
{
int number = 26;
int r = a % number;
int flag = 0;
while (r != 0)
{
a = number;
number = r;
r = a % number;
}
if (number != 1)
{
return flag;
}
else
{
return flag + 1;
}
}
void solve_function(char M[], char C[]) //求解密钥
{
int A[2][2];
int B[2] = {0, 0};
int i;
int flag = 0;
memset(A, 0, sizeof(A));
int A_deverse = 0;
Change_To_Number(M, 4);
Change_To_Number(C, 4);
for (A[0][0] = 1; A[0][0] < 26; A[0][0]++)
{
for (A[0][1] = 1; A[0][1] < 26; A[0][1]++)
{
for (A[1][0] = 1; A[1][0] < 26; A[1][0]++)
{
for (A[1][1] = 1; A[1][1] < 26; A[1][1]++)
{
flag = 0;
A_deverse = A[0][0] * A[1][1] - A[0][1] * A[1][0];
if (GCD(A_deverse) != 1)
continue;
if ((A[0][0] * M[0] + A[0][1] * M[1]) % 26 == C[0])
flag++;
if ((A[0][0] * M[2] + A[0][1] * M[3]) % 26 == C[2])
flag++;
if ((A[1][0] * M[0] + A[1][1] * M[1]) % 26 == C[1])
flag++;
if ((A[1][0] * M[2] + A[1][1] * M[3]) % 26 == C[3])
flag++;
if (flag == 4)
{
printf("\n");
printf("矩阵A为:\n");
printf("%d\t%d\n%d\t%d\n", A[0][0], A[0][1], A[1][0], A[1][1]);
break;
}
}
}
}
}
}