經典密碼學——行置換加密法?

Tags: 經典, 密碼學,

很多教材上對於行置換密碼、列置換密碼的定義都不是完全相同,甚至核心思想根本不一樣。筆者就自己學習的經歷,簡單介紹一種一些教材上所謂的“行置換密碼”的演算法,大家一起交流、探討。

利用這種加密方法,明文按行填寫在一個矩陣中,而明文則是以預定的順序按列讀取生成的。例如如果矩陣是4列5行,那麼明文“encryption algorithm”(省去空格後)可以如下寫入該矩陣:

2 3 1 4

e n c r

y p t i

o n a l

g o r i

t h m s

按一定的順序讀取列以生成密文。

對於這個示例,如果讀取順序為遞增順序,則明文就是:“ctarm eyogt npnoh rilis”(新增空格只是為了便於觀察)。這種加密法的金鑰是列數和讀取列的順序。如果列數很多,記起來可能會比較困難,因此它可以表示成一個關鍵詞,該關鍵詞的長度等於列數,而其字母順序決定讀取列的順序。

例如,關鍵詞“general”有7個字母,意味著矩陣有7列。由於“a”是“general”中字母順序最低的,因此數字1放在第6列;從左往右,第一個“e”為其次,所以數字2放在第2列;第二個“e”則是使數字3放在第4列。最後的順序如下:

g e n e r a l

4 2 6 3 7 1 5

_______________________________________________________________________________________

This scheme is to write the message in a rectangle, row by row, and read the message off, column by column, but permute the order of the columns.The order of the columns then becomes the key to the algorithm.For example,

Key: 4 3 1 2 5 6 7

Plaintext: a t t a c k p

o s t p o n e

d u n t i l t

w o a m x y z

Ciphertext: ttna aptm tsuo aodw coix knly petz (再次強調,空格只是為了便於觀察)

Thus, in this example, the key is 4312567.To encrypt, start with the column that is labeled 1, in this case column 3. Write down all the letters in that column.

**************************************************************************************

上述的是一次加密,也可把上述密文當做新一輪加密的明文,再次進行行置換加密。

參考資料:

《Cryptography and Network Security Principles and Practice, Fifth Edition》

————William Stallings

《Classical And Contemporary Cryptology》 ————Richard Spillman

//Z26上的行置換密碼

#include

#include

#include

#include

int length;//明文長度

char plain[100000];

char cipher[100000];

char out[100000];

int l;//金鑰長度

int key[100];//金鑰

int done_key[100]= {0}; //標記是否已經被轉換為數字

int num_key[100]= {0};//把金鑰換成數字

int num[100];//臨時矩陣,存放使順序遞增的下標序號

void gen();//金鑰生成演算法

void encryption();

void decryption();

int length_str(int a[]);

int main()

{

int i;

FILE *fp;

fp=fopen("plain.txt", "r");

fscanf(fp, "%s", plain);//從檔案讀入明文

fclose(fp);

length=strlen(plain);

gen();

encryption();

printf("以上正確");

decryption();

for(i=0;i

{

printf("%c", out[i]);

}

return 0;

}

void gen()//金鑰生成演算法

{

int i;

printf("請輸入想生成的隨機金鑰的長度:");

scanf("%d", &l);

srand(time(0));

for(i=0; i

{

key[i]=rand()%26;

}

printf("
隨機產生的金鑰串為:");

for(i=0; i

{

printf("%c ", key[i]+97);

}

printf("

");

}

char a[50000][100];//臨時矩陣,為了更方便的把密文轉換出來

//這個陣列必須設定為全域性的,在函式中宣告的話申請記憶體會出錯!!!

void encryption()

{

///轉換:把金鑰字串排序,變成數字

int k=1;

int i, j, m;

int small;//每輪迴圈給"最小"的字母編號(未編號的、靠前的、序號小的字母為最小)

for(i=0; i

{

m=0;

while(done_key[m]==1)

m++;

small=m;

for(j=0; j

{

if(done_key[j]==0)//沒轉換則繼續

if(key[j]

small=j;

}

num_key[small]=k;

done_key[small]=1;

k++;

}//

printf("The order of the key is :
");

for(i=0; i

{

printf("%d ", num_key[i]);

}

printf("
");

for(i=0; i

{

if(plain[i]>=65&&plain[i]<=90)

{

plain[i]+=32;

}

}

while(length%l)

{

strcat(plain,"p");//不能整除時補上無效字元p

length++;

}

//生成密文矩陣

k=0;

for(i=0; i

for(j=0; j

{

a[i][j]=plain[k++];

}

k=0;

for(i=0;i

{

for(j=0;j

if(num_key[j]==i+1)

num[i]=j;

}

k=0;

for(m=0;m

for(j=0;j

cipher[k++]=a[j][num[m]];

}

char b[50000][100];

void decryption()//解密函式

{

int i, j, k;

k=0;

for(i=0;i

for(j=0;j

b[j][num[i]]=cipher[k++];

k=0;

for(i=0;i

for(j=0;j

out[k++]=b[i][j];

}

//同文件夾下需要有“plain.txt”檔案,裡面必須全部是英文字母,可大小寫混雜,但是不能出現其他字元,如空格、回車換行、數字等。

相關問題答案