佇列應用之凱撒加密
阿新 • • 發佈:2019-01-04
1.凱撒加密(Caesar cipher)簡介
凱撒加密(Caesar cipher)是一種簡單的訊息編碼方式:它根據字母表將訊息中的每個字母移動常量位k。舉個例子
如果k等於3,則在編碼後的訊息中,每個字母都會向前移動3位:a會被替換為d;b會被替換成f;依此類推。字母表末尾將回捲到字母表開頭。於是,w會被替換為z,
x會被替換為a。
在解碼訊息的時候,每個字母會反方向移動同樣的位數。因此,如果k等於3,下面這條編碼後的訊息:
vlpsolflwb iroorzv frpsohalwb
會被解碼成:
simplicity follows complexity
朱麗葉斯.凱撒在他的一些機密政府通訊中真正用到了這種加密。遺憾的是,凱撒加密相當容易被破解。字母的移動只有26種可能;要破解密碼,只需嘗試各種金鑰值,
直到有一種可行即可。
使用重複金鑰(repeating key)可以對這種編碼技術做出改進,這時不再將每個字母移動常位數,而是利用一列金鑰值將各個字母移動不同的位數。如果訊息長於這列金鑰
值,可以從頭再次使用這列金鑰。例如,假設金鑰值為:
3 1 7 4 2 5
則第1個字母會移動3位,第2個字母會移動1位,依此類推,將第6個字母移動5位之後,我們會從頭再次使用這列金鑰。於是第7個字母會移動3位,第8個字母會移動
1位。反之解碼的過程類似。
2.程式碼實現
我們都知道佇列的特點是FIFO(先進先出),將金鑰儲存在佇列 中,使用了一個金鑰後,將這個金鑰新增到隊尾,這樣較長的資訊可以重複使用該金鑰。
佇列的JAVA程式碼實現如下:
/**
* 連結串列佇列的實現
*/
public class LinkedQueue {
private LinearNode front;
private LinearNode rear;
private int size;
/**
* 入隊操作
* @param node
*/
public void enqueue(LinearNode node) {
if(0 == size) {
front = rear = node;
} else {
rear.setNext(node);
rear = node;
}
size++;
}
/**
* 出隊操作
* @return
*/
public LinearNode dequeue() {
if(!isEmpty()) {
LinearNode l = front;
//when the size is 1
if(front == rear)
front = rear = null;
else
front = l.getNext();
size--;
return l;
} else {
front = rear = null;
return null;
}
}
/**
* 獲得佇列大小
* @return
*/
public int size() {
return size;
}
/**
* 判斷佇列是否為空
* @return
*/
public boolean isEmpty() {
if(0 < size)
return false;
else
return true;
}
/**
* 顯示佇列資料
*
*/
public void listNodes() {
while(!isEmpty()) {
System.out.println(dequeue().getElement());
}
}
public LinearNode getFront() {
return front;
}
public void setFront(LinearNode front) {
this.front = front;
}
public LinearNode getRear() {
return rear;
}
public void setRear(LinearNode rear) {
this.rear = rear;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
front指標指向佇列的第一個元素,也就是即將出隊的元素;rear指標指向隊尾元素,也就是剛入隊的元素。如果佇列為空則入隊時front和rear都指向剛入隊的
元素;如果最後一個元素出隊,佇列為空,front和rear都為null。
凱撒加密程式碼如下:
/**
* 凱撒加密
*/
public class KasarEncryption {
private LinkedQueue encKeyQueue = new LinkedQueue();
private LinkedQueue decKeyQueue = new LinkedQueue();
public KasarEncryption(int key[]) {
genKey(key);
}
/**
* 處理金鑰
* @param key
*/
private void genKey(int[] key) {
for(int i = 0 ; i < key.length ; i++) {
encKeyQueue.enqueue(new LinearNode<Integer>(new Integer(key[i])));
decKeyQueue.enqueue(new LinearNode<Integer>(new Integer(key[i])));
}
}
/**
* 加密
* @param plainText
* @return
*/
public String encrypt(String plainText) {
char chars[] = plainText.toCharArray();
for(int i = 0 ; i < chars.length ; i++) {
LinearNode<Integer> l = encKeyQueue.dequeue();
int movement = l.getElement().intValue();
chars[i] += movement;
encKeyQueue.enqueue(l);
}
return new String(chars);
}
/**
* 解密
* @param encryptedText
* @return
*/
public String decrypt(String encryptedText) {
char chars[] = encryptedText.toCharArray();
for(int i = 0 ; i < chars.length ; i++) {
LinearNode<Integer> l = decKeyQueue.dequeue();
int movement = l.getElement().intValue();
chars[i] -= movement;
decKeyQueue.enqueue(l);
}
return new String(chars);
}
public static void main(String args[]) throws InterruptedException {
String plainText = "my name is bilei";
int key[] = {3,5,4,1};
KasarEncryption ke = new KasarEncryption(key);
if(args.length > 0) {
plainText = "";
for(int i = 0 ; i < args.length ; i++) {
if(i == args.length-1)
plainText += args[i];
else
plainText += args[i]+" ";
}
}
System.out.println("明文 "+plainText);
System.out.println("加密........");
String encryptedText = ke.encrypt(plainText);
System.out.println("密文 "+encryptedText);
Thread.sleep(3000);
System.out.println("解密........");
System.out.println("明文 "+ke.decrypt(encryptedText));
}
}
我們要用到兩個佇列,一個為加密佇列,另一個為解密佇列,這兩個佇列存放相同的金鑰,訊息格式儲存為String型別,在加密解密操作時,將其轉換為char陣列
分別對陣列中每一元素進行加密。
程式碼測試:
明文 darkdiable is jason;jason is darkdiable
加密........
密文 gfvlgnecoj$jv%nbvtr<mfwpq%mt#iesnimbeqi
解密........
明文 darkdiable is jason;jason is darkdiable
因為JAVA虛擬機器中的編碼方式採用unicode,char型別為2位元組,所以對於中文編碼也能很好支援,測試如下:
明文 凱撒加密測試
加密........
密文 凲撗劤寇濟誠
解密........
明文 凱撒加密測試
凱撒加密(Caesar cipher)是一種簡單的訊息編碼方式:它根據字母表將訊息中的每個字母移動常量位k。舉個例子
如果k等於3,則在編碼後的訊息中,每個字母都會向前移動3位:a會被替換為d;b會被替換成f;依此類推。字母表末尾將回捲到字母表開頭。於是,w會被替換為z,
x會被替換為a。
在解碼訊息的時候,每個字母會反方向移動同樣的位數。因此,如果k等於3,下面這條編碼後的訊息:
vlpsolflwb iroorzv frpsohalwb
會被解碼成:
simplicity follows complexity
朱麗葉斯.凱撒在他的一些機密政府通訊中真正用到了這種加密。遺憾的是,凱撒加密相當容易被破解。字母的移動只有26種可能;要破解密碼,只需嘗試各種金鑰值,
直到有一種可行即可。
使用重複金鑰(repeating key)可以對這種編碼技術做出改進,這時不再將每個字母移動常位數,而是利用一列金鑰值將各個字母移動不同的位數。如果訊息長於這列金鑰
值,可以從頭再次使用這列金鑰。例如,假設金鑰值為:
3 1 7 4 2 5
則第1個字母會移動3位,第2個字母會移動1位,依此類推,將第6個字母移動5位之後,我們會從頭再次使用這列金鑰。於是第7個字母會移動3位,第8個字母會移動
1位。反之解碼的過程類似。
2.程式碼實現
我們都知道佇列的特點是FIFO(先進先出),將金鑰儲存在佇列 中,使用了一個金鑰後,將這個金鑰新增到隊尾,這樣較長的資訊可以重複使用該金鑰。
佇列的JAVA程式碼實現如下:
/**
* 連結串列佇列的實現
*/
public class LinkedQueue {
private LinearNode front;
private LinearNode rear;
private int size;
/**
* 入隊操作
* @param node
*/
public void enqueue(LinearNode node) {
if(0 == size) {
front = rear = node;
} else {
rear.setNext(node);
rear = node;
}
size++;
}
/**
* 出隊操作
* @return
*/
public LinearNode dequeue() {
if(!isEmpty()) {
LinearNode l = front;
//when the size is 1
if(front == rear)
front = rear = null;
else
front = l.getNext();
size--;
return l;
} else {
front = rear = null;
return null;
}
}
/**
* 獲得佇列大小
* @return
*/
public int size() {
return size;
}
/**
* 判斷佇列是否為空
* @return
*/
public boolean isEmpty() {
if(0 < size)
return false;
else
return true;
}
/**
* 顯示佇列資料
*
*/
public void listNodes() {
while(!isEmpty()) {
System.out.println(dequeue().getElement());
}
}
public LinearNode getFront() {
return front;
}
public void setFront(LinearNode front) {
this.front = front;
}
public LinearNode getRear() {
return rear;
}
public void setRear(LinearNode rear) {
this.rear = rear;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
front指標指向佇列的第一個元素,也就是即將出隊的元素;rear指標指向隊尾元素,也就是剛入隊的元素。如果佇列為空則入隊時front和rear都指向剛入隊的
元素;如果最後一個元素出隊,佇列為空,front和rear都為null。
凱撒加密程式碼如下:
/**
* 凱撒加密
*/
public class KasarEncryption {
private LinkedQueue encKeyQueue = new LinkedQueue();
private LinkedQueue decKeyQueue = new LinkedQueue();
public KasarEncryption(int key[]) {
genKey(key);
}
/**
* 處理金鑰
* @param key
*/
private void genKey(int[] key) {
for(int i = 0 ; i < key.length ; i++) {
encKeyQueue.enqueue(new LinearNode<Integer>(new Integer(key[i])));
decKeyQueue.enqueue(new LinearNode<Integer>(new Integer(key[i])));
}
}
/**
* 加密
* @param plainText
* @return
*/
public String encrypt(String plainText) {
char chars[] = plainText.toCharArray();
for(int i = 0 ; i < chars.length ; i++) {
LinearNode<Integer> l = encKeyQueue.dequeue();
int movement = l.getElement().intValue();
chars[i] += movement;
encKeyQueue.enqueue(l);
}
return new String(chars);
}
/**
* 解密
* @param encryptedText
* @return
*/
public String decrypt(String encryptedText) {
char chars[] = encryptedText.toCharArray();
for(int i = 0 ; i < chars.length ; i++) {
LinearNode<Integer> l = decKeyQueue.dequeue();
int movement = l.getElement().intValue();
chars[i] -= movement;
decKeyQueue.enqueue(l);
}
return new String(chars);
}
public static void main(String args[]) throws InterruptedException {
String plainText = "my name is bilei";
int key[] = {3,5,4,1};
KasarEncryption ke = new KasarEncryption(key);
if(args.length > 0) {
plainText = "";
for(int i = 0 ; i < args.length ; i++) {
if(i == args.length-1)
plainText += args[i];
else
plainText += args[i]+" ";
}
}
System.out.println("明文 "+plainText);
System.out.println("加密........");
String encryptedText = ke.encrypt(plainText);
System.out.println("密文 "+encryptedText);
Thread.sleep(3000);
System.out.println("解密........");
System.out.println("明文 "+ke.decrypt(encryptedText));
}
}
我們要用到兩個佇列,一個為加密佇列,另一個為解密佇列,這兩個佇列存放相同的金鑰,訊息格式儲存為String型別,在加密解密操作時,將其轉換為char陣列
分別對陣列中每一元素進行加密。
程式碼測試:
明文 darkdiable is jason;jason is darkdiable
加密........
密文 gfvlgnecoj$jv%nbvtr<mfwpq%mt#iesnimbeqi
解密........
明文 darkdiable is jason;jason is darkdiable
因為JAVA虛擬機器中的編碼方式採用unicode,char型別為2位元組,所以對於中文編碼也能很好支援,測試如下:
明文 凱撒加密測試
加密........
密文 凲撗劤寇濟誠
解密........
明文 凱撒加密測試