以《现代密码学》习题 1.3 为例:
设多表代换密码中:
[A=egin{bmatrix}
{3} & {13}&{21}&{9} \
{15}&{10}&{6}&{25}\
{10}&{17}&{4}&{8}\
{1}&{23}&{7}&{2}
end{bmatrix}
,
B=egin{bmatrix}
{1}\{21}\{8}\{17}
end{bmatrix}
]
加密为:(C_i≡A{M_i}+ extbf{B}(mod 26))
对明文PLEASE SEND ME THE BOOK, MY CREDIT CARD NO IS SIX ONE TWO ONE THREE EIGHT SIX ZERO ONE SIX EIGHT FOUR NINE SEVEN ZERO TWO,
用解密变换
(M_i≡A^{-1}(C_i- extbf{B})(mod 26))
验证你的结果,其中
[A^{-1}=egin{bmatrix}
{26} & {13}&{20}&{5} \
{0}&{10}&{11}&{0}\
{9}&{11}&{15}&{22}\
{9}&{22}&{6}&{25}
end{bmatrix}
]
- 根据书 1.4.2 ,先将字符串中空格去除,再取 N 位(N 为矩阵 A 的秩)的字串,进行矩阵乘法,最后再把空格加上,输出。
- 例 1.4.2 的简单验证:
#include<bits/stdc++.h>
#define rap(a,b) for(int a=0;a<b;++a)
using namespace std;
string encypt(string m,double a[][3],double b[]){
string ans;
for (int i=0;i<3;++i){
int tmp=0;
for (int j=0;j<3;++j){
tmp+=a[i][j]*(m[j]-'A');
}
tmp+=b[i];tmp%=26;
ans+=tmp+'A';
}
return ans;
}
string decypt(string c,double a[][3],double b[]){
string ans;
for(int i=0;i<3;++i){
int tmp=0;
for(int j=0;j<3;++j){
tmp+=a[i][j]*(c[j]-'A'-b[j]);
}
ans+=tmp%26+'A';
}
return ans;
}
int main(){
double a[3][3]={
11,2,19,
5,23,25,
20,7,17
};
double b[3]={0,0,0};
string c="YOUR PIN NO IS FOUR ONE TWO SIX";
//记录空格位置并去空格
vector<int>pos;
int tmp=c.find(' ');
while(tmp!=-1)
{
pos.push_back(tmp);
c.erase(tmp,1);
tmp=c.find(' ');
}
int i=0;
string m;
while(i!=c.size()){
m+=encypt(c.substr(i,3),a,b);
i+=3;
}
double a2[3][3]={
10,23,7,
15,9,22,
5,9,21
};
i=0;
string c2;
while(i!=m.size()){
c2+=decypt(m.substr(i,3),a2,b);
i+=3;
}
for(i=pos.size()-1;i>=0;--i)c.insert(pos[i]," ");
for(i=pos.size()-1;i>=0;--i)m.insert(pos[i]," ");
for(i=pos.size()-1;i>=0;--i)c2.insert(pos[i]," ");
cout<<c<<endl;
cout<<m<<endl;
cout<<c2<<endl;
return 0;
}
- 运行结果:
- 仿照例题,很容易得出习题 1.3 的算法实现:
#include<bits/stdc++.h>
#define rap(a,b) for(int a=0;a<b;++a)
using namespace std;
string encypt(string m,double a[][4],double b[]){
string ans;
for (int i=0;i<4;++i){
int tmp=0;
for (int j=0;j<4;++j){
tmp+=a[i][j]*(m[j]-'A');
}
tmp+=b[i];
ans+=tmp%26+'A';
}
return ans;
}
string decypt(string c,double a[][4],double b[]){
string ans;
int cc[4];
for(int i=0;i<4;++i)cc[i]=(int)(c[i]-'A'-b[i]+26)%26;
for(int i=0;i<4;++i){
int tmp=0;
for(int j=0;j<4;++j){
tmp+=a[i][j]*cc[j];
}
ans+=tmp%26+'A';
}
return ans;
}
int main(){
double a[4][4]={
3,13,21,9,
15,10,6,25,
10,17,4,8,
1,23,7,2
};
double b[4]={1,21,8,17};
string c="PLEASE SEND ME THE BOOK, MY CREDIT CARD NO IS SIX ONE TWO ONE THREE EIGHT SIX ZERO ONE SIX EIGHT FOUR NINE SEVEN ZERO TWO";
//记录空格位置并去空格
vector<int>pos;
int tmp=c.find(' ');
while(tmp!=-1)
{
pos.push_back(tmp);
c.erase(tmp,1);
tmp=c.find(' ');
}
//加密
int i=0;
string m;
while(i!=c.size()){
m+=encypt(c.substr(i,4),a,b);
i+=4;
}
//解密
double a2[4][4]={
26,13,20,5,
0,10,11,0,
9,11,15,22,
9,22,6,25
};
string c2;
i=0;
while(i!=m.size()){
c2+=decypt(m.substr(i,4),a2,b);
i+=4;
}
//还原空格
for(i=pos.size()-1;i>=0;--i)c.insert(pos[i]," ");
for(i=pos.size()-1;i>=0;--i)m.insert(pos[i]," ");
for(i=pos.size()-1;i>=0;--i)c2.insert(pos[i]," ");
cout<<c<<endl;
cout<<m<<endl;
cout<<c2<<endl;
return 0;
}
- 输出结果:
- What's?! 居然不对??让我们对前四个字符 "PLEA" 手工验算一下:
加密过程:
[M=egin{bmatrix}
{3} & {13}&{21}&{9} \
{15}&{10}&{6}&{25}\
{10}&{17}&{4}&{8}\
{1}&{23}&{7}&{2}
end{bmatrix}*
egin{bmatrix}
{15}\
{11}\
{4}\
{0}
end{bmatrix}=
egin{bmatrix}
{272}\{359}\{353}\{296}
end{bmatrix}
+Begin{bmatrix}
{1}\{21}\{8}\{17}
end{bmatrix}=
egin{bmatrix}
{273}\{380}\{361}\{313}
end{bmatrix}
mod 26=
egin{bmatrix}
{13}\{16}\{23}\{1}
end{bmatrix}
=egin{bmatrix}
{'N'}\{'Q'}\{'X'}\{'B'}
end{bmatrix}
]
解密过程:
[C=(egin{bmatrix}
{13}\{16}\{23}\{1}
end{bmatrix}
-egin{bmatrix}
{1}\{21}\{8}\{17}
end{bmatrix})=
egin{bmatrix}
{12}\{-5}\{15}\{-16}
end{bmatrix}*
egin{bmatrix}
{26} & {13}&{20}&{5} \
{0}&{10}&{11}&{0}\
{9}&{11}&{15}&{22}\
{9}&{22}&{6}&{25}
end{bmatrix}=
egin{bmatrix}
{935}\{375}\{784}\{910}
end{bmatrix}mod 26=
egin{bmatrix}
{'Z'}\{'L'}\{'E'}\{'A'}
end{bmatrix}
]
说明算法没有任何问题,那么问题就在问题本身了。
将给定的 (A) 与 (A^{-1}) 进行乘法运算:
[A*A^{-1}=egin{bmatrix}
{3} & {13}&{21}&{9} \
{15}&{10}&{6}&{25}\
{10}&{17}&{4}&{8}\
{1}&{23}&{7}&{2}
end{bmatrix}*
egin{bmatrix}
{26} & {13}&{20}&{5} \
{0}&{10}&{11}&{0}\
{9}&{11}&{15}&{22}\
{9}&{22}&{6}&{25}
end{bmatrix}=
egin{bmatrix}
{348} & {598} & {572}& {702}\
{669}& {911}& {650}& {832}\
{368}& {520}& {495}& {338}\
{107}& {364}& {390}& {209}
end{bmatrix}
]
而结果矩阵 mod 26 并不是单位矩阵,经过计算,正确的 (A^{-1}=)
[egin{bmatrix}
{23} & {13}&{20}&{5} \
{0}&{10}&{11}&{0}\
{9}&{11}&{15}&{22}\
{9}&{22}&{6}&{25}
end{bmatrix}
]
再次带入程序验证:
- 感谢现代密码学编者让我浪费的两小时。
以《现代密码学》习题 1.4 为例:
首先求出
[C=egin{bmatrix}
{3}\{14}\{13}\{19}
end{bmatrix},
M=egin{bmatrix}
{4}\{11}\{13}\{8}
end{bmatrix}
]
设
[A=egin{bmatrix}
{a}&{b}\{c}&{d}
end{bmatrix}有
egin{bmatrix}
{3}\{14}
end{bmatrix}*
egin{bmatrix}
{a}&{b}\{c}&{d}
end{bmatrix}=egin{bmatrix}
{4}\{11}
end{bmatrix},
egin{bmatrix}
{13}\{19}
end{bmatrix}*
egin{bmatrix}
{a}&{b}\{c}&{d}
end{bmatrix}=egin{bmatrix}
{4}\{11}
end{bmatrix}
]
可得
[egin{cases}
{3*a+14*b≡4(mod 26)} &{①}\
{3*c+14*d≡11(mod 26)}&{②}\
{13*a+19*b≡13(mod 26)}&{③}\
{13*c+19*d≡8(mod 26)}&{④}
end{cases}
]
下面给出 b 的解法:
[将①与③联立化简得125b≡13(mod 26)\(5*26-5)b≡13(mod 26)\-5b≡13(mod 26)\-5*5b≡13*5(mod 26)\\-(26-1)b≡13(mod 26)\b≡13(mod 26)\ 得 b=13。
]
同理解得:
[A=egin{bmatrix}
{10}&{13}\{9}&{23}
end{bmatrix}
]