问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

利用仿射密码实现对文件的加密和解密(C语言)

创作时间:
作者:
@小白创作中心

利用仿射密码实现对文件的加密和解密(C语言)

引用
CSDN
1.
https://m.blog.csdn.net/weixin_62788049/article/details/138874498

仿射密码是一种经典的替换密码算法,通过简单的数学变换实现对文本的加密和解密。本文将详细介绍仿射密码的工作原理,并通过C语言实现对文件的加密和解密功能,包括加密、解密算法的代码实现以及文件操作的完整示例。

一、仿射加密和解密的原理

仿射密码是一种替换密码。它是一个字母对一个字母的。它的加密过程可以表示为下面的函数:

e(x)=(ax+b) mod m

其中,a和m互质,m是字母的数目。它的解密过程可以表示为下面的函数:

d(x)=(a^(x-b)) mod m

其中a^是a对m的乘法逆元。

由加密公式容易推出解密公式:

若y = (ax+b) mod m

则 y 同余 (ax+b)mod m

y-b 同余 ax mod m

a^(y-b) 同余 x mod m

故而得出:x = (a^(y-b)) mode m

二、加密代码实现

加密代码的实现非常简单,直接根据公式加密即可,以下函数的功能是将一段字符串加密(区分大小写,忽略处字母以外的字符):

void encode(char* text,int addkey,int mulkey,char* password)
{
    unsigned int i;
    int code;
    for(i=0;i<strlen(text);i++)
    {
        if(text[i] >= 97 && text[i] <= 122)
        {
            code=text[i]-'a';
            password[i]=(code*mulkey+addkey)%26+'a';
        }
        else if(text[i] >= 65 && text[i] <= 90)
        {
            code=text[i]-'A';
            password[i]=(code*mulkey+addkey)%26+'A';
        }
        else
        {
            password[i]=text[i];
        }
    }
    password[i] = '\0';
}

三、解密代码实现

解密代码实现的关键是求出乘法逆元。那么如何求出乘法逆元呢?我们先从欧几里得算法说起。

3.1欧几里得算法(求两数最大公约数)

例如:我们要求16和6的最大公约数,下面的图很形象的说明算法的思路,就是给一个长宽分别为16和6的长方形不断地用正方形分割:

当余数为0时终止算法。代码实现也非常容易,就是不断地循环以下过程:c=a%b,把b赋值给a;c赋值给b,直到c为0,此时的b就是要求的最大公约数。以下是代码:

int Gcd(int a,int b)
{
    int c;
    while(1) 
    {
        c = a%b;
        if(c == 0)
            return b;
        a = b;
        b = c;
    }
}

那么这与我们想求的乘法逆元有什么关系呢?我们可以看到,以上算法没有用到每一步产生的商q,接下来还有一个更加厉害的算法。

3.2扩展欧几里得算法

扩展欧几里得算法是欧几里得算法的扩展:给予二整数 a 与 b, 必存在整数 s 与 t 使得as + bt = gcd(a,b)。

特别的,当a与b互为质数时有:as + bt = 1

以下图片求得了s和t的值:

3.3乘法逆元实现

我们知道乘法逆元满足以下公式:

若s为a mod b 的逆元,则满足:

sa 同余 1 mod b =>

sa + tb = 1 = gcd(a,b)

所以求乘法逆元实际上就是求sn的值。所以我们只需要在欧几里得求最大公约数的基础上,求出每一步的q,迭代更新si的值即可。以下是代码实现:

int ExtendOjld(int a,int b)
{
    int s0 = 0;
    int s1 = 1;
    int c,q,s2 = s1;
    while(1) 
    {
        c = b%a;
        q = b/a;
        if(c == 0)
            return s2;
        s2 = s0 - q * s1;
        b = a;
        a = c;
        s0 = s1;
        s1 = s2;
    }
}

3.4解密代码

求出乘法逆元后带公式即可,以下是具体代码,与加密类似:

void decode(char* password,int addkey,int mulkey,char* text)
{
    unsigned int i;
    int code;
    for(i=0;i<strlen(password);i++)
    {
        if(password[i] >= 97 && password[i] <= 122)
        {
            code=password[i]-'a';
            text[i]=( (code-addkey+ 26) * ExtendOjld(mulkey,26) )% 26 + 'a';
        }
        else if(password[i] >= 65 && password[i] <= 90)
        {
            code=password[i]-'A';
            text[i]=( (code-addkey+ 26) * ExtendOjld(mulkey,26) )% 26 + 'A';
        }
        else
        {
            text[i]=password[i];
        }
    }
    text[i] = '\0';
}

