加法密碼和乘法密碼的結合就構成了仿射密碼,仿射密碼加密的思路爲:首先將明文乘以密鑰的一部分,然後再加上密鑰的剩餘部分。
一、仿射密碼加密解密算法
假設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;
}
三、運行結果