以《现代密码学》习题1.3为例:
设多表代换密码中:
\[ A=\begin{bmatrix} {3} & {13}&{21}&{9} \\ {15}&{10}&{6}&{25}\\ {10}&{17}&{4}&{8}\\ {1}&{23}&{7}&{2} \end{bmatrix} , B=\begin{bmatrix} {1}\\{21}\\{8}\\{17} \end{bmatrix} \]
加密为:\(C_i≡A{M_i}+\textbf{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-\textbf{B})(mod\ 26)\)
验证你的结果,其中
\[ A^{-1}=\begin{bmatrix} {26} & {13}&{20}&{5} \\ {0}&{10}&{11}&{0}\\ {9}&{11}&{15}&{22}\\ {9}&{22}&{6}&{25} \end{bmatrix} \]
- 根据书 1.4.2 ,先将字符串中空格去除,再取N位的字串,进行矩阵乘法,最后再把空格加上,输出。
例 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=\begin{bmatrix} {3} & {13}&{21}&{9} \\ {15}&{10}&{6}&{25}\\ {10}&{17}&{4}&{8}\\ {1}&{23}&{7}&{2} \end{bmatrix}* \begin{bmatrix} {15}\\ {11}\\ {4}\\ {0} \end{bmatrix}= \begin{bmatrix} {272}\\{359}\\{353}\\{296} \end{bmatrix} +B\begin{bmatrix} {1}\\{21}\\{8}\\{17} \end{bmatrix}= \begin{bmatrix} {273}\\{380}\\{361}\\{313} \end{bmatrix} mod\ 26= \begin{bmatrix} {13}\\{16}\\{23}\\{1} \end{bmatrix} =\begin{bmatrix} {'N'}\\{'Q'}\\{'X'}\\{'B'} \end{bmatrix} \]
解密过程:
\[ C=(\begin{bmatrix} {13}\\{16}\\{23}\\{1} \end{bmatrix} -\begin{bmatrix} {1}\\{21}\\{8}\\{17} \end{bmatrix})= \begin{bmatrix} {12}\\{-5}\\{15}\\{-16} \end{bmatrix}* \begin{bmatrix} {26} & {13}&{20}&{5} \\ {0}&{10}&{11}&{0}\\ {9}&{11}&{15}&{22}\\ {9}&{22}&{6}&{25} \end{bmatrix}= \begin{bmatrix} {935}\\{375}\\{784}\\{910} \end{bmatrix}mod\ 26= \begin{bmatrix} {'Z'}\\{'L'}\\{'E'}\\{'A'} \end{bmatrix} \]
说明算法没有任何问题,那么问题就在问题本身了。
将给定的\(A\)与\(A^{-1}\)进行乘法运算:
\[ A*A^{-1}=\begin{bmatrix} {3} & {13}&{21}&{9} \\ {15}&{10}&{6}&{25}\\ {10}&{17}&{4}&{8}\\ {1}&{23}&{7}&{2} \end{bmatrix}* \begin{bmatrix} {26} & {13}&{20}&{5} \\ {0}&{10}&{11}&{0}\\ {9}&{11}&{15}&{22}\\ {9}&{22}&{6}&{25} \end{bmatrix}= \begin{bmatrix} {348} & {598} & {572}& {702}\\ {669}& {911}& {650}& {832}\\ {368}& {520}& {495}& {338}\\ {107}& {364}& {390}& {209} \end{bmatrix} \]
而结果矩阵mod26并不是单位矩阵,经过计算,正确的\(A^{-1}=\)
\[ \begin{bmatrix} {23} & {13}&{20}&{5} \\ {0}&{10}&{11}&{0}\\ {9}&{11}&{15}&{22}\\ {9}&{22}&{6}&{25} \end{bmatrix} \]
再次带入程序验证:
感谢现代密码学编者让我浪费的两小时。