iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 11
0
自我挑戰組

資訊工程大補帖系列 第 11

資工補帖-Day 11-密碼學之 VigenereCipher , LFSR

  • 分享至 

  • xImage
  •  

正文

修密碼學的時候課堂要練習 VigenereCipher , LFSR
那時候利用 Java 完成作業,不過後來我自己還是比較習慣 Python XD
也不知道為什麼要用 Java XD

Vigenere Cipher

  • 維吉尼亞加密
  • 古典加密法
  • 利用取代(substitution)的加密技術─用字元來取代原先的字元
  • 我自己常用的網站 vigenere-cipher
    • 密文:Cadgk Et jsha an bwd
    • ALPHABET:ABCDEFGHIJKLMNOPQRSTUVWXYZ
    • 密碼:FEI
    • 明文:Hello My name is fei
package cryptography;

import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.FileWriter;

public class VigenereCipher {

	public static void main(String[] args) throws IOException {
		
		System.out.println("=================加密=================");
		FileReader fr = new FileReader("Plaintext.txt"); // 讀取txt檔
		BufferedReader br = new BufferedReader(fr); // 取得檔案裡面輸入的文字
        
		String strNum;
		FileWriter fw = new FileWriter("cyphertext.txt"); // 新增檔案
		while ((strNum = br.readLine()) != null) {
			
			String key = "Keyisyes";
			String ori = strNum;
			String enc = encrypt(ori, changeSid(key)); // 使用changeSid()換成全英文字母的key

			System.out.println("KEY :" + key); // 印出金鑰
			System.out.println("加密>>" + enc + "\r\n"); // 印出密文
			fw.write(enc + "\r\n"); // 將密文寫入檔案
		}
		fr.close();
		fw.close();


		System.out.println("=================解密=================");
		FileReader fr4 = new FileReader("cyphertext.txt"); // 讀取txt檔


		BufferedReader br4 = new BufferedReader(fr4); // 取得檔案裡面輸入的文字


		String strNum4;
		while ((strNum4 = br4.readLine()) != null) {
			
			String key = "Keyisyes"; 
			String enc = strNum4;

			System.out.println("KEY : " + key); // 印出金鑰
			System.out.println("加密>>" + enc); // 印出密文
			System.out.println("解密(原)>>" + decrypt(enc, changeSid(key)) + "\r\n"); // 印出明文
		}
		fr4.close();



		System.out.println("====================================");
	}

	static String encrypt(String text, final String key) // 加密函式, final可鎖定key的值
	{
		String res = "";
		text = text.toUpperCase(); // 把字母都換成大寫方便進行加密
		for (int a = 0, b = 0; a < text.length(); a++) // 用for迴圈取得每個字母
		{
			char c = text.charAt(a); // 取得的字母放在c

			if (c < 'A' || c > 'Z')
				continue; // 檢查明文是否均為大寫英文字母

			res += (char) ((c + key.charAt(b) - 2 * 'A') % 26 + 'A');
			// 因為ASCII code decimal format 要進行-2A+A
			b = ++b % key.length();
			// key沒比明文長的話就繼續把key放後面做加密(用來對key循環)
		}
		return res;
	}

	static String decrypt(String text, final String key) // 解密函式, final可鎖定key的值
	{
		String res = "";
		text = text.toUpperCase(); // 把字母都換成大寫方便進行加密
		for (int a = 0, j = 0; a < text.length(); a++) // 用for迴圈取得每個字母
		{
			char c = text.charAt(a); // 取得的字母放在c

			if (c < 'A' || c > 'Z')
				continue; // 檢查密文是否均為大寫英文字母

			res += (char) ((c - key.charAt(j) + 26) % 26 + 'A'); // 將密文減掉key(+26避免為負數)
			j = ++j % key.length(); // key沒比密文長的話就繼續把key放後面做解密(用來對key循環)
		}
		return res;
	}

	static String changeSid(String s) {
		
		String key = "";
		int[] intArray = new int[s.length()];
		for (int i = 0; i < s.length(); i++) {
			
			intArray[i] = s.charAt(i);
			if (intArray[i] >= 65 && intArray[i] <= 90) {
				
				key += (char) intArray[i];
			} 
			else if (intArray[i] >= 48 && intArray[i] <= 57) {
				
				key += (char) (intArray[i] + 17);
			} 
			else {
				
				continue;
			}
		}
		return key;
	}

}


LFSR

  • Linear feedback shift register
  • 移位暫存器
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Scanner;

public class LFSR {

