利用仿射密码实现对文件的加密和解密(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;
}

六、运行结果

在这里插入图片描述
在这里插入图片描述

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是C语言实现仿射密码加密解密的代码: ``` #include <stdio.h> #include <string.h> int gcd(int a, int b) { if (b == 0) { return a; } return gcd(b, a % b); } int modInverse(int a, int m) { a = a % m; for (int x = 1; x < m; x++) { if ((a * x) % m == 1) { return x; } } return -1; } void affine_encrypt(char* plaintext, int a, int b, char* ciphertext) { int len = strlen(plaintext); for (int i = 0; i < len; i++) { if (plaintext[i] >= 'a' && plaintext[i] <= 'z') { ciphertext[i] = (char) (((a * (plaintext[i] - 'a') + b) % 26) + 'a'); } else if (plaintext[i] >= 'A' && plaintext[i] <= 'Z') { ciphertext[i] = (char) (((a * (plaintext[i] - 'A') + b) % 26) + 'A'); } else { ciphertext[i] = plaintext[i]; } } ciphertext[len] = '\0'; } void affine_decrypt(char* ciphertext, int a, int b, char* plaintext) { int len = strlen(ciphertext); int a_inv = modInverse(a, 26); for (int i = 0; i < len; i++) { if (ciphertext[i] >= 'a' && ciphertext[i] <= 'z') { plaintext[i] = (char) (((a_inv * ((ciphertext[i] - 'a' - b + 26) % 26)) % 26) + 'a'); } else if (ciphertext[i] >= 'A' && ciphertext[i] <= 'Z') { plaintext[i] = (char) (((a_inv * ((ciphertext[i] - 'A' - b + 26) % 26)) % 26) + 'A'); } else { plaintext[i] = ciphertext[i]; } } plaintext[len] = '\0'; } int main() { char plaintext[100], ciphertext[100], decryptedtext[100]; int a, b; printf("Enter the plaintext: "); scanf("%[^\n]s", plaintext); printf("Enter the value of a (should be coprime with 26): "); scanf("%d", &a); printf("Enter the value of b: "); scanf("%d", &b); if (gcd(a, 26) != 1) { printf("Invalid value of a. It should be coprime with 26.\n"); return 0; } affine_encrypt(plaintext, a, b, ciphertext); printf("Encrypted text: %s\n", ciphertext); affine_decrypt(ciphertext, a, b, decryptedtext); printf("Decrypted text: %s\n", decryptedtext); return 0; } ``` 在这个程序中,我们使用了两个函数affine_encrypt和affine_decrypt来分别实现仿射密码加密解密。这两个函数的参数分别是明文,a和b(这是仿射密码的两个参数),以及密文或解密后的明文。我们还使用了gcd函数来计算两个数的最大公约数,以及modInverse函数来计算a模26的逆元。在主函数中,我们先输入明文,a和b,然后进行加密解密,并输出结果。注意,输入的明文应该只包含字母和空格,不应该包含标点符号或数字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值