Java生成摘要(MD5 SHA-1)

剛好最近項目中需要用到一點加密的東西,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;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章