JAVA MessageDigest(MD5加密等)


轉自http://blog.csdn.net/hudashi/article/details/8394158



一、概述
java.security.MessageDigest類用於爲應用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。簡單點說就是用於生成散列碼。信息摘要是安全的單向哈希函數,它接收任意大小的數據,輸出固定長度的哈希值。關於信息摘要和散列碼請參照《數字證書簡介》
MessageDigest 通過其getInstance系列靜態函數來進行實例化和初始化。MessageDigest 對象通過使用 update 方法處理數據。任何時候都可以調用 reset 方法重置摘要。一旦所有需要更新的數據都已經被更新了,應該調用 digest 方法之一完成哈希計算並返回結果。


對於給定數量的更新數據,digest 方法只能被調用一次。digest 方法被調用後,MessageDigest  對象被重新設置成其初始狀態。


MessageDigest 的實現可隨意選擇是否實現 Cloneable 接口。客戶端應用程可以通過嘗試複製和捕獲 CloneNotSupportedException 測試可複製性:


 MessageDigest md = MessageDigest.getInstance("SHA");


 try {


     md.update(toChapter1);


     MessageDigest tc1 = md.clone();


     byte[] toChapter1Digest = tc1.digest();


     md.update(toChapter2);


     ...etc.


 } catch (CloneNotSupportedException cnse) {


     throw new DigestException("couldn't make digest of partial content");


 }


注意1:即時給定MessageDigest的實現是不可複製的,則仍然能夠通過getInstance方法實例化幾個實例計算來同時進行摘要信息的計算。


注意2:由於歷史原因,此類是抽象的,是從 MessageDigestSpi 擴展的。應用程序開發人員只應該注意在此 MessageDigest 類中定義的方法;超類中的所有方法是供希望提供自己的信息摘要算法實現的加密服務提供者使用的。 


注意3:MessageDigest並不是單實例的。如下代碼所示:


         try


            {


                MessageDigest mdTemp1 = MessageDigest.getInstance("MD5");


                MessageDigest mdTemp2= MessageDigest.getInstance("MD5");


                MessageDigest mdTemp3= MessageDigest.getInstance("MD5");


                System.out.println("mdTemp1==mdTemp2?:"+(mdTemp1==mdTemp2));


                System.out.println("mdTemp2==mdTemp3?:"+(mdTemp2==mdTemp3));


            } catch (NoSuchAlgorithmException e)


            {


                // TODO Auto-generated catch block


                e.printStackTrace();


            }


運行結果


mdTemp1==mdTemp2?:false


mdTemp2==mdTemp3?:false


構造方法摘要
protected MessageDigest(String algorithm) 
          創建具有指定算法名稱的MessageDigest 實例對象。  
方法摘要
 Object clone() 
          如果實現是可複製的,則返回一個副本。
 byte[] digest() 
          通過執行諸如填充之類的最終操作完成哈希計算。
 byte[] digest(byte[] input) 
          使用指定的字節數組對摘要進行最後更新,然後完成摘要計算。
 int digest(byte[] buf, int offset, int len) 
          通過執行諸如填充之類的最終操作完成哈希計算。
 String getAlgorithm() 
          返回標識算法的獨立於實現細節的字符串。
 int getDigestLength() 
          返回以字節爲單位的摘要長度,如果提供程序不支持此操作並且實現是不可複製的,則返回 0。
static MessageDigest getInstance(String algorithm) 
          生成實現指定摘要算法的 MessageDigest 對象。
static MessageDigest getInstance(String algorithm, Provider provider) 
          生成實現指定提供程序提供的指定算法的 MessageDigest 對象,如果該算法可從指定的提供程序得到的話。
static MessageDigest getInstance(String algorithm, String provider) 
          生成實現指定提供程序提供的指定算法的 MessageDigest 對象,如果該算法可從指定的提供程序得到的話。
 Provider getProvider() 
          返回此信息摘要對象的提供程序。
static boolean isEqual(byte[] digesta, byte[] digestb) 
          比較兩個摘要的相等性。
 void reset() 
          重置摘要以供再次使用。
 String toString() 
          返回此信息摘要對象的字符串表示形式。
 void update(byte input) 
          使用指定的字節更新摘要。
 void update(byte[] input) 
          使用指定的字節數組更新摘要。
 void update(byte[] input, int offset, int len) 
          使用指定的字節數組,從指定的偏移量開始更新摘要。
 void update(ByteBuffer input) 
          使用指定的 ByteBuffer 更新摘要。
二、實際實踐
2.1、創建 MessageDigest 對象
計算信息摘(即散列碼)要做的第一步是創建 MessageDigest對象 實例。像所有的引擎類一樣,獲取某類報文摘要算法(即散列算法,比如MD5)的  MessageDigest 對象的途徑是調用 MessageDigest 類中的 getInstance 靜態 factory 方法:
    public static MessageDigest getInstance(String algorithm)


