qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          Java之Caesar與Vigenere實(shí)現(xiàn)

          1、背景介紹

            話說目前做所謂“企業(yè)”開發(fā)的語言基本就集中在運(yùn)用.Net和J2EE上了。又話說,在下很不幸又和Java“同流合污”了一把。現(xiàn)在回想起來,真是感慨萬千啊~遙想公瑾當(dāng)年,小喬初嫁了,雄姿英發(fā),羽扇綸巾,談笑間,強(qiáng)虜灰飛煙滅。~

            額,下面插播一下正題。其實(shí),目前國內(nèi)用Java做真正的“企業(yè)級(jí)”得其實(shí)并不是很多,絕大多數(shù)都是用個(gè)SSH1就覺得這就是Java之企業(yè)級(jí)開發(fā)了,之后就開始沾沾自喜了。這你說讓Servlet和EJB3情何以堪啊~所以說,目前國內(nèi)大多數(shù)Java的開發(fā)環(huán)境并不能說真正的武裝到牙齒。

            基于這樣的原因,有些時(shí)候,我們?cè)谧鲆恍?#8220;工程”的時(shí)候~,當(dāng)然對(duì)于多數(shù)情況就是IDE菜單選擇“新建工程”這么個(gè)選項(xiàng)出來的貨了,對(duì)于某些應(yīng)用,需要用到一些加密算法,雖說Java自身帶有專門的加密庫,但是那個(gè)用起來的確有些麻煩,而且加密算法還是動(dòng)態(tài)加載的,在本地測(cè)試的話問題還不是很大,痛苦的是萬一到服務(wù)器上一跑,這個(gè)加密算法加載失敗什么的,這可就大條了。如果說是一個(gè)什么認(rèn)證系統(tǒng)之類的,那也就罷了。但如果只是一些對(duì)密碼強(qiáng)要求很低,但不加密又不行的情況,那的確是挺麻煩的一件事情。

            那么,處于對(duì)易用性,易實(shí)現(xiàn)性的考慮,那些什么DES算法就暫時(shí)不考慮了。如果真有這個(gè)需求的話,相信找個(gè)健壯性很高的DES問題還不是很大的。而在那許多經(jīng)典的加密算法中,要數(shù)Caesar加密比較經(jīng)典了。所以,處于這樣的一個(gè)需求,就打算實(shí)現(xiàn)一個(gè)經(jīng)典加密算法。

            2、Caesar加密算法

            Caesar加密算法算是經(jīng)典加密算法中最簡單的了。對(duì)于標(biāo)準(zhǔn)的Caesar來說,就是把字母序列向后移動(dòng)一定的數(shù)量,替換后得到密文,而這個(gè)數(shù)量為固定值3。也就是說,在都是由英文字母組成的文本里,字母A將會(huì)被替換成D,B會(huì)被替換成E,以此類推。

            對(duì)于Caesar加密算法,存在幾點(diǎn)問題。首先是這個(gè)作為密鑰的值是個(gè)固定的3,而且字母表又是按順序排列的,所以只要對(duì)方知道你是用Caesar加密的,就很容易的脫密成原文,雖然有些麻煩,但是這就和用原文是差不多的,即使對(duì)加密要求很低也不能低成這樣不是?然后是這個(gè)替換表,因?yàn)槭腔谧帜副淼模詫?duì)于英文來說只能加密英文字母,這樣就不能被支持了。最后,因?yàn)樘鎿Q是固定的,所以,對(duì)于同一個(gè)字母,加密后的字母也是固定的。比如“AAA”這個(gè)文本加密后,就是“DDD”,看起來還不夠迷惑人。

            基于以上的原因,我這里實(shí)現(xiàn)的Caesar做了一些修改,但是總的思路還是Caesar。

          1. public class Caesar {  
          2.     private String table;  
          3.     private int seedA = 1103515245;  
          4.     private int seedB = 12345;  
          5.       
          6.     public Caesar(String table, int seed) {  
          7.         this.table = chaos(table, seed, table.length());  
          8.     }  
          9.     public Caesar(String table) {  
          10.         this(table, 11);  
          11.     }  
          12.     public Caesar() {  
          13.         this(11);  
          14.     }  
          15.     public Caesar(int seed) {  
          16.         this("ABCDEFGHIJKLMNOPQRSTUVWXYZ", seed);  
          17.     }  
          18.     public char dict(int i, boolean reverse) {  
          19.         int s = table.length(), index = reverse ? s - i : i;  
          20.         return table.charAt(index);  
          21.     }  
          22.     public int dict(char c,  boolean reverse) {  
          23.         int s = table.length(), index = table.indexOf(c);  
          24.         return reverse ? s - index : index;  
          25.     }  
          26.     public int seed(int seed) {  
          27.         long temp = seed;  
          28.         return (int)((temp * seedA + seedB) & 0x7fffffffL);  
          29.     }  
          30.   
          31.     public String chaos(String data, int seed, int cnt) {  
          32.         StringBuffer buf = new StringBuffer(data);  
          33.         char tmp; int a, b, r = data.length();  
          34.         for (int i = 0; i < cnt; i += 1) {  
          35.             seed = seed(seed); a = seed % r;  
          36.             seed = seed(seed); b = seed % r;  
          37.             tmp = buf.charAt(a);  
          38.             buf.setCharAt(a, buf.charAt(b));  
          39.             buf.setCharAt(b, tmp);  
          40.         }  
          41.         return buf.toString();  
          42.     }  
          43.   
          44.     public String crypto(boolean reverse,  
          45.                          int key, String text) {  
          46.         String ret = null;  
          47.         StringBuilder buf = new StringBuilder();  
          48.         int m, s = table.length(), e = text.length();  
          49.   
          50.         for(int i = 0; i < e; i += 1) {  
          51.             m = dict(text.charAt(i), reverse);  
          52.             if (m < 0break;  
          53.             m = m + key + i;  
          54.             buf.append(dict(m % s, reverse));  
          55.         }  
          56.         if (buf.length() == e)  
          57.             ret = buf.toString();  
          58.         return ret;  
          59.     }  
          60.     public String encode(int key, String text) {  
          61.         return crypto(false, key, text);  
          62.           
          63.     }  
          64.     public String decode(int key, String text) {  
          65.         return crypto(true , key, text);  
          66.     }  
          67.       
          68.     public static void main(String[] args) {  
          69.         Caesar caesar = new Caesar();  
          70.         String data = caesar.encode(32"APPLE");  
          71.         caesar.decode(32, data);  
          72.     }  
          73. }

          在上面的Caesar實(shí)現(xiàn)中,我用一個(gè)整數(shù)替代了原來作為密鑰的固定值3。其次,可以通過傳入不同的字符集讓這個(gè)加密算法的適用性更廣泛。最后,算法類在初始化的時(shí)候,會(huì)對(duì)替換表做一次擾亂操作,這樣的話,即使是相同的替換表,因?yàn)槌跏蓟瘋魅氲膕eed不同,加密出來的內(nèi)容也會(huì)不同。至于程序的細(xì)節(jié),我想源碼會(huì)更直觀的告訴你的。

            3、Vigenere加密算法

            其實(shí),Vigenere加密算法從歷史考證來看好像并不是一個(gè)叫Vigenere的人發(fā)明的。大概只是因?yàn)槟承C(jī)緣巧合,被一個(gè)叫Vigenere的人用了,并且流傳開了,然后就被叫做Vigenere加密算法了。后來發(fā)現(xiàn)這原來是一個(gè)美麗的誤解,但是既然都已經(jīng)被叫習(xí)慣了,改口自然是很難了,因此就那么流傳下來了。說道這里,Bellaso先生又一次的淚目了。

            為什么我這里要把Vigenere密碼和Caesar放在一起呢?因?yàn)閂igenere算是一個(gè)升級(jí)版的Caesar算法。所以,當(dāng)時(shí)實(shí)現(xiàn)了那個(gè)Caesar后,就順帶連 Bellaso 和 Vigenere 先生,也一起緬懷一下了。和Caesar相比Vigenere是一個(gè)多表替代,就是說針對(duì)明文中不同位置的字母,會(huì)選用不同的替換表來加密。如果用上面的例子來說,對(duì)于不同位置的字母,會(huì)選擇不同的key去加密。說白了,就是多個(gè)Caesar疊加起來就是Vigenere。

            雖然說Vigenere在加密的效果上比Caesar有很多提升了,也彌補(bǔ)了Caesar上存在的一些問題。但是,我的實(shí)現(xiàn)還是做了一些小小的調(diào)整。

          1. public class Vigenere {  
          2.     private String table;  
          3.     private int seedA = 1103515245;  
          4.     private int seedB = 12345;  
          5.       
          6.     public Vigenere(String table, int seed) {  
          7.         this.table = chaos(table, seed, table.length());  
          8.     }  
          9.     public Vigenere(String table) {  
          10.         this(table, 11);  
          11.     }  
          12.     public Vigenere() {  
          13.         this(11);  
          14.     }  
          15.     public Vigenere(int seed) {  
          16.         this("ABCDEFGHIJKLMNOPQRSTUVWXYZ", seed);  
          17.     }  
          18.       
          19.     private char dict(int i, boolean reverse) {  
          20.         int s = table.length(), index = reverse ? s - i : i;  
          21.         return table.charAt(index);  
          22.     }  
          23.     private int dict(char c,  boolean reverse) {  
          24.         int s = table.length(), index = table.indexOf(c);  
          25.         return reverse ? s - index : index;  
          26.     }  
          27.     private int seed(int seed) {  
          28.         long temp = seed;  
          29.         return (int)((temp * seedA + seedB) & 0x7fffffffL);  
          30.     }  
          31.   
          32.     public String chaos(String data, int seed, int cnt) {  
          33.         StringBuffer buf = new StringBuffer(data);  
          34.         char tmp; int a, b, r = data.length();  
          35.         for (int i = 0; i < cnt; i += 1) {  
          36.             seed = seed(seed); a = seed % r;  
          37.             seed = seed(seed); b = seed % r;  
          38.             tmp = buf.charAt(a);  
          39.             buf.setCharAt(a, buf.charAt(b));  
          40.             buf.setCharAt(b, tmp);  
          41.         }  
          42.         return buf.toString();  
          43.     }  
          44.     public String crypto(boolean reverse,  
          45.                          String key, String text) {  
          46.         String ret = null;  
          47.         StringBuilder buf = new StringBuilder();  
          48.         int m, k, s = table.length(),   
          49.                   e = text.length(),   
          50.                   ke = key.length();  
          51.   
          52.         for(int i = 0; i < e; i += 1) {  
          53.             m = dict(text.charAt(i), reverse);  
          54.             k = dict(key.charAt(i % ke), false);  
          55.             if (m < 0 || k < 0break;  
          56.             m = m + k + i;  
          57.             buf.append(dict(m % s, reverse));  
          58.         }  
          59.         if (buf.length() == e)  
          60.             ret = buf.toString();  
          61.         return ret;  
          62.     }  
          63.     public String encode(String key, String text) {  
          64.         return crypto(false, key, text);  
          65.           
          66.     }  
          67.     public String decode(String key, String text) {  
          68.         return crypto(true , key, text);  
          69.     }  
          70.     public static void main(String[] args) {  
          71.         Vigenere vigenere = new Vigenere();  
          72.         String data = vigenere.encode("BELLASO""APPLE");  
          73.         vigenere.decode("BELLASO", data);  
          74.     }  
          75. }

          話說,Vigenere加密算法傳入的密鑰到不是一個(gè)數(shù)字,是一個(gè)字符串。這個(gè)字符串中所用的字符,必須在替換表中出現(xiàn)過的。總的來說,Vigenere的強(qiáng)度要比Caesar強(qiáng)一些。但是終究還是會(huì)被破解的。不過,Vigenere有機(jī)會(huì)成為強(qiáng)度相當(dāng)高的一種加密手段,前提是~前提是你的密鑰長度大于或等于明文長度。然而,在實(shí)際應(yīng)用中,這個(gè)密鑰總是小于明文長度的。

            4、總結(jié)

            總的來說,理解這兩個(gè)加密算法都不算太難。對(duì)于密碼學(xué)大牛來說,這簡直是小兒科了。兩個(gè)算法有許多地方都是公用的,只是在一些地方有少許不同。在開發(fā)中,可以根據(jù)自己的喜好選擇一下。不要期待這兩個(gè)加密算法能有多大的抗破解強(qiáng)度,但是,作為一個(gè)煙霧彈掩蓋一下明文還是可以的。不過,如果你要將這個(gè)加密算法反復(fù)對(duì)一組明文加密的話,你最好自己再測(cè)試一下。因?yàn)椋用艽螖?shù)多了,出來的不一定是一個(gè)強(qiáng)度高的密文,也可能會(huì)是明文本身,切記切記。

            另外,有些人可能會(huì)想,那如果我要加密的是中文或者二進(jìn)制數(shù)據(jù),是不是要建立一個(gè)超大的密碼表,比如把中文字符集放進(jìn)去?我想說的是,這個(gè)加密算法強(qiáng)度不是很高的,如果你非有這個(gè)需求,要上身穿著阿瑪尼,腳上穿著丁子拖加褲衩,那也是可以的,方法就是用Base64把你的數(shù)據(jù)轉(zhuǎn)一下碼。剩下的就是傳一個(gè)包含那64個(gè)字符的轉(zhuǎn)換表。建議“=”符號(hào)不要加密。

            就像我題目所說的,聊勝于無。有時(shí)候,有條褲衩穿著出門,總比一絲不掛的出門要好。前者,你最多是被人說不太文明。而后者,你卻鐵定要被請(qǐng)去喝茶的。我實(shí)現(xiàn)這兩個(gè)密碼最主要的現(xiàn)實(shí)意義也在于此,最后,感謝你能堅(jiān)持看到文章的末尾,如果你有什么疑問或者想法,希望你能告訴我,我也很樂意與你交流。

          posted on 2011-11-07 10:32 順其自然EVO 閱讀(342) 評(píng)論(0)  編輯  收藏 所屬分類: 新聞

          <2011年11月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 南京市| 广灵县| 永年县| 黄浦区| 九寨沟县| 慈利县| 托里县| 延吉市| 加查县| 陈巴尔虎旗| 北川| 香格里拉县| 红桥区| 容城县| 阿克陶县| 宝应县| 西丰县| 扬州市| 平湖市| 开鲁县| 麟游县| 南宁市| 浦城县| 曲阳县| 平果县| 龙口市| 乌苏市| 罗田县| 溧水县| 巫山县| 普陀区| 衡山县| 安西县| 泗洪县| 会同县| 简阳市| 大埔区| 花莲市| 棋牌| 临海市| 呼玛县|