當柳上原的風吹向天際的時候...

          真正的快樂來源于創(chuàng)造

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks

          #

          MD5是消息摘要算法的一種,它和SHA,HMAC是消息摘要算法的主要代表,其前身有MD2,MD3,MD4算法。
          消息摘要算法又稱為散列算法,其不可破解的核心在于散列函數(shù)的單向性,即可以通過散列函數(shù)得到結果,卻不可能通過結果反推出其原始信息。這是消息摘要算法的安全性根本所在。如果用戶輸入的密碼是123456789,則會得到25f9e794323b453885f5181f1b624d0這樣的結果;如果有人拿到25f9e794323b453885f5181f1b624d0這樣的結果,他是不可能反推出密碼123456789的。
          但是,總所周知的是,MD5已經(jīng)被我國山東大學王小云教授攻破了。他是怎么做到這不可能的事呢?當然不是反推,而是使用的碰撞算法,具體來說就是,拿到25f9e794323b453885f5181f1b624d0這樣的結果,用多種精心設計的字符串去試試,總有一個字符串經(jīng)MD5加密后能得到25f9e794323b453885f5181f1b624d0這樣的結果,這個字符串也許是真實密碼,也是是別的,但它加密后可以得到和123456789加密后一樣的效果。這就意味著,你給自己設定的密碼,別人通過其他密碼也可能通過驗證!
          其原因還是在于散列函數(shù),不同的輸入通過散列函數(shù)可能得到同一結果,雖然這個可能性較小。王教授成果的意義在于,以前號稱用全世界所有計算機算一百年不能做到的,用他的辦法用一臺普通微機在數(shù)個小時內(nèi)就能做到。這個很了不起,諸位如果有意可以去當他的研究生,這樣就知道是怎么做的了。
          那么,MD5還有存在的價值嗎。當然有,因為破解者要破解成功有三個必要條件,一,知道算法;二,知道密鑰;三,有大量數(shù)據(jù)供測試。如果把幾種其它算法和MD5混合,破解者就容易困惑,再加上時間限制,破解也不是件容易的事。最后,還有理論上不可能破解的量子密碼,如果它能實用化,則能達到真正意義上的不可破解。


          posted @ 2010-12-08 18:58 何楊 閱讀(413) | 評論 (2)編輯 收藏

          密碼學的加密算法可分為 單向加密算法,對稱加密算法和非對稱加密算法三類。
          • 單向加密算法是數(shù)據(jù)完整性驗證的常用算法,MD5SHA是單向加密算法的代表;
          • 對稱加密算法是數(shù)據(jù)存儲加密的常用算法,DESAES是對稱加密算法的代表;
          • 非對稱加密算法是數(shù)據(jù)傳輸加密的常用算法,RSA是非對稱加密算法的代表。對稱加密算法也可以用作數(shù)據(jù)傳輸加密,但非對稱加密算法在密鑰管理方面更有優(yōu)勢,在安全級別上更高,只是時間效率上不如對稱加密算法。

          JAVA API對密碼學的支持
          • MessageDigest類,可以構建MD5,SHA兩種加密算法;
          • Mac類可以構建HMAC加密算法;
          • Cipher類可以構建多種加密算法,如DES,AES,RSA,DSA,DH等;
          • Signature類可用于數(shù)字簽名和簽名驗證;
          • Certificate類可用于操作證書。

          posted @ 2010-12-05 14:24 何楊 閱讀(222) | 評論 (0)編輯 收藏

          本版新增功能:
          1.增加對DB2數(shù)據(jù)庫的支持。
          2.過濾器不區(qū)分大小寫。
          3.取消了歡迎窗口。

          下載地址:
          http://www.box.net/shared/0flunl0zul

          Softonic下載頁面:
          http://sqltoolbox.softonic.cn/

          概述

          SqlToolBox是一款純綠色的免費數(shù)據(jù)庫客戶端軟件,基于Java Swing編制而成,旨在于為開發(fā)人員,系統(tǒng)工程師和數(shù)據(jù)庫管理員提供一種通用方便和快捷的數(shù)據(jù)庫操作工具,使他們擺脫需要學習掌握使用多種數(shù)據(jù)庫客戶端 的苦惱,并減輕他們?nèi)粘2僮鲾?shù)據(jù)庫和編寫Sql語句的任務量,幫助他們把精力投入到解決更有意義的問題上去。

          SqlToolBox現(xiàn)有功能

          1. 能連接到MySql,Oracle,Ms Sql Server和DB2四種數(shù)據(jù)庫。
          2. 連接到數(shù)據(jù)庫后,會提供數(shù)據(jù)庫Schema和表的樹視圖以便用戶進行瀏覽和查找,另外還提供了一個過濾器幫助用戶縮小查找范圍。
          3. 用戶能自動快速獲取單表的創(chuàng)建,查詢,更新,刪除,建表語句,整表全部數(shù)據(jù)插入語句,單表對應Pojo類和單表的Hibernate映射文件等常用文字,且可借此構造更復雜的Sql語句。
          4. 能執(zhí)行Sql語句并顯示執(zhí)行結果,如果是查詢語句會以表格形式顯示結果,還提供CSV形式數(shù)據(jù)下載;如果是非查詢語句或是錯誤的查詢語句則會以文字形式告知用戶。
          5. 在用戶輸入Sql語句的過程中提供Sql語法高亮功能,以助于Sql語句的識別。
          6. 提供Sql格式化功能以助于Sql語句的識別和整理。
          7. 提供Redo/Undo,Shift整體退格進格,大小寫轉(zhuǎn)化,將Sql語句用StringBuilder包容以及將Sql語句中關鍵字大寫表示等常用文字編輯功能。這些都能幫助程序員在程序中書寫Sql語句。
          8. 能保存和記憶數(shù)據(jù)庫信息,以便下次打開。

          運行SqlToolBox有何前提條件?

          將SqlToolBox運行起來的唯一前提是安裝JDK6或以上版本。

          SqlToolBox需要安裝嗎?

          SqlToolBox是一款純綠色軟件,它對您的系統(tǒng)不做出任何更改,因此不需要安裝和卸載。

          SqlToolBox安全嗎?

          由于軟件使用Java編寫而成,它本身就具有較高的安全性。此外作者保證在SqlToolBox整個系列中都不會加入病毒,木馬,插件等壞東西。

          如何運行SqlToolBox?

          解開下載包,然后雙擊run.bat即可。

          在Unix/Linux下如何運行SqlToolBox?

          除了也需要安裝JDK外,您還需要參照run.bat寫一份腳本,然后執(zhí)行它。

          如何使用SqlToolBox打開一個數(shù)據(jù)庫?

          程序運行起來后,您將看到一個輸入數(shù)據(jù)庫信息的對話框,請依次填入數(shù)據(jù)庫所在機器的IP地址,數(shù)據(jù)庫的庫名稱,選擇數(shù)據(jù)庫的類型以及輸入登錄數(shù)據(jù)庫的用戶 名和密碼等必要信息。此后再點擊“連接數(shù)據(jù)庫”按鈕,程序?qū)⒋蜷_數(shù)據(jù)庫。如果您將以上信息填錯也不要緊,程序會提示哪里出現(xiàn)了問題。此外您可以在登錄前點 擊“測試連接”按鈕,程序也會告訴您是否能連接到指定的數(shù)據(jù)庫。

          打開數(shù)據(jù)庫后程序左邊部分如何使用?

          成功連接到數(shù)據(jù)庫以后,數(shù)據(jù)庫的Schema和table結構會在畫面的左邊以樹的形式展現(xiàn)出來,如果展現(xiàn)的內(nèi)容過多,您還可以在上方的“過濾器”輸入欄 中輸入關鍵字以縮小展現(xiàn)范圍。在這顆樹中,表格(table)是以小圓點的方式展現(xiàn)的,左鍵點擊這個圓點,程序?qū)⒃谟覀却蜷_一個Sql語句操作窗口,并執(zhí) 行“select * from table”語句,最后在下方以表格的形式展現(xiàn)給您;如果您用右鍵點擊這個圓點,程序?qū)棾鲆粋€右鍵菜單,選擇其中的項目您將可以在右邊的Sql語句操作 窗口中得到單表的字段信息,創(chuàng)建(insert),查詢(select),更新(update),刪除語句(delete)及建表語句(create table),單表對應Pojo文件,單表的Hibernate映射文件等文字。

          打開數(shù)據(jù)庫后程序右邊部分是如何使用的?

          用左右鍵點擊表格后,您將在右側看到一個“Sql語句操作窗口”,它分成三部分:工具欄菜單,輸入窗口和輸出窗口。輸入窗口是用以輸入,編輯和整理Sql 語句的;工具欄菜單中的一大排按鈕都是為編輯處理輸入窗口中的文字而準備的;輸出窗口則是展示Sql語句執(zhí)行后的結果的,如果是查詢語句,它會以表格的形 式告知您查詢的結果,如果是其它語句,它會以文字的形式告知。通常的操作手法是,先在輸入窗口中用鼠標選中您要操作的文本,再在工具欄菜單中點擊執(zhí)行特定 操作的按鈕,然后在下方的輸出窗口中就能看到具體的結果,當然如果僅是文本編輯操作的話輸出窗口是不會有反應的。

          如何執(zhí)行Sql語句?

          程序員和數(shù)據(jù)庫管理員總是習慣使用語句來操作數(shù)據(jù)庫,這也是本軟件的最重要功能之一。執(zhí)行Sql語句的過程具體來說是這樣做的,首先,在輸入窗口輸入您向 執(zhí)行的Sql語句,如“select * from table”之類,當然您更可以通過表格的右鍵菜單來獲得常用的sql語句(在輸入或是粘貼文本的過程中,Sql語句中的關鍵字會以藍色顯示,這是語法高 亮功能所致);其次,你需要選中你想執(zhí)行的文本,再點擊工具欄菜單中的向右三角形按鈕,這段文本將得到執(zhí)行,執(zhí)行結果將在下方的輸出窗口得到展示。如果您 執(zhí)行的是查詢語句,輸出窗口將以表格的形式列出查詢結果集的字段和內(nèi)容;如果您執(zhí)行的是刪除,更新,添加,修改表等語句或是執(zhí)行錯誤的Sql文本,輸出窗 口將以文本形式告知執(zhí)行結果。另外工具欄菜單中的雙向右三角形按鈕用于批量執(zhí)行Sql語句,它以分號“;”來作為每段Sql的分隔標志,然后分別執(zhí)行每 段。

          如何快速調(diào)整對執(zhí)行查詢語句后得到的表格列寬度?

          如果您想自動調(diào)整某列的寬度,可以雙擊這列的表頭,此后這列的寬度會根據(jù)這列的最長文字進行調(diào)整;您還可以在表格上點擊右鍵,選擇“調(diào)整列寬為最適合狀態(tài)”一項,那么所有的列寬都會進行調(diào)整。

          如何得到執(zhí)行查詢語句后得到的表格的內(nèi)容?

          您還可以在表格上點擊右鍵,選擇“下載表格為CSV文件”一項,此后查詢語句和得到的結果都會被放入一個CSV文件中。CSV是一中文本文件,但您可以用Excel打開它,也會得到xls文件一樣的效果。

          在新增或是刪除一張表后,在左邊的樹中為什么沒有相應的變化?

          新增或是刪除一張表后,您需要手動執(zhí)行一下左上方的更新按鈕(最上方的大圖標中第一個),此后程序會重新載入數(shù)據(jù)庫的Schema和table,這樣您剛才對表格進行增刪操作就能體現(xiàn)出來。

          如果我需要常打開數(shù)據(jù)庫進行操作或是需要常操作多個數(shù)據(jù)庫,程序能為我提供那些便利?

          本軟件有記憶功能,如果您正確連接到一個數(shù)據(jù)庫,那么相應的信息如IP地址,數(shù)據(jù)庫名,數(shù)據(jù)庫類型,連接數(shù)據(jù)庫的用戶名和密碼都會被記憶下來,這樣下次打 開時就不用重復輸入了。如果您需要常操作多個數(shù)據(jù)庫,您可以通過保存按鈕(最上方五個大圖標中的第二個)將數(shù)據(jù)庫信息保存成XML文件,這樣在登錄畫面中 就可以通過“打開文件按鈕”得到相應的數(shù)據(jù)庫信息。

          如果我有想法和建議,如何與作者聯(lián)系?

          首先,您可以點擊程序上方的信封按鈕,通過郵件heyang78@gmail.com和我聯(lián)系,我會樂于回復您的郵件并會認真考慮您提出的想法和建議;其次,您還可以通過QQ和我聯(lián)系,我的Q號是805985315;其三,我的MSN是junglesong_5@gmail.com,通過MSN也能找到我;最后,歡迎您登錄我的博客http://heyang.blogjava.net,如果SqlToolBox有所變化,我會在第一時間在博客上公告。

          感謝名單

          SqlToolBox的成長離不開以下人士的建議,激勵和幫助,在此謹向他們表示誠摯的謝意:
          • danielxu(關于jtds-1.2.2.jar的添加)
          • creasure(關于開源的建議)
          • Always BaNg.(關于語法高亮)
          • mircle(關于提升加載數(shù)據(jù)庫對象的性能)
          • willim2000(他也做了一個類型相同的軟件)
          • ytfulz(提供連接SqlServer的連接測試以,改變輸出表格形式,調(diào)整輸出表格列寬的建議)
          • 王宏亮(提供將程序和JRE整體打包的建議)
          • 朱儉(關于幫助窗口只打開一個的建議)
          • ☆振興中華☆(關于選擇數(shù)據(jù)表的建議)


          posted @ 2010-12-03 19:25 何楊 閱讀(1226) | 評論 (4)編輯 收藏

          安裝步驟:
          1.到http://sourceforge.jp/projects/amateras/releases/?package_id=4435 去下載 AmaterasUML_1.3.2.zip
          2.下載完畢后,解開壓縮包,將其中三個jar文件拷貝到你的Eclipse目錄的plugins目錄下。
          3.啟動或者重啟您的Eclipse。

          如何使用:
          1.點擊Eclipse的菜單"File"--"New"--"Others"。


          2.找到Amateras UML一項,選擇你要繪制的UML圖類型。


          3.選擇一個要存儲UML圖文件的文件夾。


          4.好了,可以開始畫了。



          我是在JavaEye看人介紹后裝的,用了感覺確實不錯,Visio可以見回收站去了。

          posted @ 2010-12-02 14:29 何楊 閱讀(1707) | 評論 (0)編輯 收藏

          按:以下文字涉及RSA對WebService傳遞的數(shù)據(jù)的加密解密,如果您已經(jīng)熟知RSA或是有其它更好的方法請不要往下看以免浪費時間.

          WebService采用的協(xié)議是SOAP,它基于HTTP,而HTTP是明文方式,也就是說,采用WebService傳遞的數(shù)據(jù)是明文的。如果是天氣預報這種公開的只讀信息的WebService無所謂,如果涉及寫入或是和私密數(shù)據(jù)相關,那么明文傳遞就有很大的潛在危險性,必須加以遏止。

          一般來說有兩種方法,一是采用https加密的方式,另一種是用非對稱加密算法對數(shù)據(jù)加密,下文提到的RSA就是第二種。

          使用RSA對WebService傳遞的信息加密解密的基本思想是:服務器端提供一個WebService方法byte[] getServerPublicKey(),客戶端可以以此得到服務器端的公鑰,然后使用服務器端的公鑰對要傳出去的數(shù)據(jù)進行RSA加密,并附帶以自己的公鑰;服務器端得到客戶端的請求后,先用自己的私鑰解密客戶端送來的數(shù)據(jù),得到處理結果后用客戶端提供的公鑰加密,然后傳回;客戶端得到服務器端的返回數(shù)據(jù)后,用自己的私鑰進行解密,最終得到了服務器端的真實數(shù)據(jù)。服務器端和客戶端各自保存自己的RSA私鑰用于解密,提供給對方RSA公鑰進行加密,這樣中間傳遞的信息就安全了。

          加密解密示意順序圖:


          下面是服務器端實現(xiàn)類的代碼:
          package com.heyang;


          public class ServiceImpl implements IService{
              @Override
              
          public byte[] getResonse(byte[] params, byte[] clientPublicKey) {
                  
          try {
                      
          // 使用自己的私鑰解密客戶端用服務器端公鑰加密的數(shù)據(jù)
                      String decryptString=SecurityUtil.getCoder().getDecryptString(params);
                      
                      
          // 要返回的結果
                      String response="你好!"+decryptString;
                      
                      
          // 使用客戶端提供的公鑰對返回的數(shù)據(jù)進行加密
                      byte[] retval=SecurityUtil.getCoder().getEncryptArray(response, clientPublicKey);
                      
                      
          return retval;
                  } 
          catch (Exception e) {
                      e.printStackTrace();
                      
                      
          return null;
                  }
              }

              @Override
              
          public byte[] getServerPublicKey() {
                  
          return SecurityUtil.getCoder().getPublicKey();
              }
          }


          客戶端調(diào)用服務器端的代碼:
          package com.heyang;

          import org.codehaus.xfire.XFireFactory;
          import org.codehaus.xfire.client.XFireProxyFactory;
          import org.codehaus.xfire.service.Service;
          import org.codehaus.xfire.service.binding.ObjectServiceFactory;

          public class Test {
              
          public static void main(String[] args) {
                  Service srvcModel 
          = new ObjectServiceFactory().create(IService.class);
                  XFireProxyFactory factory 
          = new XFireProxyFactory(XFireFactory
                          .newInstance().getXFire());

                  String helloWorldURL 
          = "http://localhost:8080/XfireSample/services/hello";
                  
          try {
                      IService srvc 
          = (IService) factory.create(srvcModel, helloWorldURL);

                      
          // 得到服務器端的公鑰
                      byte[] serverPublicKey=srvc.getServerPublicKey();
                      System.out.print(
          "從服務器端得到的公鑰為:");
                      
          for(byte b:serverPublicKey){
                          System.out.print(b);
                      }
                      System.out.println();
                      
                      
                      RSASecurityCoder coder
          =SecurityUtil.getCoder();
                      String requestString
          ="世界";
                      
                      
          // 使用服務器端的公鑰對要傳出去的數(shù)據(jù)進行加密
                      byte[] params=coder.getEncryptArray(requestString, serverPublicKey);
                      
                      
          // 得到服務器端的返回結果
                      byte[] responseArray=srvc.getResonse(params, coder.getPublicKey());
                      
                      
          // 使用自己的私鑰進行解密
                      String responseString=coder.getDecryptString(responseArray);
                      System.out.println(
          "從服務器端返回的字符串結果是:"+responseString);
                  } 
          catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }

          輸出的結果為:
          從服務器端得到的公鑰為:48-127-9748136942-12272-122-913111503-127-115048-127-1192-127-1270-575108-121578675121-687-32-1165359-2586-50-127114-24-6769-17-128115114982868-11550-121-111-69-494021-48-22-5844-37-8645-115-125-984651-344761-117-7875-34115-101-119164666123-4211-13-103-62-30-587926842-12338-32-91-24-75-1177128103-12-71108-121-122112-712-1089753-2691-7863-6385-41-10210782-8784120344-69-90474108-3661-47089-1261812510046-123-3910723101
          從服務器端返回的字符串結果是:你好!世界

          服務器端和客戶端使用的RSA加密解密類代碼:
          package com.heyang;

          import java.security.KeyFactory;
          import java.security.KeyPair;
          import java.security.KeyPairGenerator;
          import java.security.PrivateKey;
          import java.security.PublicKey;
          import java.security.interfaces.RSAPrivateKey;
          import java.security.interfaces.RSAPublicKey;
          import java.security.spec.PKCS8EncodedKeySpec;
          import java.security.spec.X509EncodedKeySpec;

          import javax.crypto.Cipher;

          /**
           * RSA加密解密類
           * 說明:
           * 作者:何楊(heyang78@gmail.com)
           * 創(chuàng)建時間:2010-12-1 下午06:14:38
           * 修改時間:2010-12-1 下午06:14:38
           
          */
          public class RSASecurityCoder{
              
          // 非對稱加密密鑰算法
              private static final String Algorithm="RSA";
              
              
          // 密鑰長度,用來初始化
              private static final int Key_Size=1024;
              
              
          // 公鑰
              private final byte[] publicKey;
              
              
          // 私鑰
              private final byte[] privateKey;
              
              
          /**
               * 構造函數(shù),在其中生成公鑰和私鑰
               * 
          @throws Exception
               
          */
              
          public RSASecurityCoder() throws Exception{
                  
          // 得到密鑰對生成器
                  KeyPairGenerator kpg=KeyPairGenerator.getInstance(Algorithm);
                  kpg.initialize(Key_Size);
                  
                  
          // 得到密鑰對
                  KeyPair kp=kpg.generateKeyPair();
                  
                  
          // 得到公鑰
                  RSAPublicKey keyPublic=(RSAPublicKey)kp.getPublic();
                  publicKey
          =keyPublic.getEncoded();
                  
                  
          // 得到私鑰
                  RSAPrivateKey keyPrivate=(RSAPrivateKey)kp.getPrivate();
                  privateKey
          =keyPrivate.getEncoded();
              }
              
              
          /**
               * 用公鑰對字符串進行加密
               * 
               * 說明:
               * 
          @param originalString
               * 
          @param publicKeyArray
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時間:2010-12-1 下午06:29:51
               
          */
              
          public byte[] getEncryptArray(String originalString,byte[] publicKeyArray) throws Exception{
                  
          // 得到公鑰
                  X509EncodedKeySpec keySpec=new X509EncodedKeySpec(publicKeyArray);
                  KeyFactory kf
          =KeyFactory.getInstance(Algorithm);
                  PublicKey keyPublic
          =kf.generatePublic(keySpec);
                  
                  
          // 加密數(shù)據(jù)
                  Cipher cp=Cipher.getInstance(Algorithm);
                  cp.init(Cipher.ENCRYPT_MODE, keyPublic);
                  
          return cp.doFinal(originalString.getBytes());
              }
              
              
              
          /**
               * 使用私鑰進行解密
               * 
               * 說明:
               * 
          @param encryptedDataArray
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時間:2010-12-1 下午06:35:28
               
          */
              
          public String getDecryptString(byte[] encryptedDataArray) throws Exception{
                  
          // 得到私鑰
                  PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(privateKey);
                  KeyFactory kf
          =KeyFactory.getInstance(Algorithm);
                  PrivateKey keyPrivate
          =kf.generatePrivate(keySpec);
                  
                  
          // 解密數(shù)據(jù)
                  Cipher cp=Cipher.getInstance(Algorithm);
                  cp.init(Cipher.DECRYPT_MODE, keyPrivate);
                  
          byte[] arr=cp.doFinal(encryptedDataArray);
                  
                  
          // 得到解密后的字符串
                  return new String(arr);
              }

              
          public byte[] getPublicKey() {
                  
          return publicKey;
              }
              
              
          public static void main(String[] arr) throws Exception{
                  String str
          ="你好,世界! Hello,world!";
                  System.out.println(
          "準備用公鑰加密的字符串為:"+str);
                  
                  
          // 用公鑰加密
                  RSASecurityCoder rsaCoder=new RSASecurityCoder();
                  
          byte[] publicKey=rsaCoder.getPublicKey();        
                  
          byte[] encryptArray=rsaCoder.getEncryptArray(str, publicKey);
                  
                  System.out.print(
          "用公鑰加密后的結果為:");
                  
          for(byte b:encryptArray){
                      System.out.print(b);
                  }
                  System.out.println();
                  
                  
          // 用私鑰解密
                  String str1=rsaCoder.getDecryptString(encryptArray);
                  System.out.println(
          "用私鑰解密后的字符串為:"+str1);
              }
          }

          用于初始化RSASecurityCoder實例的SecurityUtil類代碼:
          package com.heyang;

          /**
           * 信息安全實用類
           * 說明:
           * 作者:何楊(heyang78@gmail.com)
           * 創(chuàng)建時間:2010-12-2 上午10:57:49
           * 修改時間:2010-12-2 上午10:57:49
           
          */
          public class SecurityUtil{
              
          // 用于加密解密的RSA編碼類
              private static RSASecurityCoder coder;
              
              
          /**
               * 初始化coder的靜態(tài)構造子
               
          */
              
          static{
                  
          try {
                      coder
          =new RSASecurityCoder();
                  } 
          catch (Exception e) {
                      e.printStackTrace();
                  }
              }

              
          public static RSASecurityCoder getCoder() {
                  
          return coder;
              }
          }


          您可以從http://www.box.net/shared/cyg98xgz78 獲得上述代碼涉及到的兩個實例工程。

          好了,感謝您看到這里,希望此文字沒有耽誤您太多寶貴時間。
          posted @ 2010-12-02 11:44 何楊 閱讀(11044) | 評論 (16)編輯 收藏

          按:以下文字涉及RSA解密加密的基本操作,您如果已經(jīng)知曉就不用浪費時間了。

          在加密解密過程中,如果加密解密雙方都使用同一密鑰,那么泄密的可能性還是存在的,無論你把這個密鑰放在代碼,文件或是數(shù)據(jù)庫中。最好是密鑰分成兩部分,公鑰提供出去給應答者,讓它給返回的結果加密,請求者得到返回結果后,用自己的私鑰將其解密,公鑰和私鑰都由程序生成。這樣,客戶端和服務器端程序的所有者和編寫者都難以知道每個客戶端的私鑰是什么,從而難以破解數(shù)據(jù)。RSA就是實現(xiàn)這一想法的途徑之一。

          舉例來說,現(xiàn)在有一客戶端視圖和WebService服務器端通信,假如服務器端的響應函數(shù)是 String getResponse(String params,byte[] publicKeyArray);兩邊程序都有下面的RSASecurityCoder類,客戶端在發(fā)送請求前,可以得到此類的一個實例,并得到其公鑰,然后調(diào)用服務器端的getResponse函數(shù),公鑰就是這個函數(shù)的第二個參數(shù);服務器端得到請求后,處理得到結果,然后用第二個參數(shù)--客戶端送來的公鑰進行加密,然后送回結果;客戶端得到結果后用自己的私鑰進行解密就可以了。這樣,信息在傳輸過程的安全性就有了充分的保證了。

          下面請看代碼:
          package com.heyang.util;

          import java.security.KeyFactory;
          import java.security.KeyPair;
          import java.security.KeyPairGenerator;
          import java.security.PrivateKey;
          import java.security.PublicKey;
          import java.security.interfaces.RSAPrivateKey;
          import java.security.interfaces.RSAPublicKey;
          import java.security.spec.PKCS8EncodedKeySpec;
          import java.security.spec.X509EncodedKeySpec;

          import javax.crypto.Cipher;

          /**
           * RSA加密解密類
           * 說明:
           * 作者:何楊(heyang78@gmail.com)
           * 創(chuàng)建時間:2010-12-1 下午06:14:38
           * 修改時間:2010-12-1 下午06:14:38
           
          */
          public class RSASecurityCoder{
              
          // 非對稱加密密鑰算法
              private static final String Algorithm="RSA";
              
              
          // 密鑰長度,用來初始化
              private static final int Key_Size=1024;
              
              
          // 公鑰
              private final byte[] publicKey;
              
              
          // 私鑰
              private final byte[] privateKey;
              
              
          /**
               * 構造函數(shù),在其中生成公鑰和私鑰
               * 
          @throws Exception
               
          */
              
          public RSASecurityCoder() throws Exception{
                  
          // 得到密鑰對生成器
                  KeyPairGenerator kpg=KeyPairGenerator.getInstance(Algorithm);
                  kpg.initialize(Key_Size);
                  
                  
          // 得到密鑰對
                  KeyPair kp=kpg.generateKeyPair();
                  
                  
          // 得到公鑰
                  RSAPublicKey keyPublic=(RSAPublicKey)kp.getPublic();
                  publicKey
          =keyPublic.getEncoded();
                  
                  
          // 得到私鑰
                  RSAPrivateKey keyPrivate=(RSAPrivateKey)kp.getPrivate();
                  privateKey
          =keyPrivate.getEncoded();
              }
              
              
          /**
               * 用公鑰對字符串進行加密
               * 
               * 說明:
               * 
          @param originalString
               * 
          @param publicKeyArray
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時間:2010-12-1 下午06:29:51
               
          */
              
          public byte[] getEncryptArray(String originalString,byte[] publicKeyArray) throws Exception{
                  
          // 得到公鑰
                  X509EncodedKeySpec keySpec=new X509EncodedKeySpec(publicKeyArray);
                  KeyFactory kf
          =KeyFactory.getInstance(Algorithm);
                  PublicKey keyPublic
          =kf.generatePublic(keySpec);
                  
                  
          // 加密數(shù)據(jù)
                  Cipher cp=Cipher.getInstance(Algorithm);
                  cp.init(Cipher.ENCRYPT_MODE, keyPublic);
                  
          return cp.doFinal(originalString.getBytes());
              }
              
              
              
          /**
               * 使用私鑰進行解密
               * 
               * 說明:
               * 
          @param encryptedDataArray
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時間:2010-12-1 下午06:35:28
               
          */
              
          public String getDecryptString(byte[] encryptedDataArray) throws Exception{
                  
          // 得到私鑰
                  PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(privateKey);
                  KeyFactory kf
          =KeyFactory.getInstance(Algorithm);
                  PrivateKey keyPrivate
          =kf.generatePrivate(keySpec);
                  
                  
          // 解密數(shù)據(jù)
                  Cipher cp=Cipher.getInstance(Algorithm);
                  cp.init(Cipher.DECRYPT_MODE, keyPrivate);
                  
          byte[] arr=cp.doFinal(encryptedDataArray);
                  
                  
          // 得到解密后的字符串
                  return new String(arr);
              }

              
          public byte[] getPublicKey() {
                  
          return publicKey;
              }
              
              
          public static void main(String[] arr) throws Exception{
                  String str
          ="你好,世界! Hello,world!";
                  System.out.println(
          "準備用公鑰加密的字符串為:"+str);
                  
                  
          // 用公鑰加密
                  RSASecurityCoder rsaCoder=new RSASecurityCoder();
                  
          byte[] publicKey=rsaCoder.getPublicKey();        
                  
          byte[] encryptArray=rsaCoder.getEncryptArray(str, publicKey);
                  
                  System.out.print(
          "用公鑰加密后的結果為:");
                  
          for(byte b:encryptArray){
                      System.out.print(b);
                  }
                  System.out.println();
                  
                  
          // 用私鑰解密
                  String str1=rsaCoder.getDecryptString(encryptArray);
                  System.out.println(
          "用私鑰解密后的字符串為:"+str1);
              }
          }

          輸出:
          準備用公鑰加密的字符串為:你好,世界! Hello,world!
          用公鑰加密后的結果為:
          62-90-128-107-100-7070-11157-123-9160-6-116-68-1476-45-112-107-53-90107-84-670-9862-35-11116-83-10864312117-96-117-56995-2510321-89-89-828977-8810940100-91-76986562-222574-12815-120118-103-11-121-6030-6490-79-804911111-17-473984-7046-12294-8454-27108-26-11281-43833782-7926-612284-81781132357-3108-12673245-5111912-86-10041-799104-8146-5712374-55
          用私鑰解密后的字符串為:你好,世界! Hello,world
          !


          看到這里,如果有人說客戶端調(diào)用服務器端的getResponse函數(shù)時,第一個參數(shù)params不是還會暴露一部分信息嗎? 不要怕,我們可以讓服務器端再準備一個WebService函數(shù) byte[] getServerPublicKey();客戶端可以調(diào)用這個函數(shù)以得到服務器端的公鑰,然后把params用這個公鑰加密,然后再調(diào)用getResponse(String params,byte[] publicKeyArray)函數(shù),服務器端接到請求后,用自己的私鑰對第一個參數(shù)進行解密就可以了。這樣,所有信息都得到了保護。

          如果String的表現(xiàn)力不夠怎么辦,有了XML的幫助,這從來不是問題,您說呢?

          好了,感謝您看到這里,希望上面的文字能對您有所幫助;如果您要使用的話,上面的代碼需要改寫一下,相信您知道該怎么辦。

          posted @ 2010-12-01 19:19 何楊 閱讀(500) | 評論 (0)編輯 收藏

          按:以下內(nèi)容涉及傳統(tǒng)的AES加密解密方法,熟悉它的請不要浪費寶貴時間。

          如果用Base64進行加密解密是不安全的,因為這種方式的方法和密鑰(字符映射表)都是公開的,對此熟悉的人如果看到一串字符后面帶一些等號,很容易想到是Base64進行加密。因此,我們必須采取一些更安全的加密解密方式,AES就是其一。

          在使用AES進行加密解密之前,需要到Sun的官方網(wǎng)站上下載一個權限文件:jce_policy,目前它的下載網(wǎng)址是:http://www.oracle.com/technetwork/java/javase/downloads/index.html ,找到“Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6”后點擊按鈕下載,得到下載文件后解開,然后將其中的local_policy.jar和US_export_policy.jar拷貝到你的JAVA_HOME\jre\lib\security和JRE_HOME\lib\security兩個目錄下。如果沒有這一步驟,進行加密解密的時候會產(chǎn)生java.security.InvalidKeyException異常。

          接下來就是代碼了:
          package com.heyang.util;

          import java.security.Key;

          import javax.crypto.Cipher;
          import javax.crypto.KeyGenerator;
          import javax.crypto.SecretKey;
          import javax.crypto.spec.SecretKeySpec;

          import org.apache.commons.codec.binary.Hex;


          /**
           * AES算法加密解密實用工具類
           * 說明:
           * 作者:何楊(heyang78@gmail.com)
           * 創(chuàng)建時間:2010-11-29 上午11:19:11
           * 修改時間:2010-11-29 上午11:19:11
           
          */
          public class AESSecurityUtil{
              
          // 加密方法
              private static final String Algorithm="AES";
              
              
          // 進行加密解密的密鑰
              private static final String Key="03a53dfc257fe1b0996626a5e2e2210692936bd16cc60f37211cbeef9353e268";
              
              
          /**
               * 取得解密后的字符串
               * 
               * 說明:
               * 
          @param encryptArr
               * 
          @return
               * 創(chuàng)建時間:2010-12-1 下午03:33:31
               
          */
              
          public static String getDecryptString(byte[] encryptArr){
                  
          try{
                      Cipher cp
          =Cipher.getInstance(Algorithm);
                      cp.init(Cipher.DECRYPT_MODE, getKey());
                      
          byte[] arr=cp.doFinal(encryptArr);
                      
                      
          return new String(arr);
                  }
                  
          catch(Exception ex){
                      System.out.println(
          "無法進行解密,原因是"+ex.getMessage());
                      
          return null;
                  }
              }
              
              
          /**
               * 取得加密后的字節(jié)數(shù)組
               * 
               * 說明:
               * 
          @param originalString
               * 
          @return
               * 創(chuàng)建時間:2010-12-1 下午03:33:49
               
          */
              
          public static byte[] getEncryptByteArray(String originalString){
                  
          try{
                      Cipher cp
          =Cipher.getInstance(Algorithm);
                      cp.init(Cipher.ENCRYPT_MODE, getKey());
                      
          return cp.doFinal(originalString.getBytes());
                  }
                  
          catch(Exception ex){
                      System.out.println(
          "無法進行加密,原因是"+ex.getMessage());
                      
          return null;
                  }
              }
              
              
          /**
               * 取得密鑰數(shù)組
               * 
               * 說明:
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時間:2010-12-1 下午03:31:08
               
          */
              
          private static byte[] initKey() throws Exception{
                  KeyGenerator kg
          =KeyGenerator.getInstance(Algorithm);
                  kg.init(
          256);
                  
                  SecretKey sk
          =kg.generateKey();
                  
                  
          return sk.getEncoded();
              }
              
              
          /**
               * 取得字符串形式的密鑰
               * 
               * 說明:
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時間:2010-12-1 下午03:31:36
               
          */
              
          public static String initKeyHex() throws Exception{
                  
          return new String(Hex.encodeHex(initKey()));
              }
              
              
          /**
               * 取得密鑰
               * 
               * 說明:
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時間:2010-12-1 下午03:33:17
               
          */
              
          private static Key getKey() throws Exception{
                  
          byte[] arr=Hex.decodeHex(Key.toCharArray());
                  
                  
          return new SecretKeySpec(arr,Algorithm);
              }
              
              
          public static void main(String[] args)  throws Exception{
                  
          //System.out.println(initKeyHex());
                  
                  String str
          ="Hello!World 你好!世界。";
                  
                  
          byte[] arr=AESSecurityUtil.getEncryptByteArray(str);
                  System.out.print(
          "AES加密后的結果為:");
                  
          for(byte b:arr){
                      System.out.print(b);
                  }
                  System.out.println();
                  
                  String str1
          =AESSecurityUtil.getDecryptString(arr);
                  System.out.println(
          "AES解密后的字符串為:"+str1);
              }
          }
          測試輸出如下:
          AES加密后的結果為:833522115-115-6373-10-940-110-93-87736-561-1083427-99-6-6218-4104108-1031216395-92
          AES解密后的字符串為:Hello
          !World 你好!世界。

          上面代碼中值得注意的是,加密后的結果不能直接變成String形式,因為這會導致解密的不可行(解密拋出javax.crypto.IllegalBlockSizeException異常)。如果要使用其他的Key,可以單獨執(zhí)行一下initKeyHex()函數(shù),將輸出結果置換掉靜態(tài)變量Key的值即可。

          這樣,在AES的幫助下,我們實現(xiàn)了比較安全的加密,破解者知道方法AES,但不知道密鑰的話,解密會很困難。但是,話說回來,java程序被反編譯很容易,別有用心的人還是可以看到密鑰,但我們還是可以用公鑰加密私鑰解密的方式來對付,這個以后有空再說。

          好了,感謝您看到這里。
          posted @ 2010-12-01 16:10 何楊 閱讀(4060) | 評論 (1)編輯 收藏

          按:以下內(nèi)容很簡單,對Base64熟悉者無須往下看。

          Base64是一種基于64個字符的編碼算法,最早用于解決電子郵件傳輸?shù)膯栴},它的編碼和解碼操作可以充當加密和解密操作,其字符映射表就是其密鑰。但是,Base64算法及其密鑰都是公開的,因此不能被認為是安全的加密解密方法。

          下面是其示例代碼:
          package com.heyang.util;

          import org.apache.commons.codec.binary.Base64;


          /**
           * 常規(guī)Base64加密解密實用工具類
           * 說明:
           * 作者:何楊(heyang78@gmail.com)
           * 創(chuàng)建時間:2010-11-29 上午07:52:01
           * 修改時間:2010-11-29 上午07:52:01
           
          */
          public class Base64SecurityUtil{
              
          /**
               * 得到Base64加密后的字符串
               * 
               * 說明:
               * 
          @param originalString
               * 
          @return
               * 創(chuàng)建時間:2010-11-29 上午07:53:30
               
          */
              
          public static String getEncryptString(String originalString){
                  
          byte[] arr = Base64.encodeBase64(originalString.getBytes(), true);
                  
          return new String(arr);
              }
              
              
          /**
               * 得到Base64解密后的字符串
               * 
               * 說明:
               * 
          @param encryptString
               * 
          @return
               * 創(chuàng)建時間:2010-11-29 上午07:56:02
               
          */
              
          public static String getDecryptString(String encryptString){
                  
          byte[] arr = Base64.decodeBase64(encryptString.getBytes());
                  
          return new String(arr);
              }
              
              
          /**
               * 測試
               * 
               * 說明:
               * 
          @param args
               * 創(chuàng)建時間:2010-11-29 上午07:56:39
               
          */
              
          public static void main(String[] args){
                  String str
          ="Hello world!你好,世界。";
                  
                  String str1
          =Base64SecurityUtil.getEncryptString(str);
                  System.out.println(
          "經(jīng)Base64加密后的密文為"+str1);
                  
                  String str2
          =Base64SecurityUtil.getDecryptString(str1);
                  System.out.println(
          "經(jīng)Base64解密后的原文為"+str2);
              }
          }
          輸出:
          經(jīng)Base64加密后的密文為SGVsbG8gd29ybGQhxOO6w6OsysC956Gj

          經(jīng)Base64解密后的原文為Hello world
          !你好,世界。


          posted @ 2010-11-29 08:10 何楊 閱讀(1246) | 評論 (0)編輯 收藏

          按:以下還是炒冷飯,如果您對加鹽了解就不用往下看了,以免浪費寶貴時間。
          如果不了解下文部分細節(jié)的話,您可以參考這篇文章:使用MD5對存放在數(shù)據(jù)庫中用戶密碼進行保護


          直接對重要數(shù)據(jù)進行MD5處理后,反向解密確實難度很大,但還是可以找出破綻的,請看下圖:


          如果名為李自成的用戶可以查看數(shù)據(jù)庫,那么他可以觀察到自己的密碼和別人的密碼加密后的結果都是一樣,那么,別人用的和自己就是同一個密碼,這樣,就可以利用別人的身份登錄了。

          那么我們以前的加密方法是否對這種行為失效了呢?其實只要稍微混淆一下就能防范住了,這在加密術語中稱為“加鹽”。具體來說就是在原有材料(用戶自定義密碼)中加入其它成分(一般是用戶自有且不變的因素),以此來增加系統(tǒng)復雜度。當這種鹽和用戶密碼相結合后,再通過摘要處理,就能得到隱蔽性更強的摘要值。下面請見代碼:
          // 對密碼進行加鹽后加密,加密后再通過Hibernate往數(shù)據(jù)庫里存
                  String changedPswd=DigestUtils.md5Hex(name+pswd);

          就是這樣簡單,上面代碼中鹽就是用戶名,可以的話還可以用用戶注冊時的郵件,注冊時間等非空信息(如果是空信息這個加鹽處理會失效)。

          下面是數(shù)據(jù)庫中兩個用戶的記錄,他們的實際登錄密碼都是123456,但光看用戶記錄是完全看不出來的。這下別有用心的人打開數(shù)據(jù)庫看到的密碼都完全不一樣,他以前的手段就失效了。


          加鹽就是這樣簡單,感謝您看到這里。




          posted @ 2010-11-28 09:53 何楊 閱讀(11815) | 評論 (6)編輯 收藏

          以下文章屬于老調(diào)重彈,您如果對MD5的使用已經(jīng)熟悉請不要往下看以免浪費寶貴時間。

          登錄Web系統(tǒng)時通常都采用用戶名和密碼的形式,如果這樣的數(shù)據(jù)以明碼的方式放在數(shù)據(jù)庫中的話無疑會給別有用心的人以可趁之機,所以采取一定的防范措施是必要的。

          現(xiàn)在比較安全的方式是用MD5進行加密,利用Apache commons的DigestUtils工具類我們可以迅速做到這一點。
          要得到Apache commons的DigestUtils工具類,你必須加載commons-codec-1.x.jar包,我使用的是commons-codec-1.3.jar。使用的具體類是:org.apache.commons.codec.digest.DigestUtils.

          下面,我們的任務是,當用戶注冊時,將他注冊的密碼加密后存入數(shù)據(jù)庫,下面請見具體代碼:
           1 // 對密碼進行加密,加密后再通過Hibernate往數(shù)據(jù)庫里存
           2         String changedPswd=DigestUtils.md5Hex(pswd);
           3         
           4         User user=new User(name,changedPswd,email,brief);
           5         
           6         if(service.hasSameName(name)){
           7             // 同名檢測
           8             request.setAttribute("msg""已經(jīng)有和'"+name+"'同名的用戶存在了,請換個名稱注冊.");
           9             return new ActionForward("/web/page/register.jsp");
          10         }
          11         
          12         if(service.hasSameEmail(email)){
          13             // 同Emial檢測
          14             request.setAttribute("msg""已經(jīng)有和'"+email+"'相同的用戶存在了,請換個Email注冊.");
          15             return new ActionForward("/web/page/register.jsp");
          16         }
          17         
          18         try{
          19             service.create(user);
          20             saveUserRegisterInforToLog(user,request);
          21             request.setAttribute("msg"""+name+",歡迎您的加盟.???????¼???");
          22             return new ActionForward("/web/page/login.jsp");
          23         }
          24         catch(Exception ex){
          25             String str="創(chuàng)建用戶時遇到未預計的異常,具體的異常信息為'"+ex.getMessage()+"',請與系統(tǒng)維護人員聯(lián)系.";
          26             request.setAttribute("msg",str );
          27             logger.fatal(str);
          28             return new ActionForward("/web/page/register.jsp");
          29         }

          以上第二行代碼是進行MD5加密的處理,如果用戶輸入的密碼是123456789,則會得到25f9e794323b453885f5181f1b624d0b這樣的字符串。

          注冊用戶后,數(shù)據(jù)庫中您將看到如下的對應記錄,看到這樣的文字,要去反猜原始密碼是非常困難的,當然您有山東大學王小云教授的本事則不費吹灰之力。


          下面,我們還要對登錄時做一番處理,因為登錄時用的是原始密碼,我們應該對它進行加密后再和數(shù)據(jù)庫中的對應字段進行比對,代碼如下:
                      User user=objs.get(0);
                      
                      
          // 得到MD5加密后的密碼
                      String changedPswd=DigestUtils.md5Hex(password);
                          
                      
          // 再與數(shù)據(jù)庫中用戶密碼進行比對
                      if(user.getPassword().equals(changedPswd)==false){
                          
          throw new ErrorPswdException("密碼不匹配.");
                      }
          else{
                          
          return user;


                      }

          以上代碼中,password是用戶在頁面輸入的原始密碼,changedPswd是經(jīng)過MD5加密后的密碼,user是按名稱查詢出來的用戶,他的密碼部分就是已經(jīng)經(jīng)過MD5加密的,我們拿這兩個密碼進行比對即可。

          之所以沒有反向還原是因為MD5加密和Base64不一樣,前者是不可逆的,后者則可以還原。當然,Base64不是嚴格意義上的加密手段。

          最后的問題,如果數(shù)據(jù)庫中原有數(shù)據(jù)未經(jīng)加密怎么辦,好在MySql數(shù)據(jù)庫提供了md5函數(shù)幫我們做到這一點,使用update projectmanager_user set pswd=md5(pswd) 這樣的語句就可以將原來數(shù)據(jù)庫中的密碼部分用MD5加密了。

          下面的圖片演示了這一過程:

          原始數(shù)據(jù):


          使用update projectmanager_user set pswd=md5(pswd)加密后的數(shù)據(jù)庫記錄:


          到此啰嗦完了,感謝您看到這里。
          posted @ 2010-11-27 13:56 何楊 閱讀(7923) | 評論 (4)編輯 收藏

          僅列出標題
          共28頁: First 上一頁 14 15 16 17 18 19 20 21 22 下一頁 Last 
          主站蜘蛛池模板: 肇东市| 龙山县| 瑞安市| 成安县| 库尔勒市| 德化县| 白城市| 若羌县| 铜川市| 宁陕县| 托克逊县| 康平县| 新乡市| 昔阳县| 神池县| 乡宁县| 容城县| 会宁县| 沙雅县| 镇安县| 县级市| 蒙城县| 太仓市| 镇坪县| 屯昌县| 宜丰县| 永济市| 南雄市| 嘉兴市| 垫江县| 邯郸县| 湖州市| 九寨沟县| 安仁县| 灵武市| 和顺县| 吉林省| 葫芦岛市| 中山市| 万宁市| 湛江市|