古典密碼算法的實現


1、古典密碼可以分為代替密碼和置換密碼兩種,這里實現了代替密碼中的仿射變換和置換密碼中的換位變換。

 

2、仿射變換:

加密過程:e(x) = ax + b (mod m)

解密過程:d(e(x)) = a^(-1)*(e(x) - b) mod m

參數要求:a,m互質;a,b互質;m是集合中元素的個數。(例如當前取1~9和a~z中的所有元素作為集合,m為36)

加密實現:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String []args) {
 5         int m = 36, thisNum, index = 0; // m是集合中元素的個數(例如當前取1~9和a~z中的所有元素作為集合,m為36)
 6         Scanner s = new Scanner(System.in);
 7         // 將輸入的字符串轉化為字符數組
 8         char[] buff = s.nextLine().toCharArray();
 9         // 參數a、b手動輸入
10         int a = s.nextInt();
11         int b = s.nextInt();
12         // 參數要求:a,m互質;a,b互質
13         while (fun1(m, a) != 1 || fun1(Math.max(a, b), Math.min(a, b)) != 1) {
14             System.out.println("參數不符合要求,請重新輸入");
15             a = s.nextInt();
16             b = s.nextInt();
17         }
18         for (char i : buff) {
19             // 由字符轉換為數字
20             if (i > '9') thisNum = (int)i - 87;
21             else thisNum = (int)i - 48;
22             // 對該數字加密
23             thisNum = (thisNum*a+b)%m;
24             // 加密后再將數字轉換為字符
25             if (thisNum < 10) buff[index++] = (char)(thisNum+48);
26             else buff[index++] = (char)(thisNum+87);
27         }
28         System.out.println(buff);
29         s.close();
30     }
31 
32     // 歐幾里得算法求兩個數的最大公因數
33     public static int fun1(int a, int b) {
34         return b == 0 ? a : fun1(b, a%b);
35     }
36 }

解密實現:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String []args) {
 5         int m = 36, thisNum, index = 0, k;
 6         Scanner s = new Scanner(System.in);
 7         char[] buff = s.nextLine().toCharArray();
 8         int a = s.nextInt();
 9         int b = s.nextInt();
10         while (fun1(m, a) != 1 || fun1(Math.max(a, b), Math.min(a, b)) != 1) {
11             System.out.println("參數不符合要求,請重新輸入");
12             a = s.nextInt();
13             b = s.nextInt();
14         }
15         // k為a模m的逆元
16         k = fun2(a, m);
17         for (char i : buff) {
18             // 將加密后的字符轉換為數字
19             if (i > '9') thisNum = (int)i - 87;
20             else thisNum = (int)i - 48;
21             // 解密過程 D(E(x)) = a^(-1)*(E(x)-b) mod m
22             thisNum = ((thisNum-b)*k)%m;
23             // 如果結果是負數,則轉換為正數,原理為 a % b = (a % b + b) % b
24             if(thisNum < 0) thisNum += m;
25             // 最后將解密后的數字轉換為字符
26             if (thisNum < 10) buff[index++] = (char)(thisNum+48);
27             else buff[index++] = (char)(thisNum+87);
28         }
29         System.out.println(buff);
30     }
31 
32     public static int fun1(int a, int b) {
33         return b == 0 ? a : fun1(b, a%b);
34     }
35 
36     // 循環求a模m的逆元
37     public static int fun2(int a, int m) {
38         for (int i = 0; i < m; i++) {
39             if (a*i%m == 1) {
40                 a = i;
41                 break;
42             }
43         }
44         return a;
45     }
46 }

 

3、換位密碼

加密過程:保持明文的所有字符不變,根據一定的規則重新排列明文。

解密過程:加密過程的逆過程。

注解:加密過程和解密過程都是創建索引的過程,即用數組存儲哪個位置放哪個字符,最后再通過索引重新組合成密文或明文。

示例:

明文矩陣:
a s d f g
h j k l m
n b v c

密文矩陣:
d a g s f
k h m j l
v n b c

(計算結果中n和b之間有一個空格,但輸出時將空格去掉了)

明文:asdfghjklmnbvc
密鑰:31524

