1. 程式人生 > >佇列應用之凱撒加密

佇列應用之凱撒加密

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位元組,所以對於中文編碼也能很好支援,測試如下:
明文 凱撒加密測試
加密........
密文 凲撗劤寇濟誠
解密........
明文 凱撒加密測試