仿射算法加解密

一、仿射密码加密

仿射密码
仿射密码也是一般单表替代密码的一个特例,是一种线性变换。仿射密码的明文空间和密文空间与移位密码相同,但密钥空间为 K={(k1,k2)| k1,k2∈Z26,gcd(k1,26)=1}
对任意m∈M,c∈C,k = (k1,k2)∈K。
定义加密变换为:c = Ek (m) = (k1 m +k2) (mod 26)
相应解密变换为: m = Dk (c) = k1-1 (c-k2) (mod 26)

实例:
设明文消息为china,密钥k=(k1, k2)=(9,2)试用仿射密码对其进行加密。

明文消息对应的数字序列为(2,7,8,13,0),用仿射密码对明文进行加密如下:

 

故加密后的密文为:unwpc。

加密代码实现

#include<stdio.h>
#include <string.h>
int k1,k2;
char text[50];
//加密函数
void encrypt()
{
    int i,z=0;
    int l = strlen(text);
    for(i=0;i<l;i++)
    {
        //判断大小写
        if (text[i] >= 'A' && text[i] <= 'Z'){
           text[z]=(k1*(text[i]-'A')+k2)%26+'A';
        } else if (text[i] >= 'a' && text[i] <= 'z'){
            text[z]=(k1*(text[i]-'a')+k2)%26+'a';
        } else{  //判断是否是空格
            text[z] = text[i];
        }
        z++;
    }
    printf("密文为:%s\n",text);
}
int main(void)
{
    printf("输入明文\n");
    scanf("%[^\n]%*c", text);

    printf("请输入密钥k1\n");
    scanf("%d",&k1);
    printf("请输入密钥k2\n");
    scanf("%d",&k2);

    encrypt();
    getchar();
    return 0;
}

 

 

二、仿射密码解密

仿射密码
仿射密码也是一般单表替代密码的一个特例,是一种线性变换。仿射密码的明文空间和密文空间与移位密码相同,但密钥空间为 K={(k1,k2)| k1,k2∈Z26,gcd(k1,26)=1} ,其中,, 。
对任意m∈M,c∈C,k = (k1,k2)∈K,
定义加密变换为:c = Ek (m) = k1 m +k2 (mod 26)
相应解密变换为:m = Dk (c) = k1-1 (c-k2) (mod 26)

示例1:
密文消息为unwpc,密钥k=(k1, k2)=(9,2),试对密文消息进行解密。解密过程如下:

密文消息对应的数字为(20,13,22,15,2),利用扩展的欧几里德算法可计算出,k1的逆元为3

 

 

 

 故恢复出来的明文为china。

代码实现

#include<stdio.h>
#include <string.h>
int k1,k2;
char text[100];
int *p;//第1行数组的值
int *q;//第二行数组的值
int h[2][10];
int degree;
//解密函数
void decrypt()
{
    int i,mid;
    int l = strlen(text);
    for(i=0;i<l;i++)
    {
        //判断大小写
        if (text[i] >= 'A' && text[i] <= 'Z')
        {
            mid=text[i]-'A'-k2;
            text[i]=(k1*((text[i]-'A')-k2))%26+'A';
            if(mid < 0)
            {
                text[i] = text[i] + 26;
            }//当k2过大,可能会出现负数

        }
        else if (text[i] >= 'a' && text[i] <= 'z')
        {
            mid=(text[i]-'a')-k2;
            text[i]=(k1*((text[i]-'a')-k2))%26+'a';

            if((mid)<0)
            {
                text[i]=text[i]+26;
            }


        }

     }
     printf("明文为:%s\n",text);
 }

 /*欧几里得算法*/
int gcd(int a,int b,int num)
{
    *(p+num)=a;
    *(q+num)=b;
    num=num+1;
    if(b==0)
        return a;
    return gcd(b,a%b,num);
}
//扩展欧几里得求逆元
int vid(int x,int y)
{

    int mid=0;
    mid=y;
    //求每次的y值
    y=x-(h[0][degree]/h[1][degree])*y;
    x=mid;
    degree--;
    if(degree==-1)
        return x;

    return vid(x,y);
}
int inverse_element(int a)
{
    int b,min;
    int num=0;
    b=26;
    //用两个指针指向a,b两个数。
    p=&h[0][0];
    q=&h[1][0];

    //执行辗转相除法
    min=gcd(a,b,num);

    //判断最大公约数是否为1
    if(min==1)
        printf("%d,%d互素",a,b);
    else{
        printf("%d,%d不互素",a,b);
        return 0;
    }

    //得到数组中最后一个数
    for (degree = 0; degree <10 ; ++degree) {  //a的值

        if(*(p+degree)==1)
            break;
    }
    degree--;
    //进入求逆元的递归函数
    int x=1,y=0;
    x=vid(x,y);
    //判断逆元
    if(x>=0){
        printf("\n逆元为%d",x);
        return x;
    }

    else{
        printf("\n逆元为%d ",h[1][0]+x);
        return h[1][0]+x;
    }

}
int main(void)
{
    printf("输入密文\n");
    scanf("%[^\n]%*c", text);


    printf("请输入密钥k1\n");
    scanf("%d",&k1);
    printf("请输入密钥k2\n");
    scanf("%d",&k2);
    k1=inverse_element(k1);//获得逆元
    decrypt();

    return 0;
}

 

posted @ 2022-04-01 20:54  丹青初鸿  阅读(2566)  评论(0编辑  收藏  举报