nighty

          折騰的年華
          posts - 37, comments - 143, trackbacks - 0, articles - 0

          Java MD5加密生成摘要

          Posted on 2008-05-08 15:02 寒武紀 閱讀(6545) 評論(2)  編輯  收藏 所屬分類: 信息安全

              剛好最近項目中需要用到一點加密的東西,java安全類庫提供了一個java.security.MessageDigest類,此 MessageDigest 類為應用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的單向哈希函數,它接收任意大小的數據,并輸出固定長度的哈希值。有現成的當然是最好的,省事省力。
              MD5的非常有實際應用性。有網友給出這樣的描述,可以參照一下:http://blog.csdn.net/Daping_Zhang/archive/2005/05/28/382688.aspx
               該類的getInstance(String algorithm) 方法返回一個MessageDigest的實體,加密的一系統的digest()方法和update(byte input)方法。加密后返回一個byte[],16位,我們經常見到很多開源網站的下載地址會有一個[md5]的鏈接,打開其實就是一小段文本內容。例如:
              MD5 (commons-logging-1.1.1-bin.zip) = f88520ed791673aed6cc4591bc058b55
              這是Jakarta的logging組件下載時提供的MD5摘要信息,是對這個zip包進行全文加密生成的摘要,摘要碼就是后面的f88520ed791673aed6cc4591bc058b55,如果你下載以后,按照MD5的算法生成自己的摘要,如果這二個摘要一樣,就證明這個文件是沒有被人篡改過的。
              遇到的問題是Java的MessageDigest類執行后返回的byte[16]得轉換成十六進制的字符串,如果直接用new String(byte[]),得到的結果將是不正確的。算法有很多網友提供了,照搬了。比較有趣的是,commons-logging提供的那個MD5居然和我自己生成的不一樣(難道文件被修改過?),后來嘗試了其它地方提供的MD5碼,都沒有問題。
              有很多相關的現成代碼,搜集了一下整理如下(經過驗證):

          public class MD5Builder {

              
          static Logger logger = Logger.getLogger(MD5Builder.class);
               
          // 用來將字節轉換成 16 進制表示的字符
              static char hexDigits[] = '0''1''2''3''4''5''6''7''8',
                      
          '9''a''b''c''d''e''f' }

              
              
          /**
               * 對文件全文生成MD5摘要
               * 
          @param file   要加密的文件
               * 
          @return MD5摘要碼
               
          */

              
          public static String getMD5(File file) {
                  FileInputStream fis 
          = null;
                  
          try {
                      MessageDigest md 
          = MessageDigest.getInstance("MD5");

                      logger.info(
          "MD5摘要長度:" + md.getDigestLength());
                      fis 
          = new FileInputStream(file);
                      
          byte[] buffer = new byte[2048];
                      
          int length = -1;
                      logger.info(
          "開始生成摘要");
                      
          long s = System.currentTimeMillis();
                      
          while ((length = fis.read(buffer)) != -1{
                          md.update(buffer, 
          0, length);
                      }

                      logger.info(
          "摘要生成成功,總用時: "
                              
          + (System.currentTimeMillis() - s) + "ms");
                      
          byte[] b = md.digest();
                      
          return byteToHexString(b);
                      
          // 16位加密
                      
          // return buf.toString().substring(8, 24);
                  }
           catch (Exception ex) {
                      logger.error(ex);
                      ex.printStackTrace();
                      
          return null;
                  }
          finally {
                      
          try {
                          fis.close();
                      }
           catch (IOException ex) {
                          ex.printStackTrace();
                      }

                  }

              }


              
          /**
               * 對一段String生成MD5加密信息
               * 
          @param message 要加密的String
               * 
          @return 生成的MD5信息
               
          */

              
          public static String getMD5(String message){
                  
          try {
                      MessageDigest md 
          = MessageDigest.getInstance("MD5");
                      logger.info(
          "MD5摘要長度:" + md.getDigestLength());
                      
          byte[] b = md.digest(message.getBytes());
                      
          return byteToHexString(b);
                  }
           catch (NoSuchAlgorithmException e) {
                      logger.error(e);
                      e.printStackTrace();
                      
          return null;
                  }

              }

              
              
          /**
               * 把byte[]數組轉換成十六進制字符串表示形式
               * 
          @param tmp    要轉換的byte[]
               * 
          @return 十六進制字符串表示形式
               
          */

              
          private static String byteToHexString(byte[] tmp) {
                  String s;
                  
          // 用字節表示就是 16 個字節
                  char str[] = new char[16 * 2]; // 每個字節用 16 進制表示的話,使用兩個字符,
                  
          // 所以表示成 16 進制需要 32 個字符
                  int k = 0// 表示轉換結果中對應的字符位置
                  for (int i = 0; i < 16; i++// 從第一個字節開始,對 MD5 的每一個字節
                      
          // 轉換成 16 進制字符的轉換
                      byte byte0 = tmp[i]; // 取第 i 個字節
                      str[k++= hexDigits[byte0 >>> 4 & 0xf]; // 取字節中高 4 位的數字轉換, 
                      
          // >>> 為邏輯右移,將符號位一起右移
                      str[k++= hexDigits[byte0 & 0xf]; // 取字節中低 4 位的數字轉換
                  }

                  s 
          = new String(str); // 換后的結果轉換為字符串
                  return s;
              }

          }

            



          剛進場的時候戲就落幕

          Feedback

          # re: Java MD5加密生成摘要[未登錄]  回復  更多評論   

          2009-03-13 20:46 by aaa
          dddddddddddddd

          # re: Java MD5加密生成摘要  回復  更多評論   

          2009-03-20 15:33 by 書頁
          /** *//**
          * 對一段String生成MD5加密信息
          * @param message 要加密的String
          * @return 生成的MD5信息
          */
          public static String getMD5(String message){
          try {
          MessageDigest md = MessageDigest.getInstance("MD5");
          logger.info("MD5摘要長度:" + md.getDigestLength());
          byte[] b = md.digest(message.getBytes());
          return byteToHexString(b);
          } catch (NoSuchAlgorithmException e) {
          logger.error(e);
          e.printStackTrace();
          return null;
          }
          }



          byte[] b = md.digest(message.getBytes());
          應該修改成:
          byte[] b = md.digest(message.getBytes("GBK"));

          指定編碼,這樣這塊代碼在不同編碼的系統下出來的MD5就是一樣啦!

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 乌拉特中旗| 读书| 黔西县| 隆昌县| 辉县市| 定西市| 遂溪县| 东乡县| 安阳市| 中方县| 永吉县| 桓仁| 商城县| 威信县| 平舆县| 乐东| 永康市| 温宿县| 吴川市| 江城| 灌南县| 普兰县| 遵化市| 政和县| 海晏县| 铜山县| 上林县| 韩城市| 大宁县| 颍上县| 扶沟县| 瓮安县| 南郑县| 清水河县| 舒城县| 马边| 嵩明县| 瑞昌市| 库伦旗| 八宿县| 天长市|