ICode9

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

仿射算法加解密

2022-04-01 21:00:36  阅读:232  来源: 互联网

标签:密码 int text 加解密 k1 k2 算法 仿射


一、仿射密码加密

仿射密码
仿射密码也是一般单表替代密码的一个特例,是一种线性变换。仿射密码的明文空间和密文空间与移位密码相同,但密钥空间为 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;
}

 

标签:密码,int,text,加解密,k1,k2,算法,仿射
来源: https://www.cnblogs.com/danqingchuhong/p/16088966.html

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

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

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

ICode9版权所有