1. 凱撒加密演算法 1.1 演算法邏輯 根據一個固定偏移值(offset), 將字母向一個方向偏移, 進行加密. 1.2 初步思路 獲取明文(plaintext) 獲取明文字元串的單獨字元 進行字元值偏移 當偏移超出字母範圍時, 回到第一個字母處繼續偏移. 得到密文(ciphertext) 1.3 初 ...
1. 凱撒加密演算法
1.1 演算法邏輯
根據一個固定偏移值(offset
), 將字母向一個方向偏移, 進行加密.
1.2 初步思路
- 獲取明文(
plaintext
) - 獲取明文字元串的單獨字元
- 進行字元值偏移
- 當偏移超出字母範圍時, 回到第一個字母處繼續偏移.
- 得到密文(
ciphertext
)
1.3 初步編程
/*
凱撒密碼:
偏移量
A(65)~Z(90)
a(97)~z(122)
方法1: 但偏移量超過範圍時, 返回到最初迴圈
方法二:進行數組偏移(加密)
方法三:進行數組回位(解密)
*/
public class Task01_Caesar {
public static void main(String[] args) {
// 輸入明文
String plaintext = "I told it was a lie. ";
// 明文加密
String password = leadingPlaintext(plaintext, 10);
System.out.println(password);
// 密文解密
String plaintext1 = leadingPassword(password, 10);
System.out.println(plaintext1);
}
// 凱撒密碼加密
public static String leadingPlaintext(String plaintext, int leadingNum) {
String password = "";
// 將明文轉化成字元數組
char[] charPassword = plaintext.toCharArray();
// 進行加密操作
int[] intPassword = new int[charPassword.length];
for (int i = 0; i < charPassword.length; i++) {
// 將字元數組轉化成字元碼數組
intPassword[i] = (int)charPassword[i];
// 字元碼數組偏移&範圍限定
intPassword[i] = limitLetter(intPassword[i], intPassword[i]+leadingNum);
// 偏移字元碼數組重新輸出為字元數組
charPassword[i] = (char)intPassword[i];
// 將字元數組轉化成字元串
password = String.valueOf(charPassword);
}
return password;
}
// 凱撒密碼解密
public static String leadingPassword(String password, int leadingNum) {
String plaintext = "";
// 將密碼轉化成字元數組
char[] charPassword = password.toCharArray();
// 進行解密操作
int[] intPassword = new int[charPassword.length];
for (int i = 0; i < charPassword.length; i++) {
// 將字元數組轉化成字元碼數組
intPassword[i] = (int)charPassword[i];
// 字元碼數組偏移&範圍限定
intPassword[i] = limitLetter(intPassword[i], intPassword[i]-leadingNum);
// 偏移字元碼數組重新輸出為字元數組
charPassword[i] = (char)intPassword[i];
// 將字元數組轉化成字元串
plaintext = String.valueOf(charPassword);
}
return plaintext;
}
// 進行範圍限定
public static int limitArea(int num, int min, int max) {
int area = 26; // 限定範圍區間
while (num < min || num > max) {
if (num < min) {
num += area;
} else if (num > max) {
num -= area;
}
}
return num;
}
// 進行字母範圍限定
public static int limitLetter(int originNum, int leadingNum) {
if (originNum >=65 && originNum <= 90) {
leadingNum = limitArea(leadingNum, 65, 90);
} else if (originNum >= 97 && originNum <= 122) {
leadingNum = limitArea(leadingNum, 97, 122);
}
return leadingNum;
}
}
我的思路是:
- 首先將字元串轉化為字元數組
- 字元數組可以轉化為整型數組
- 對數組進行偏移
- 對偏移的數組進行校正
- 將數組重新返回為字元串
然後我使用了4個方法, 第一個方法(leadingPlaintext
)和第二個方法(leadingPassword
)進行數組偏移, 其中調用了第三, 四個方法進行偏移數組校正.
1.4 查詢演算法
public class Task02_Caesar {
public static void main(String[] args) {
String plaintext = "I'm a robot. ";
String pwd = caesar(plaintext, 5);
String str = caesar(pwd, -5);
System.out.println(pwd);
System.out.println(str);
}
public static String caesar(String text, int offset) {
String cipher = "";
for (int i = 0; i < text.length(); i++) {
// 迭代字元
char c = text.charAt(i);
if (c >= 'A' && c <= 'Z') { // 若當前選中字元為大寫字母
c += (offset % 26);
if (c < 'A') {
c += 26;
} else if (c > 'Z') {
c -= 26;
}
} else if (c >= 'a' && c <= 'z') { // 若當前選中字元為小寫字母
c += (offset % 26);
if (c < 'a') {
c += 26;
} else if (c > 'z') {
c -= 26;
}
}
cipher += c;
}
return cipher;
}
}
1.5 思路重置
- 不需要將字元串轉化為字元數組, 可以通過
String.charAt()
方法在for迴圈里直接獲取單獨的字元. 不需要使用String.toCharArray()
方法將字元串轉化為字元數組. - 因為字元char本質其實是數字, 所以可以直接使用char進行邏輯判斷, 不需要將其轉換為數字碼點再判斷.
- 當需要框定一個數的範圍, 進行A-B迴圈時, 可以通過取餘操作進行限定.
b = (b % 26)+1
(限定範圍1~26的數字)
1.6 A-B迴圈
/*
* description: 1~26迴圈數輸出
*/
public class Task03_ABLoop {
public static void main(String[] args) {
for (int i = 0; i <= 100; i++) {
System.out.print(i%26+1+" ");
if (i%26+1 == 26) {
System.out.println();
}
}
}
}