ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c语言实现多表代换密码算法及求逆元

2020-09-06 15:34:17  阅读:367  来源: 互联网

标签:多表 int Enstring ++ re 逆元 return StrLen 及求


密文及明文默认长度为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("请输入正确的功能编号!");
    }
    } 
}

标签:多表,int,Enstring,++,re,逆元,return,StrLen,及求
来源: https://www.cnblogs.com/pluie/p/13621846.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有