計(jì)算文件Checksum的幾種方法

checksum簡(jiǎn)介

回憶一下幽纷,自己是否在網(wǎng)站上下載文件時(shí)看到過(guò)Checksum這個(gè)東西,一串字符串?

比如挠羔,我們到Apache網(wǎng)站上去下載用于操作Excel的依賴(lài)包 Apache POI,就可以看到checksum:SHA-256埋嵌, SHA-512破加。以poi-bin-4.1.0-20190412.tar.gz文件為例,點(diǎn)擊SHA-256和SHA-512的鏈接查看相關(guān)的值如下:

##SHA-256的值
d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb

##SHA-512的值
87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9

本文將簡(jiǎn)單介紹一下checksum(含義雹嗦,作用)以及如何使用java程序計(jì)算出不同算法的checksum值范舀,包括MD5SHA-1了罪,SHA-256以及SHA-512锭环。

Checksum:總和檢驗(yàn)碼,校驗(yàn)和泊藕。在數(shù)據(jù)處理和數(shù)據(jù)通信領(lǐng)域中辅辩,用于校驗(yàn)?zāi)康牡囊唤M數(shù)據(jù)項(xiàng)的和。這些數(shù)據(jù)項(xiàng)可以是數(shù)字或在計(jì)算檢驗(yàn)總和過(guò)程中看作數(shù)字的其它字符串吱七。通常是以十六進(jìn)制為數(shù)制表示的形式汽久。
作用:用于檢查文件完整性,檢測(cè)文件是否被惡意篡改踊餐,比如文件傳輸(如插件景醇、固件升級(jí)包等)場(chǎng)景使用。

計(jì)算checksum

接下來(lái)吝岭,我們一起看下怎么使用java程序產(chǎn)生相關(guān)的checksum值三痰,本文以文件poi-bin-4.1.0-20190412.tar.gz為例,具體可以通過(guò)如下路徑下載:

http://mirror.bit.edu.cn/apache/poi/release/bin/poi-bin-4.1.0-20190412.tar.gz

因?yàn)橐褂貌煌惴ǖ腸hecksum值窜管,包括MD5散劫、SHA-1,SHA-256以及SHA-512幕帆,先定義一個(gè)枚舉類(lèi)获搏,用于區(qū)分不同的算法。

package com.wangmengjun.tutorial.checksum;
 
public enum CheckSumAlgoType {
  MD5("MD5"), SHA_256("SHA-256"), SHA_512("SHA-512"), SHA_1("SHA1"); 
  private String name;
  private CheckSumAlgoType(String name) {    
      this.name = name;  
  }
  public String getName() {    return name;  }
  public void setName(String name) {    this.name = name;  }
}

接下來(lái)失乾,我們就來(lái)看看幾種計(jì)算文件checksum的方法:

  1. 使用java.security.MessageDigest
  2. 使用org.apache.commons.codec.digest.DigestUtils
  3. 使用com.google.common.io.Files.hash

使用java.security.MessageDigest

public static String genChecksum1(File file, String checkSumAlgo) throws NoSuchAlgorithmException, IOException {    
    MessageDigest messageDigest = MessageDigest.getInstance(checkSumAlgo);    
    messageDigest.update(Files.readAllBytes(file.toPath()));    
    byte[] digestBytes = messageDigest.digest();    
    StringBuffer sb = new StringBuffer();    
    for (byte b : digestBytes) {      
        sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));    
    }    
    return sb.toString();  
}

其中常熙,下面的這段代碼

StringBuffer sb = new StringBuffer();    
for (byte b : digestBytes) {      
    sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));    
}    
return sb.toString();

可以使用javax.xml.bind.DatatypeConverter的方法來(lái)做纬乍,簡(jiǎn)化后的代碼如下:

public static String genChecksum1(File file, String checkSumAlgo) throws NoSuchAlgorithmException, IOException {    
        MessageDigest messageDigest = MessageDigest.getInstance(checkSumAlgo);    
        messageDigest.update(Files.readAllBytes(file.toPath()));    
        byte[] digestBytes = messageDigest.digest();    
        return DatatypeConverter.printHexBinary(digestBytes).toLowerCase();  
}

因?yàn)?code>DatatypeConverter.printHexBinary(digestBytes)返回的字符大寫(xiě),所以添加了toLowerCase()方法保持其一致性裸卫。

使用org.apache.commons.codec.digest.DigestUtils

使用commons-codec來(lái)完成仿贬,Maven工程需要添加依賴(lài)包,如:

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>    
    <groupId>commons-codec</groupId>    
    <artifactId>commons-codec</artifactId>    
    <version>1.13</version>
</dependency>

簡(jiǎn)單代碼如下墓贿,通過(guò)調(diào)用類(lèi)DigestUtils的靜態(tài)方法完成指定checksum的計(jì)算即可:

public static String genChecksum2(File file, CheckSumAlgoType checkSumAlgoType)      throws FileNotFoundException, IOException {    
/**     * 使用org.apache.commons.codec.digest.DigestUtils     */    
        String checksum = null;    
        switch (checkSumAlgoType) {    
            case MD5:      
                checksum = DigestUtils.md5Hex(new FileInputStream(file));      
                break;
            case SHA_1:      
                checksum = DigestUtils.sha1Hex(new FileInputStream(file));      
                break;
            case SHA_256:      
                checksum = DigestUtils.sha256Hex(new FileInputStream(file));      
                break;    
            case SHA_512:      
                checksum = DigestUtils.sha512Hex(new FileInputStream(file));      
                break;    
            default:      
                checksum = DigestUtils.md5Hex(new FileInputStream(file));    
        }
        return checksum;  
}

使用com.google.common.io.Files.hash

