利用仿射密码实现对文件的加密和解密
一、仿射加密和解密的原理
仿射密码是一种替换密码。它是一个字母对一个字母的。它的加密过程可以表示为下面的函数:
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