官术网_书友最值得收藏!

3.2 哈希

3.2.1 散列函數簡介

哈希函數也稱為散列函數,在維基百科中的定義如下:

散列函數是可以將任意大小的數據映射到固定大小數據的任何函數。散列函數返回的值稱為散列值、哈希代碼、摘要或簡單散列。散列函數通常與哈希表配合使用,哈希表是計算機軟件中用于快速查找數據的常用數據結構。

作為加密算法的一種,散列函數是一種單向密碼體制,即一個從明文到密文的不可逆映射,只有加密過程,沒有解密過程。

散列函數的主要特點有:壓縮性強、計算簡單、計算結果單向性。壓縮性強是指對于任意大小的輸入內容,哈希值的長度很小,而且長度是固定位數的。計算簡單是指對于任意給定的消息,計算其哈希值都比較簡單。計算結果單向性是指對于給定的哈希值,無法倒推輸入的原始數值。這也是散列函數安全性的重要基礎。

當然,將無限內容壓縮到有限位數的取值范圍內,不可避免會出現不同的內容卻有相同哈希值的碰撞結果。因此抗碰撞性是一個良好的散列函數的必備條件。

目前,哈希算法主要有兩類:MD系列和SHA系列。MD(Message Digest,消息摘要)系列有MD4、MD5、HAVAL等,SHA(Secure Hash Algorithm,安全散列算法)系列有SHA1、SHA256等。其中,MD5是密碼學專家R.L.Rivest設計的,SHA是美國算法制定機構設計的。

常見的哈希算法有SHA-1算法、SHA-2算法、SHA-3算法,分別介紹如下。

1)SHA-1算法

SHA-1算法的輸入是最大長度小于264位的消息,輸入消息以512位的分組為單位進行處理,輸出是160位的消息摘要。SHA-1算法具有實現速度高、容易實現、應用范圍廣等優點。

2)SHA-2算法

SHA-2算法的輸出長度可取224位、256位、384位、512位,分別對應SHA-224、SHA-256、SHA-384、SHA-512。它還包含另外兩個算法:SHA-512/224、SHA-512/256。比之前的哈希算法具有更強的安全強度和更靈活的輸出長度,其中,SHA-256是常用算法。SHA-256算法的輸入是最大長度小于264位的消息,輸出是256位的消息摘要,輸入消息以512位的分組為單位進行處理。

3)SHA-3算法

美國政府選擇Keccak算法作為SHA-3算法的加密標準,因為Keccak算法擁有良好的加密性能以及抗解密能力。

4)RIPEMD算法

RIPEMD(RACE Integrity Primitives Evaluation Message Digest),即RACE原始完整性校驗消息摘要。RIPEMD使用MD4的設計原理,并針對MD4的算法缺陷進行了改進,1996年首次發布RIPEMD-128版本,它在性能上與SHA-1算法類似。

上述算法中,SHA-1算法已經破解,SHA-2算法是使用范圍較為廣泛的算法,經常用于數字簽名領域。對研發小伙伴而言,我們去開源網站下載源代碼的過程中完整性校驗就是基于哈希算法的。

在區塊鏈系統中,目前使用的主流哈希算法是SHA-256,下面將從實戰的角度,為讀者展示如何進行哈希計算。

3.2.2 SHA-256 Java實戰

我們可以用多種方法來實現用Java編寫SHA-256的哈希計算接口??梢曰贏pache commons-codec的工具類來實現SHA-256加密,也可以利用Hutool的工具類來實現SHA-256加密。

下面展示利用Apache commons-codec的工具類實現SHA-256加密的代碼和利用Hutool的工具類實現SHA-256加密的代碼,代碼如下:

package com.niudong.demo.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Hex;
import cn.hutool.crypto.digest.DigestUtil;

public class SHAUtil {

  /***
  * 利用Apache commons-codec的工具類實現SHA-256加密
  *
  * @param originalStr加密前的報文
  * @return String加密后的報文
  */
  public static String getSHA256BasedMD(String originalStr) {
    MessageDigest messageDigest;
    String encdeStr = "";
    try {
      messageDigest = MessageDigest.getInstance("SHA-256");
      byte[] hash = messageDigest.digest(originalStr.getBytes("UTF-8"));
      encdeStr = Hex.encodeHexString(hash);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return encdeStr;
  }

  /***
  * 利用Hutool的工具類實現SHA-256加密
  *
  * @param originalStr加密前的報文
  * @return String加密后的報文
  */
  public static String sha256BasedHutool(String originalStr) {
    return DigestUtil.sha256Hex(originalStr);
  }
}

如上述代碼所示,我們實現了getSHA256BasedMD()和sha256BasedHutool()方法,下面編寫單元測試代碼對兩個方法進行測試,單元測試代碼如下:

    package com.niudong.demo.util;

    import org.testng.Assert;
    import org.testng.annotations.Test;

    public class SHAUtilTest {
      /**
      * SHAUtil測試類
      */

      // 測試getSHA256方法
      @Test
      public void testGetSHA256() {
        String originalStr = "區塊鏈是分布式數據存儲、點對點傳輸、共識機制、加密
          算法等計算機技術的新型應用模式。";

Assert.assertEquals("3c8fede03b42a9a3186fb96d7f22a1862bcb00e445e0b2956 6c613590306e3da",
          SHAUtil.getSHA256BasedMD(originalStr));
      }

      // 測試getSHA256方法
      @Test
      public void testSha256BasedHutool() {
        String originalStr = "區塊鏈是分布式數據存儲、點對點傳輸、共識機制、加密
          算法等計算機技術的新型應用模式。";

Assert.assertEquals("3c8fede03b42a9a3186fb96d7f22a1862bcb00e445e0b2956 6c613590306e3da",
          SHAUtil.sha256BasedHutool(originalStr));
      }
    }

在IDE窗口右擊鼠標,在右鍵快捷菜單中單擊“Run As”,在彈出的下拉列表中選擇“TestNG test”,執行單元測試代碼。測試結果輸出如下:

PASSED: testGetSHA256
PASSED: testSha256BasedHutool

===============================================
    Default test
    Tests run: 2, Failures: 0, Skips: 0
===============================================

===============================================
Default suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.
    JUnitReportReporter@2d3fcdbd:  9 ms
[TestNG] Time taken by org.testng.reporters.
    EmailableReporter2@1936f0f5: 12 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@62043840: 66 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 0 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@3567135c: 10 ms
[TestNG] Time taken by
    org.testng.reporters.SuiteHTMLReporter@180bc464: 54 ms
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
主站蜘蛛池模板: 潮安县| 彭山县| 融水| 枣阳市| 临夏市| 手游| 泾川县| 奈曼旗| 故城县| 宁化县| 稷山县| 金秀| 梧州市| 大渡口区| 类乌齐县| 苍溪县| 吴旗县| 绥江县| 四川省| 云阳县| 紫金县| 平塘县| 鸡西市| 泸定县| 灌阳县| 明水县| 甘谷县| 上犹县| 崇文区| 武平县| 苗栗市| 麻城市| 河东区| 长葛市| 贵南县| 玉田县| 邵阳市| 盐边县| 葫芦岛市| 汝城县| 泽库县|