使用Guava來(lái)完成茧泪,Maven工程需要添加依賴(lài)包,如:

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>    
    <groupId>com.google.guava</groupId>    
    <artifactId>guava</artifactId>    
    <version>23.0</version>
</dependency>

簡(jiǎn)單代碼如下聋袋,通過(guò)調(diào)用com.google.common.io.Fileshash方法即可:

public static String genChecksum3(File file, CheckSumAlgoType checkSumAlgoType) throws IOException {    
        /**     * 使用Guava     */    
        String checksum = null;    
        switch (checkSumAlgoType) {    
            case MD5:      
                checksum = com.google.common.io.Files.hash(file, Hashing.md5()).toString();
                break;    
            case SHA_1:      
                checksum = com.google.common.io.Files.hash(file, Hashing.sha1()).toString();      
                break;
            case SHA_256:      
                checksum = com.google.common.io.Files.hash(file, Hashing.sha256()).toString();      
                break;    
            case SHA_512:      
                checksum = com.google.common.io.Files.hash(file, Hashing.sha512()).toString();      
                break;    
            default:      
                checksum = com.google.common.io.Files.hash(file, Hashing.md5()).toString();    
        }    
        return checksum;  
}

驗(yàn)證

最后队伟,我們一起來(lái)驗(yàn)證一下上述幾種方法對(duì)文件的checksum計(jì)算。

public static void main(String[] args) throws NoSuchAlgorithmException, IOException {    
File file = new File("/users/wmj/Downloads/poi-bin-4.1.0-20190412.tar.gz");    
        for (CheckSumAlgoType type : CheckSumAlgoType.values()) {      
            System.out.println("采用" + type.getName() + "計(jì)算checksum");      
            System.out.println(          String.format("method=%s,checksum=%s", "genChecksum1", genChecksum1(file, type.getName())));      
            System.out.println(String.format("method=%s,checksum=%s", "genChecksum2", genChecksum2(file, type)));      
            System.out.println(String.format("method=%s,checksum=%s", "genChecksum3", genChecksum3(file, type)));      
            System.out.println();    
        }  
}

運(yùn)行結(jié)果如下:

采用MD5計(jì)算checksum
method=genChecksum1,checksum=2fa39c79790c29c53368ec0c14fdea97
method=genChecksum2,checksum=2fa39c79790c29c53368ec0c14fdea97
method=genChecksum3,checksum=2fa39c79790c29c53368ec0c14fdea97


采用SHA-256計(jì)算checksum
method=genChecksum1,checksum=d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb
method=genChecksum2,checksum=d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb
method=genChecksum3,checksum=d8db4f8228d87935ca46b0af72db68ad83f45b31d885e67b089d195b5ee800bb

采用SHA-512計(jì)算checksum
method=genChecksum1,checksum=87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9
method=genChecksum2,checksum=87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9
method=genChecksum3,checksum=87499ab94882605ee2f407fc66e24c613ae98896b8d5f527b6cd8c604574922fc72d148da42962b2ee30ad18cd712e3de42bfe14770261b07217717c52a738a9

采用SHA1計(jì)算checksum
method=genChecksum1,checksum=f56e42474fa81676d82a38ae6a8df67194a50b93
method=genChecksum2,checksum=f56e42474fa81676d82a38ae6a8df67194a50b93
method=genChecksum3,checksum=f56e42474fa81676d82a38ae6a8df67194a50b93

我們可以看到幽勒,計(jì)算結(jié)果和Apache上顯示的checksum是一致的缰泡。

總結(jié)

本文主要給出了三種計(jì)算checksum的方式,包括:

使用java.security.MessageDigest
使用org.apache.commons.codec.digest.DigestUtils
使用com.google.common.io.Files.hash

當(dāng)然代嗤,可能還有其它的實(shí)現(xiàn)方式和工具包,如果讀者發(fā)現(xiàn)其它的也可以同步一下缠借,一起學(xué)習(xí)干毅。

作者:孟君的編程札記
鏈接:https://www.imooc.com/article/290973?block_id=tuijian_wz
來(lái)源:慕課網(wǎng)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市泼返,隨后出現(xiàn)的幾起案子硝逢,更是在濱河造成了極大的恐慌,老刑警劉巖绅喉,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渠鸽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡柴罐,警方通過(guò)查閱死者的電腦和手機(jī)徽缚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)革屠,“玉大人凿试,你說(shuō)我怎么就攤上這事∷浦ィ” “怎么了那婉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)党瓮。 經(jīng)常有香客問(wèn)我详炬,道長(zhǎng),這世上最難降的妖魔是什么寞奸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任呛谜,我火速辦了婚禮在跳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呻率。我一直安慰自己硬毕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布礼仗。 她就那樣靜靜地躺著吐咳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天吐辙,我揣著相機(jī)與錄音蟋定,去河邊找鬼。 笑死臣镣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔫饰,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼愉豺!你這毒婦竟也來(lái)了篓吁?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蚪拦,失蹤者是張志新(化名)和其女友劉穎杖剪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體驰贷,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盛嘿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了括袒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片次兆。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锹锰,靈堂內(nèi)的尸體忽然破棺而出类垦,到底是詐尸還是另有隱情,我是刑警寧澤城须,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布蚤认,位于F島的核電站,受9級(jí)特大地震影響糕伐,放射性物質(zhì)發(fā)生泄漏砰琢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望陪汽。 院中可真熱鬧训唱,春花似錦、人聲如沸挚冤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)训挡。三九已至澳骤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間澜薄,已是汗流浹背为肮。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肤京,地道東北人颊艳。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像忘分,于是被迫代替她去往敵國(guó)和親棋枕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361