修密碼學的時候課堂要練習 VigenereCipher , LFSR
那時候利用 Java 完成作業,不過後來我自己還是比較習慣 Python XD
也不知道為什麼要用 Java XD
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;
}
}
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();
}
}