C语言实现古典密码—内含实例

C语言实现古典密码—内含实例


写在前沿的话:
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;
                    }
                }
            }
        }
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值