一.關鍵步驟:
(1) 加密:先將大小寫轉換成數字0-25,按照c=m*p+q%26進行加密
加密結果如圖所示
(2) 解密:根據m=(c-q)*p-1,關鍵是求出密鑰p的逆,代碼如圖
解密結果如圖1.4所示.
(3)破解:密鑰空間為311,可以進行暴力破解,關鍵破解代碼
二.安全性分析:
仿射密碼安全性較弱,抵抗不了窮舉攻擊
三.加密源碼
#include<bits/stdc++.h>
using namespace std;
int main(){
//c=a*p+q;
int p,q,len,n,x;
char a[9999],c;
while(cin>>p){// 輸入密鑰p,q,明文a
cin>>q>>a;
if((p%2==0)||(p==1&&q==0)){//p!=1&&q!=0,p需與26互素
cout<<"密鑰不合法";
break;
}
len=strlen(a);
for(int i=0;i<len;i++){//字母轉成數字0-25
if(a[i]>=65&&a[i]<=90)
a[i]-=65;
else if(a[i]>=97&&a[i]<=122)
a[i]-=97;
x=a[i];
cout<<x<<" ";}//將轉成數字的明文輸出
cout<<"密文如下"<<endl;
for(int i=0;i<len;i++){//加密n=a*p+q
n=p*a[i]+q;
cout<<n<<" ";//輸出加密后的數字
n=n%26+65;
a[i]=n;
}
cout<<endl;
for(int i=0;i<len;i++)
cout<<a[i]<<" ";//輸出加密后的字母
}
return 0;
}
四.解密源碼
#include<bits/stdc++.h>
using namespace std;
//n=a*p+q
int f(int p){// 求p的逆 ;
int m,k,r,d,i;
int a[8][4]={0};
a[0][0]=1,a[0][3]=1;
k=p;
m=26,r=1,d=0,i=0;
while(r){//列表法求出逆
r=m%k;
d=m/k;
i++;
a[i][0]=a[i-1][1];
a[i][2]=a[i-1][3];
a[i][1]=a[i-1][0]-a[i-1][1]*d;
a[i][3]=a[i-1][2]-a[i-1][3]*d;
m=k;
k=r;
}
if(a[i-1][3]<0)//如果逆小於0,加26
a[i-1][3]+=26;
p=a[i-1][3];
return p;
}
int main(){
int n,p,q,len,k;
char a[9999];
while(cin>>p){
if(p%2==0||p==13)
{cout<<"密鑰不合法,請重新輸入"<<endl;
break; }
cin>>q>>a;
len=strlen(a);
//判斷大小寫 ,並轉成數字0-25
for(int i=0;i<len;i++){
if(a[i]>=65&&a[i]<=90)
a[i]-=65;
else if(a[i]>=97&&a[i]<=122)
a[i]-=97;
n=a[i]-q;
if(n<0)
n+=26;
n=n*f(p);
n=n%26+65;//由數字轉成大寫字母
a[i]=n;
}
for(int i=0;i<len;i++)//輸出明文
cout<<a[i]<<" ";}
return 0;
}