加密實現:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String []args) {
 5         Scanner s = new Scanner(System.in);
 6         char[] mingwen = s.nextLine().toCharArray();
 7         char[] miyao = s.nextLine().toCharArray();
 8         StringBuffer miwen = new StringBuffer();
 9         int[] poi = new int[miyao.length];
10         int index = 0, thisRow = 0, realPoi;
11 
12         // 計算出明文矩陣的列數和行數
13         int col = miyao.length;
14         int row = (mingwen.length / col) + (mingwen.length % col == 0? 0 : 1);  // 處理明文矩陣最后一行可能不滿的情況
15         
16         // 密鑰位置格式化(密鑰中的所有字符都大於等於'1'所以最后減1方便后續計算)
17         for (int i = 0; i < poi.length; i++) poi[i] = miyao[i] - 48 - 1;
18 
19 
20         for (int i = 0; i < row * col; i++) {
21             // 計算出當前位置i的真正字符(例如加密后第0位為2,即字符d),如果該字符在明文中存在,則將其添加到密文中
22             if ((realPoi = poi[index++] + thisRow * col) < mingwen.length) miwen.append(mingwen[realPoi]);
23             // 如果當前位置無字符則用空格代替
24             else miwen.append(' ');
25             
26             if (index >= col) {
27                 index = index % col;
28                 thisRow++;
29             }
30         }
31 
32         // 密文去空格(解密時密文中的空格需要保留)
33         for (int i = 0; i < miwen.length(); i++) {
34             if (miwen.charAt(i) == ' ') miwen.deleteCharAt(i);
35         }
36 
37         // 輸出加密后的密文
38         System.out.println(miwen);
39     }
40 }

解密實現:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String []args) {
 5         Scanner s = new Scanner(System.in);
 6         char[] miwen = s.nextLine().toCharArray();
 7         char[] miyao = s.nextLine().toCharArray();
 8         StringBuffer mingwen = new StringBuffer();
 9         int []poi = new int[miyao.length];
10         int index = 0, thisRow = 0, realPoi;
11 
12         // 獲取解密密鑰並將密鑰的位置格式化(最后減一),即加密的逆過程
13         for (char c : miyao) {
14             poi[(int)c - 48 - 1] = index++;
15         }
16         index = 0;
17 
18         // 密文矩陣的列數和行數
19         int col = miyao.length;
20         int row = (miwen.length / col) + (miwen.length % col == 0? 0 : 1);
21 
22         for (int i = 0; i < row * col; i++) {
23             // 計算出當前位置i的真正字符並將該字符添加到明文字符串中
24             if ((realPoi = poi[index++] + thisRow * col) < miwen.length) mingwen.append(miwen[realPoi]);
25             
26             if (index >= col) {
27                 index = index % col;
28                 thisRow++;
29             }
30         }
31 
32         // 輸出解密后的明文
33         System.out.println(mingwen);
34     }
35 }

 

4、希爾密碼(Hill密碼)- 屬於古典密碼中的多表代換密碼,運用了基本的矩陣論原理

注解:

1)每個字母當作 26 進制數字:a=0, b=1, c=2... 一串字母當成n維向量,跟一個n×n的矩陣相乘,再將得出的結果模 26。用作加密的矩陣(即密匙)必須是可逆的,否則就不可能譯碼。只有矩陣的行列式和 26 互質,才是可逆的。

2)明文和密文的長度必須是給定的矩陣的列數的整數倍。(矩陣相乘的前提)

加密過程:將明文轉化為n維向量(字符轉數字)與n×n的矩陣相乘,再將得出的結果模 26 后轉化為字符。

解密過程:將明文轉化為n維向量(字符轉數字)與n×n的矩陣相乘,再將得出的結果模 26 后轉化為字符。

加密實現:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         // 三階可逆矩陣A
 6         int[][] A = { { 1, 2, 3 }, { 1, 1, 2 }, { 0, 1, 2 } };
 7 
 8         Scanner s = new Scanner(System.in);
 9         char[] mingwen = s.nextLine().toCharArray();
10         char[] miwen = new char[mingwen.length];
11         int row = 3, col = mingwen.length / 3, index = 0;
12 
13         while (index < col) {
14             int sum;
15             for (int i = 0; i < row; i++) {
16                 sum = 0;
17                 for (int j = 0; j < row; j++) {
18                     sum += A[i][j] * (int) (mingwen[j+index*row] - 97);
19                 }
20                 sum %= 26;
21                 if (sum < 0) sum += 26;
22                 miwen[i + index*row] = (char) (sum + 97);
23             }
24             index++;
25         }
26 
27         for (char c : miwen) {
28             System.out.print(c);
29         }
30     }
31 }

解密實現:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         // A的逆矩陣
 6         int[][] A_1 = {{0, 1, -1}, {2, -2, -1}, {-1, 1, 1}};
 7 
 8         Scanner s = new Scanner(System.in);
 9         char[] miwen = s.nextLine().toCharArray();
10         char[] mingwen = new char[miwen.length];
11         int row = 3, col = mingwen.length / 3, index = 0;
12 
13         while (index < col) {
14             int sum;
15             for (int i = 0; i < 3; i++) {
16                 sum = 0;
17                 for (int j = 0; j < 3; j++) {
18                     sum += A_1[i][j] * (int)(miwen[j+index*row] - 97);
19                 }
20                 sum %= 26;
21                 if (sum < 0) sum += 26;
22                 mingwen[i+index*row] = (char)(sum+97);
23             }
24             index++;
25         }
26 
27         for(char c : mingwen) {
28             System.out.print(c);
29         }
30     }
31 }

 


免責聲明!

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



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