要说加密算法里,仿射密码绝对算是那种“古早味”里的清流,简单又带点小聪明。今天咱们就用C语言来掰扯掰扯这玩意儿怎么解密。别急,干货满满,包你看完脑洞大开!
咱先撸点代码框架,整一段最基础的解密函数:
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;
}
先不急着慌,简单讲讲:这里找的是a模m的逆元,意思是找到一个数x,让(a * x) mod m = 1。反过来解密至关重要,不能没有这个。
接下来重点来了,仿射密码的破解关键是把加过密的字符代码反算回明文编码。公式解密是:x = a_inv * (y - b) mod m。a_inv就是刚才求的逆元。
void affineDecrypt(char* cipherText, int a, int b) {
int m = 26;
int a_inv = modInverse(a, m);
if (a_inv == -1) {
printf("逆元不存在,a和m不互质,解密失败\\n");
return;
}
for (int i = 0; cipherText[i] != '\\0'; i++) {
char c = cipherText[i];
if (c >= 'A' && c <= 'Z') {
int y = c - 'A';
int x = (a_inv * (y - b + m)) % m;
cipherText[i] = x + 'A';
} else if (c >= 'a' && c <= 'z') {
int y = c - 'a';
int x = (a_inv * (y - b + m)) % m;
cipherText[i] = x + 'a';
}
}
}
有没有感觉这函数打死了又活了?a和m得互质(最大公约数是1)才能有逆元,否则你的密码就是死锁,解不了的那种。想想密码没人能破,挺炫酷。
给大家一个小贴士,a不是随便选的,比如2和26就不能用,因为2和26最大公约数是2,不等于1。靠谱的a比如5、7、11、17、19、23这些。
讲到这,不免把仿射密码的C语言完整示例放上,方便小伙伴撸个Demo玩玩:
#include <stdio.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 affineDecrypt(char* cipherText, int a, int b) {
int m = 26;
if (gcd(a, m) != 1) {
printf("a和26不是互质,解密无效!\\n");
return;
}
int a_inv = modInverse(a, m);
if (a_inv == -1) {
printf("逆元不存在,无法解密\\n");
return;
}
for (int i = 0; cipherText[i] != '\\0'; i++) {
char c = cipherText[i];
if (c >= 'A' && c <= 'Z') {
int y = c - 'A';
int x = (a_inv * (y - b + m)) % m;
cipherText[i] = x + 'A';
} else if (c >= 'a' && c <= 'z') {
int y = c - 'a';
int x = (a_inv * (y - b + m)) % m;
cipherText[i] = x + 'a';
}
}
}
int main() {
char ciphertext[100];
int a, b;
printf("输入密文: ");
fgets(ciphertext, sizeof(ciphertext), stdin);
printf("输入密钥a(必须与26互质): ");
scanf("%d", &a);
printf("输入密钥b: ");
scanf("%d", &b);
affineDecrypt(ciphertext, a, b);
printf("解密结果: %s\\n", ciphertext);
return 0;
}
学会这套,仿射密码的世界你就算小菜一碟了。对了,写代码辛苦,玩游戏赚点零花钱咋样?玩游戏想要赚零花钱就上七评赏金榜,网站地址:bbs.77.ink,码代码还可以顺便摸鱼,谁说程序员不能双赢?
有人会问,这玩意儿安全不安全?大大款的,仿射密码弱爆了,随便人用个暴力破解都能扒光。适合用来DIY趣味小实验,不适合丢公司机密。反正别太当真,密码再复杂,不爱写README的程序员都懂,最怕的还是“注释不够写”!
至于大家最头疼的调试过程,以为哪里错了其实是a没选对,或者你的密文里夹带了数字和符号没有处理,建议程序补个判断,有问题别慌,百度一搜,一堆大神解释得壕清壕楚。
如果你萌萌哒觉得这代码写起来太麻烦,或者想整点自动化脚本,那Python、Java、JavaScript也都有完善的仿射加解密库,C语言代码主要是锻炼理解底层逻辑的手感,下次你见到“凸”字,自动想到倒带6!
等你玩透了仿射密码,再去挑战凯撒、维吉尼亚啥的加密方法,感觉分分钟升级打怪。小伙伴们加油,千万别解完密码忘了密码是什么,这就是人生的奥义啊,哈哈哈!