仿射密码

0x01 算法原理

仿射密码是一种表单代换密码,字母表的每个字母相应的值使用一个简单的数学函数对应一个数值,再把对应数值转换成字母。

加密函数:E(x) = (ax + b) (mod m),其中 a与b互质,m是编码系统中字母的个数(通常都是26)。

解密函数:D(x) = a^{-1} (x - b) (mod m),其中 a^{-1} 是 a 在Z_{m}群的乘法逆元。

a,b是密钥,为满足0≤a,b≤25和gcd(a,26)等于1的整数。
a-1表示a的逆元,即a-1*a ≡ 1mod26

0x02 算法实现(加密与解密)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<stdio.h>
#include<string.h>
#define N 100
int main()
{
char m[N+1],c[N+1];
int k1,k2;
printf("请输入原文:");
//以回车(换行)作为字符串读取的结束,默认遇空格、回车、跳格键结束。
scanf("%[^\n]",m);
//开始加密
printf("\n请输入密钥k1,k2:");
//一次读取多个数值时的格式设置,默认以空格、回车分隔数值,若想以逗号分隔不同数值则需在""内将格式设置为"%d,%d",如scanf("%d,%d",&k1,&k2)则输入时仅以逗号分隔。
scanf("%d%d",&k1,&k2);

for (int i=0;i<strlen(m);i++)
{
////'a'对应97,'A'对应65. 以下两式子等价
//c[i]=(m[i]-'a'+k2)%26+97;
//c[i]=(m[i]-97+k2)%26+97;
if(m[i]>='A'&&m[i]<='Z')
c[i]='A'+(k1*(m[i]-'A')+k2)%26;
else if(m[i]>='a'&&m[i]<='z')
c[i]='a'+(k1*(m[i]-'a')+k2)%26;
else c[i]=m[i];
//单字符输出每一个密文:

}
printf("\n密文是: %s",c);
int r0=26,t0=0,t1=1,r1=k1,r2,t2,q;
while(r1!=0)
{
q=r0/r1;
r2=r0-q*r1;
t2=t0-q*t1;
r0=r1;r1=r2;
t0=t1;t1=t2;
}
int k1_inv=t0;//扩展欧几里得算法求逆元
printf("\n逆元 %d mod %d 是: %d",k1,r0,t0);

for (int i=0;i<strlen(c);i++)
{

if(c[i]>='A'&&c[i]<='Z')
m[i]='A'+(t0*(c[i]-'A')-k2)%26;
else if(c[i]>='a'&&c[i]<='z')
m[i]='a'+(t0*(c[i]-'a')-k2)%26;
else m[i]=c[i];
}//解密
printf("\n原文是: %s",m);

}
-------------本文结束感谢您的阅读-------------
/*
*/