四、主函数文件操作实现

比较简单,直接上代码:

#include "affine.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define DECRY_FILE "仿射密文.txt"
#define ENCRY_FILE "仿射明文.txt"
int main()
{
    char buff_r[1025];
    char buff_w[1025];
    int k,b;
    unsigned int n;
    char mode;
    FILE *fp_r = NULL;
    FILE *fp_w = NULL;
    printf("Please input e(加密)/d(解密) k b\n");
    scanf("%c",&mode);
    scanf("%d %d",&k,&b);
    if(mode == 'e')
    {	
        fp_r = fopen(ENCRY_FILE,"r");
        fp_w = fopen(DECRY_FILE,"w");
        while( (n=fread(buff_r,1,sizeof(buff_r),fp_r))>0 )
        {
            encode(buff_r,b,k,buff_w);
            fwrite( buff_w, 1, n, fp_w );
        }
    }
    else if(mode == 'd')
    {
        fp_r = fopen(DECRY_FILE,"r");
        fp_w = fopen(ENCRY_FILE,"w");
        while( (n=fread(buff_r,1,sizeof(buff_r),fp_r))>0 )
        {
            decode(buff_r,b,k,buff_w);
            fwrite( buff_w, 1, n, fp_w );
        }
    }
    fclose(fp_r);
    fclose(fp_w);
    return 0;
}

五、总体代码

#include "affine.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define DECRY_FILE "仿射密文.txt"
#define ENCRY_FILE "仿射明文.txt"
#include "affine.h"
#include <stdlib.h>
#include <string.h>
//扩展欧几里得算法求乘法逆元a^-1
int ExtendOjld(int a,int b)
{
    int s0 = 0;
    int s1 = 1;
    int c,q,s2 = s1;
    while(1) 
    {
        c = b%a;
        q = b/a;
        if(c == 0)
            return s2;
        s2 = s0 - q * s1;
        b = a;
        a = c;
        s0 = s1;
        s1 = s2;
    }
}
//加密
void encode(char* text,int addkey,int mulkey,char* password)
{
    unsigned int i;
    int code;
    for(i=0;i<strlen(text);i++)
    {
        if(text[i] >= 97 && text[i] <= 122)
        {
            code=text[i]-'a';
            password[i]=(code*mulkey+addkey)%26+'a';
        }
        else if(text[i] >= 65 && text[i] <= 90)
        {
            code=text[i]-'A';
            password[i]=(code*mulkey+addkey)%26+'A';
        }
        else
        {
            password[i]=text[i];
        }
    }
    password[i] = '\0';
}
//解密
void decode(char* password,int addkey,int mulkey,char* text)
{
    unsigned int i;
    int code;
    for(i=0;i<strlen(password);i++)
    {
        if(password[i] >= 97 && password[i] <= 122)
        {
            code=password[i]-'a';
            text[i]=( (code-addkey+ 26) * ExtendOjld(mulkey,26) )% 26 + 'a';
        }
        else if(password[i] >= 65 && password[i] <= 90)
        {
            code=password[i]-'A';
            text[i]=( (code-addkey+ 26) * ExtendOjld(mulkey,26) )% 26 + 'A';
        }
        else
        {
            text[i]=password[i];
        }
    }
    text[i] = '\0';
}
int main()
{
    char buff_r[1025];
    char buff_w[1025];
    int k,b;
    unsigned int n;
    char mode;
    FILE *fp_r = NULL;
    FILE *fp_w = NULL;
    printf("Please input e(加密)/d(解密) k b\n");
    scanf("%c",&mode);
    scanf("%d %d",&k,&b);
    if(mode == 'e')
    {	
        fp_r = fopen(ENCRY_FILE,"r");
        fp_w = fopen(DECRY_FILE,"w");
        while( (n=fread(buff_r,1,sizeof(buff_r),fp_r))>0 )
        {
            encode(buff_r,b,k,buff_w);
            fwrite( buff_w, 1, n, fp_w );
        }
    }
    else if(mode == 'd')
    {
        fp_r = fopen(DECRY_FILE,"r");
        fp_w = fopen(ENCRY_FILE,"w");
        while( (n=fread(buff_r,1,sizeof(buff_r),fp_r))>0 )
        {
            decode(buff_r,b,k,buff_w);
            fwrite( buff_w, 1, n, fp_w );
        }
    }
    fclose(fp_r);
    fclose(fp_w);
    return 0;
}

六、运行结果

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号