注意:算法名不區分大小寫。例如,以下所有調用都是相等的:
MessageDigest.getInstance("SHA");
MessageDigest.getInstance("sha");
MessageDigest.getInstance("sHa");
調用程序可選擇指定提供者名稱,以保證所要求的算法是由已命名提供者實現的:
public static MessageDigest getInstance(String algorithm, String provider);


調用 getInstance 將返回已初始化過的MessageDigest對象。因此,它不需要進一步的初始化。
2.2、向MessageDigest傳送要計算的數據
計算數據的摘要的第二步是向已初始化的MessageDigest對象提供傳送要計算的數據。這將通過一次或多次調用以下某個 update(更新)方法來完成:
public void update(byte input);
public void update(byte[] input);
public void update(byte[] input, int offset, int len);
2.3、計算摘要
通過調用 update 方法向MessageDigest對象提傳送要計算的數據後,你就可以調用以下某個 digest(摘要)方法來計算摘要(即生成散列碼):
public byte[] digest();
public byte[] digest(byte[] input);
public int digest(byte[] buf, int offset, int len);
前兩個方法返回計算出的摘要。後一個方法把計算出的摘要儲存在所提供的 buf 緩衝區中,起點是 offset。len 是 buf 中分配給該摘要的字節數。該方法返回實際存儲在 buf 中的字節數。
對第二個接受輸入字節數組變量的 digest 方法的調用等價於用指定的輸入調用:
    public void update(byte[] input)


,接着調用不帶參數的 digest 方法.
三、例子演示
3.1、★ 編程思路:
java.security包中的MessageDigest類提供了計算消息摘要(即生成散列碼)的方法,首先生成對象,執行其update( )方法可
以將原始數據傳遞給該對象,然後執行其digest( )方法即可得到消息摘要。具體步驟如下:
(1)生成MessageDigest對象
MessageDigest m=MessageDigest.getInstance("MD5");


MessageDigest類也是一個工廠類,其構造器是受保護的,不允許
直接使用new MessageDigist( )來創建對象,而必須通過其靜態方法getInstance( )生成MessageDigest對象。
其中傳入的參數指定計算消息摘要所使用的算法,常用的有"MD5","SHA"等。
(2)傳入需要計算的字符串
m.update(x.getBytes("UTF8" ));


分析:x爲需要計算的字符串,update傳入的參數是字節類型或字節類型數組,對於字符串,需要先使用getBytes( )方法生成字符串數組。
(3)計算消息摘要
byte s[ ]=m.digest( );


分析:執行MessageDigest對象的digest( )方法完成計算,計算的結果通過字節類型的數組返回。
(4)處理計算結果
必要的話可以使用如下代碼將計算結果(byte數組)轉換爲字符串。
 static String convertToHexString(byte data[]) {
  StringBuffer strBuffer = new StringBuffer();
  for (int i = 0; i < data.length; i++) {
   strBuffer.append(Integer.toHexString(0xff & data[i]));
  }
  return strBuffer.toString();
 }
3.2、示例一
★完整程序如下:
public class MessageDigestDemo extends Thread {
 public void run() {
  String text = "abc";
  byte data[] = null;
  MessageDigest m;
  try {
   data = text.getBytes("UTF8");
   m = MessageDigest.getInstance("MD5");
   m.update(data);
   byte resultData[] = m.digest();
   System.out.println(convertToHexString(resultData));
  } catch (NoSuchAlgorithmException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (UnsupportedEncodingException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }


 }


 static String convertToHexString(byte data[]) {
  StringBuffer strBuffer = new StringBuffer();
  for (int i = 0; i < data.length; i++) {
   strBuffer.append(Integer.toHexString(0xff & data[i]));
  }
  return strBuffer.toString();
 }
}
★運行結果
900150983cd24fb0d6963f7d28e17f72


 3.3、示例二
在這裏我們將對計算生成的md5使用 sun.misc.BASE64Encoder進行簡單的加密。
    public String md5sumWithEncoder(String text) throws NoSuchAlgorithmException, 
UnsupportedEncodingException{
        /*確定計算方法*/
        MessageDigest md5=MessageDigest.getInstance("MD5");
        BASE64Encoder base64en = new BASE64Encoder();
        /*加密後的散列碼字符串*/
        String strMd5=base64en.encode(md5.digest(text.getBytes("utf-8")));
        return strMd5;
    }
調用函數
String str="0123456789"
 System.out.println(md5sumWithEncoder(str));
 輸出
eB5eJF1ptWaXm4bijSPyxw==
3.4、示例三
關於此請參考《一點關於計算MD5的封裝》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章