zoukankan      html  css  js  c++  java
  • c语言实现多表代换密码算法及求逆元

    密文及明文默认长度为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("
    %f %f %f %f %f %f %f %f 
    ",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
    ", sum);
                //printf("sum is %d
    ", 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):
    A:");
        IuputAre_A(A);                  //A的输入
        printf("
    B:");
        InputB(B);                      //B的输入
        printf("
    A^-1:");
        IuputAre_A(re_A);               //A^-1的输入
    }
        while(1){                                         //验证密钥的正确性(即A*A^-1=E),若不正确则提示再次输入
            if(!checkA(A,re_A)){
                system("cls");
                printf("请输入正确的A和A^-1!
    A:");
                IuputAre_A(A);
                printf("A^-1:");
                IuputAre_A(re_A);
                continue;
            }
            break;
        }
        while(1){
        printf("
    请输入功能序号:
    0.加密
    1.解密
    2.求逆元
    3.退出程序
    ");
        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
    ", 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
    ", DeString);
        }
        else if(FunType==2)                               //功能2.求逆元
        {
            int a, m;
            printf("a:");
            scanf("%d", &a);
            printf("m:");
            scanf("%d", &m);
            printf("
    %d模%d 的逆元为:%d
    ", a, m, re_yuan(a, m));
        }
        else
        {
            printf("请输入正确的功能编号!");
        }
        } 
    }
    
  • 相关阅读:
    JS Dom_API
    JS 动态表格(添加、删除行)
    将本地网页上传到 apache2 及 github 的步骤
    软件工程之美 第一周
    树莓派安装芯片驱动并测试
    Visoul Studio 2019 远程调试 中文乱码
    Visoul Studio 2019 远程调试 RaspberryPi C 项目
    课设提纲
    PHP PDO 一 : 常用方法
    设置子域名及申请其证书
  • 原文地址:https://www.cnblogs.com/pluie/p/13621846.html
Copyright © 2011-2022 走看看