加法密码和乘法密码的结合就构成了仿射密码,仿射密码加密的思路为:首先将明文乘以密钥的一部分,然后再加上密钥的剩余部分。
一、仿射密码加密解密算法
假设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;
- }
复制代码
三、运行结果
|