多表代換密碼


以《現代密碼學》習題 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 位(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=\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} \]

而結果矩陣 mod 26 並不是單位矩陣,經過計算,正確的 \(A^{-1}=\)

\[\begin{bmatrix} {23} & {13}&{20}&{5} \\ {0}&{10}&{11}&{0}\\ {9}&{11}&{15}&{22}\\ {9}&{22}&{6}&{25} \end{bmatrix} \]

再次帶入程序驗證:

  • 感謝現代密碼學編者讓我浪費的兩小時。

以《現代密碼學》習題 1.4 為例:

首先求出

\[C=\begin{bmatrix} {3}\\{14}\\{13}\\{19} \end{bmatrix}, M=\begin{bmatrix} {4}\\{11}\\{13}\\{8} \end{bmatrix} \]

\[A=\begin{bmatrix} {a}&{b}\\{c}&{d} \end{bmatrix}有 \begin{bmatrix} {3}\\{14} \end{bmatrix}* \begin{bmatrix} {a}&{b}\\{c}&{d} \end{bmatrix}=\begin{bmatrix} {4}\\{11} \end{bmatrix}, \begin{bmatrix} {13}\\{19} \end{bmatrix}* \begin{bmatrix} {a}&{b}\\{c}&{d} \end{bmatrix}=\begin{bmatrix} {4}\\{11} \end{bmatrix} \]

可得

\[\begin{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=\begin{bmatrix} {10}&{13}\\{9}&{23} \end{bmatrix} \]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM