加法密码和乘法密码的结合就构成了仿射密码,仿射密码加密的思路为:首先将明文乘以密钥的一部分,然后再加上密钥的剩余部分。
一、仿射密码加密解密算法
假设c , m , a , b ∈Z26
加密:ek(m) ≡c ≡ a⋅m + b mod 26
解密:dk(c) = m = a-1 ⋅(c-b) mod 26
密钥为:k =(a ,b ),且满足限制条件 gcd( a ,26)=1。当a=1时,仿射密码变为加法密码,当b=0时,仿射密码变为乘法密码。
解密可以很容易地从加密函数推导出来:
a ⋅ m + b≡c mod 26
a ⋅ m≡ (c– b )mod 26
m ≡ a-1⋅ (c– b )mod 26
二、C++编程实现仿射密码的攻击
1.问题描述
仿射密码系统用五元组(P,C,K,E,D)表示,设P=C={abcdefghijklmnopqrstuvwxyz}.现在截获了一段密文“ojbkojbk”。请编程分析出明文。
2.C++代码如下:
#include <iostream>
#include <string>
#include <cstdio>
#include<stdlib.h>
using namespace std;
/*
欧几里德算法
*/
int gcd(int a,int b)
{
int temp;
if(a<b)//判断大小
{
temp=a;
a=b;
b=temp;
}
if(b==0) return a;
else return gcd(b,a%b);//递归
}
int main()
{
string List("abcdefghijklmnopqrstuvwxyz"),c("ojbkojbk"),result;
int a,b,m,p;
/*
加密:c = Ea,b(m) ≡ a, + b(mod 26)
解密:m = Da,b(c) ≡ a^-1(c - b)(mod 26)
a,b是密钥 0<=a,b<=n,gcd(a,m)=1
逆元:a^-1*a≡1mod m
*/
for(a=2;a<26;a++){
//a和26互素
if(gcd(a,26)==1){
//求a的乘法逆元p
for(b=2;b<26;b++){
if((a*b)%26==1){
p=b;break;
}
}
//下面进行解密
for(b = 0; b < 28; b++) // k2 = b<q
{
for(int i=0;i<c.size();i++){
for(int k = 0; k < List.size(); k += 1){
if(List[k] == c[i]) //得到密文所对应的密文数字
{
//string中文测试,因为编码和string类的原因,一个中文字符占两个下标
// pp=pp+bi1[k] + bi1[k + 1];
// cout<<pp<<endl;
// printf("k:%d ",k);
// printf("\n");
m = (p * (k - b)) % 26; //得到密文数字相对应的明文数字
//得到明文数字对应的明文
if (m >= 0)
{
result = result + List[m] ;
}
else
{
m = m+ 26;
result = result + List[m];
}
}
}
}
printf ("当 a = %02d, b = %02d 时,解密得到的明文是: ", a, b);
cout << result << endl;
result.clear();
}
}
}
return 0;
}
三、运行结果