	public static void main(String[] args) {

		Scanner scannerobj = new Scanner(System.in);

		/* 讀取明文檔(位置) */
		System.out.println("Please input your plaintext's filepath : ");
		String fileInputPath = scannerobj.nextLine();

		/* (拋例外)如果抓不到明文檔 */
		Scanner fileInput = null;

		try {
			
			fileInput = new Scanner(new FileInputStream(fileInputPath));
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
		}

		/* 讀取輸出檔(位置) */
		System.out.println("Please output your plaintext's filepath : ");
		String fileOutputPath = scannerobj.nextLine();

		/* (拋例外)如果抓不到密文檔 */
		PrintWriter fileOutput = null;

		try {
			
			fileOutput = new PrintWriter(new FileOutputStream(fileOutputPath));
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
		}

		/* 輸入回饋暫存器 並且用空格分開 先讀一行字串 進行切割 並且轉換成整數陣列 */
		System.out.print("輸入回饋值並且用空格分開:");
		boolean error = false;
		String feedBackString;
		int[] feedBack;
		String[] feedBackdata;
		int x;
		do {
			
			x = 0;
			error = false;
			feedBackString = scannerobj.nextLine();
			feedBackdata = feedBackString.split(" ");
			feedBack = new int[feedBackdata.length];
			for (int i = 0; i < feedBackdata.length; i++) {
				
				// 加上try catch,防止被非數字的字元弄壞
				try {
					
					feedBack[i] = Integer.parseInt(feedBackdata[i]);
					if (feedBack[i] > 7 || feedBack[i] < 0) {
						
						System.out.println("您輸入錯誤的回饋暫存器(不得超出範圍,最大為b\"7\"),請重新輸入所有暫存器 ");
						error = true;
						break;
					}
					else{
						
						x++;
					}
					
					if (x > 8) {
						
						System.out.println("您輸入錯誤的回饋暫存器(不得重複輸入),請重新輸入所有暫存器 ");
						error = true;
						break;
					}
					// 一個錯就算錯,所以不用在迴圈內重設error
				} catch (NumberFormatException exception) {
					
					System.out.println("您輸入錯誤的回饋暫存器(僅能輸入數字),請重新輸入所有暫存器 ");
					error = true;
					break;
				}
			}
		} while (error);

		/* 尋找最大的暫存器 */
		/*int feedMax = 0;
		for (int i = 0; i < feedBack.length; i++) {
			
			if (feedBack[i] >= feedMax)
				feedMax = feedBack[i] + 1;
		}*/

		/* 輸入種子值 並且用空格分開 先讀一行字串 進行切割 並且倒著轉換成整數陣列 */
		System.out.print("輸入種子並且用空格分開: ");
		boolean error2 = false;
		String seedString;
		int[] seed;
		String[] seeddata;
		do {
			
			error2 = false;
			seedString = scannerobj.nextLine();
			seeddata = seedString.split(" ");
			seed = new int[seeddata.length + 1];
			for (int i = 7, j = 0; i >= 0 && j < seeddata.length; i--, j++) {
				
				if (seeddata.length != 8) {
					
					System.out.println("您輸入錯誤的種子(數量不符),請重新輸入所有種子 ");
					error2 = true;
					break;
				}
				
				// 加上try catch,防止被非數字的字元弄壞
				try {
					
					seed[i] = Integer.parseInt(seeddata[j]);
					if (seed[i] != 1 && seed[i] != 0) {
						
						System.out.println("您輸入錯誤的種子(僅能輸入0或1),請重新輸入所有種子 ");
						error2 = true;
						break;
					}
					
					// 一個錯就算錯,所以不用在迴圈內重設error
				} catch (NumberFormatException exception) {
					
					System.out.println("您輸入錯誤的種子(僅能輸入數字),請重新輸入所有種子 ");
					error2 = true;
					break;
				}
			}
		} while (error2);

		/*完成所有seed存放(放入seed[feedMax])*/
		int a = 0;
		for(int k = 0; k < feedBack.length; k++){
			
			if(k==0){
				
				a = seed[feedBack[k]];
			}
			else{
						
				a = a ^ seed[feedBack[k]];
			}
		}
		//(ex : b4 = b2 XOR b0) >> 算出b"4" = "feedMax"
		seed[8] = a;
	
		/* 開始計算 (加密)*/
		int key, addC;
		String ciphertext = "";
		String allKey = "";
		String p = "";
		while(fileInput.hasNext()){
			
			p = fileInput.nextLine();
			for(int i = 0; i <= p.length(); i++){
				
				if(i != 0){
					//key = 最右邊的seed(移出)
					key = seed[0];
					for(int j = 0; j < seed.length; j++){
						
						if(j == seed.length - 1){
							
							a = 0;
							for(int k = 0; k < feedBack.length; k++){
								
								if(k==0){
									
									a = seed[feedBack[k]];
								}
								else{
											
									a = a ^ seed[feedBack[k]];
								}
							}
							//(ex : b4 = b2 XOR b0) >> 算出b"4" = "max"
							seed[8] = a;
						}
						else{
							//其他seed為原seed右移一位
							seed[j] = seed[j + 1];
						}
					}
					//得密文
					addC = Integer.parseInt(p.substring(i-1,i)) ^ key;
					//紀錄key
					allKey = allKey + key;
					//紀錄密文
					ciphertext = ciphertext + addC;
				}
			}
			//將密文寫入輸出檔
			fileOutput.println(ciphertext);
		}
		
		/*直接檢查密文*/
		System.out.println("===================================================");
		System.out.println("The plaintext is : ");
		//印出密文
		System.out.println(">>" + p);
		
		System.out.println("The key is : ");
		//印出密文
		System.out.println(">>" + allKey);
		
		System.out.println("The ciphertext is : ");
		//印出密文
		System.out.println(">>" + ciphertext);
		
		/* 關閉 */
		fileInput.close();
		fileOutput.close();
		scannerobj.close();

	}

}

上一篇
資工補帖-Day 10-計算機概論 (C++)
下一篇
資工補帖-Day 12-Web程式設計
系列文
資訊工程大補帖30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言