真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java加解密(五)信息摘要算法-創(chuàng)新互聯(lián)

目錄
  • 信息摘要算法
    • 1 定義
    • 2 特點
    • 3 使用場景
    • 4 常用的非對稱加密算法
      • 4.1 MD(Message Digest)消息摘要
      • 4.2 SHA(Secure Hash Algorithm)安全散列
      • 4.3 MAC(Message Authentication Code)消息認證碼
    • 5 JDK支持的信息摘要算法
    • 6 Bouncy Castle 支持的信息摘要算法
    • 7 信息摘要算法的破解
      • 7.1 碰撞
      • 7.2 MD5的破解
        • 7.2.1 窮舉法
        • 7.2.2 字典法
        • 7.2.3 彩虹表
        • 7.2.4 差分攻擊
      • 7.3 降低MD5的破解概率
    • 8 算法調(diào)用示例

10年積累的成都做網(wǎng)站、成都網(wǎng)站制作經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先網(wǎng)站設計后付款的網(wǎng)站建設流程,更有平城免費網(wǎng)站建設讓你可以放心的選擇與我們合作。信息摘要算法 1 定義

數(shù)據(jù)摘要算法(信息摘要)是密碼學算法中非常重要的一個分支,它通過對所有數(shù)據(jù)提取指紋信息以實現(xiàn)數(shù)據(jù)簽名、數(shù)據(jù)完整性校驗等功能,由于算法具有其不可逆性,有時候也會被用做敏感信息加密。

消息摘要算法的主要特征是加密過程不需要密鑰,并且經(jīng)過加密的數(shù)據(jù)無法被解密,可以被解密逆向的只有CRC32算法,只有輸入相同的明文數(shù)據(jù)經(jīng)過相同的消息摘要算法才能得到相同的密文。

消息摘要算法也叫散列函數(shù)、哈希函數(shù),嚴格的說并不算是一種加密算法。消息摘要算法的主要作用不是完成數(shù)據(jù)的加密與解密工作的,它是用來驗證數(shù)據(jù)完整性的重要技術(shù)。通過摘要函數(shù),可以為數(shù)據(jù)創(chuàng)建“數(shù)字指紋”(散列值)。

需要指出的是MAC(Message Authentication Code)算法是支持密鑰的一種摘要算法。

2 特點
  • 單向不可逆:消息摘要函數(shù)是無陷門的單向函數(shù),即只能進行正向的信息摘要,而無法從摘要中恢復出任何的消息,甚至根本就找不到任何與原信息相關的信息
  • 相同的輸入必會產(chǎn)生相同的輸出,且不同輸入得到相同輸出的概率極低(如果遇到這種情況,就叫碰撞)
  • 散列值不同,則原始消息一定不同
  • 無論輸入的數(shù)據(jù)長度多少,得到的輸出值長度是固定的(不同的哈希算法長度不一樣)
3 使用場景

在計算機領域,我們希望能知道別人傳遞的消息是否完整、是否有被篡改,這里就用到信息摘要算法。

例如我們要在數(shù)據(jù)庫中保存用戶密碼,首先肯定不能保存明文,既然要使用密文保存,那使用對稱加密還是非對稱加密呢?結(jié)合實際場景和安全性考慮,兩種都不合適!因為這兩種都要考慮密鑰的管理,如果密鑰泄漏那密碼則有被破解的風險。在這種場景下,我們可以使用單向散列函數(shù)來解決這個問題,這樣即使算法和密文都泄漏,也無法逆向計算出明文。

當然散列函數(shù)還有更多用途,比如文件一致性校驗、數(shù)字簽名等。

4 常用的非對稱加密算法

信息摘要算法來源于CRC算法,最初CRC算法是用來驗證數(shù)據(jù)完整性的,即我們常見的奇偶校驗碼、循環(huán)冗余校驗,在CRC基礎上發(fā)展出了MD和SHA兩大算法家族,CRC比這些算法都要早,MD算法比SHA算法早,SHA算法是對MD算法的改進。再后來則發(fā)展出了可以帶有密碼的信息摘要算法-MAC算法。

信息摘要算法包括三大類,MD、SHA和MAC算法,MD的分類是按照版本規(guī)定的,SHA一般是按照產(chǎn)生的消息長度分類的,但是SHA系列算法在學術(shù)上會按照算法版本區(qū)分SHA-0、SHA-1、SHA-2、SHA-3,
MAC算法是Hmac加融合的其他算來命名的。

  • MD系列算法: Message Digest Algorithm ,目前主流的是MD5算法,為第五版算法,之前有MD2、MD3、MD4算法。
  • SHA系列算法:安全哈希算法(Secure Hash Algorithm)主要適用于數(shù)字簽名標準(Digital Signature Standard DSS)里面定義的數(shù)字簽名算法(Digital Signature Algorithm DSA);
  • MAC系列算法:帶有密碼信息的信息摘要算法,學名:密鑰散列消息認證碼,是對MD和SHA算法的演變和改進,包括Hmac-MD2、Hmac-MD4、Hmac-MD5、Hmac-SHA-256等。
  • CRC算法比較古老,但是在數(shù)據(jù)壓縮領域被廣泛使用作為完整性校驗
4.1 MD(Message Digest)消息摘要

MD5算法是典型的消息摘要算法,它由MD4、MD3、MD2算法改進而來。無論是哪種MD算法,它們都需要獲得一個隨機長度的信息并產(chǎn)生一個128位的二進制信息摘要,轉(zhuǎn)換成16進制就是32位的字符串。我們見到的大部分MD5算法的數(shù)字指紋都是32位十六進制的字符串。

隨著計算機發(fā)展水平的提高,MD5算法已不再適合安全要求較高的場合。

4.2 SHA(Secure Hash Algorithm)安全散列

SHA算法基于MD4算法基礎之上,其與MD算法不同之處在于摘要長度,SHA算法的摘要長度更長,安全性更高。

SHA-0算法,1983年第一個版本,因降低密碼安全性撤回
SHA-1算法,1995年發(fā)布,通常我們也把SHA-1算法簡稱為SHA算法。其在安全協(xié)定中使用廣泛。包括TLS/SSL,SSH等。SHA-0和SHA-1算法可對大長度為264的字節(jié)信息做摘要處理,得到160位的摘要信息,40為16進制的字符串
SHA-2算法,是SHA-224,SHA-256,SHA-384,SHA-512四種算法的總稱。

4.3 MAC(Message Authentication Code)消息認證碼

MAC算法結(jié)合了MD5和SHA算法的優(yōu)勢,并加入了密鑰的支持,是一種更為安全的消息摘要算法。我們也通常把MAC算法稱為HMAC算法(keyed-Hash Message Authentication Code)。

MD系列算法與SHA系列算法分別是兩種不同形式的信息摘要算法,都是沒有密鑰的散列函數(shù)算法。MAC兼容了MD與SHA這兩種的特性,并且在這個基礎上添加了密鑰。通常又把MAC稱為HMAC,即含有密鑰的散列函數(shù)算法。

MAC算法則為MD與SHA系列算法的基礎上添加了密鑰,構(gòu)成了新的算法:HmacMD2、HmacMD4、HmacMD5、HmacSHA1、HmacSHA224、HmacSHA356、HmacSHA384、HmacSHA512。

5 JDK支持的信息摘要算法

JDK8原生算法列表,可參第一篇博文: https://blog.csdn.net/yunyun1886358/article/details/128592503#311_JDK_Provider_63

6 Bouncy Castle 支持的信息摘要算法

Bouncy Castle算法列表,可參第一篇博文:
https://editor.csdn.net/md/?articleId=128592503#323_Bouncy_Castle_Provider_568

7 信息摘要算法的破解 7.1 碰撞

碰撞不可逆是破解摘要算法的基礎。

碰撞就是先基于消息1用信息摘要算法算出一個摘要值,再根據(jù)這個值,逆算出另外一個不同的消息2,但是它們的摘要值是一樣的。

如果我們能找到一個消息2,生成的摘要與原始消息1是一樣的,那么無論消息1和2是否一樣,我們都可以將消息2發(fā)送給校驗方,并通過校驗。因為校驗方只持有摘要值,并且根據(jù)摘要值無法還原消息1,校驗方也不知道消息1是什么,他只校驗消息2通過算法生成的摘值和他持有的是一致,校驗就通過了。

2004年,我國中科院院士王小云證實md5算法無法防止碰撞,因此,不適用于安全性認證。她的研究成果表明了給定消息 M1,能夠計算獲取 M2,使得 M2 產(chǎn)生的散列值與 M1 產(chǎn)生的散列值相同。

7.2 MD5的破解

都說MD5已經(jīng)被證明是一種不安全的算法,那么如何對MD5進行碰撞呢 ?

7.2.1 窮舉法

窮舉法就是不停地嘗試各種字符的排列組合,看哪一個組合的MD5碼能對上。缺點是太耗費時間。舉個例子,假設我們要破解一個6位大小寫字母和數(shù)字混合的密碼,那么一共有 (26 + 26 + 10) ^ 6 種組合。這個數(shù)的大小超過500億。

7.2.2 字典法

字典法就是把計算結(jié)果以映射表的形式存放起來,一個原文對應著一個MD5值。將已知的MD5碼查表,就可直接反查出原文。字典法體現(xiàn)了算法設計的“以空間換時間”的思想。缺點是比較耗費空間,而且實際上還是要窮舉一遍所有的輸入,只不過把窮舉的結(jié)果存了起來。
一個用字典法實現(xiàn)md5解密的網(wǎng)站:https://md5.cn/

7.2.3 彩虹表

如果說窮舉法太耗費時間,字典法太耗費存儲空間的話,我們能不能考慮在時間消耗和空間消耗之間折中呢?我們可以考慮用鏈表將一系列有意義的原文和 MD5 碼串起來。
大概方法就是將一部分MD5摘要值和原文按照相近性分別保存到不同的哈希鏈表中,然后根據(jù)要破解的MD5摘要值計算出原始消息可能存在那條鏈表中,然后這條鏈表的頭開始計算,然后得到碰撞值。

一個已經(jīng)計算好的彩虹表: http://project-rainbowcrack.com/table.htm

7.2.4 差分攻擊

上面介紹的窮舉法、字典法和彩虹表法都是暴力破解,適用于任何的消息摘要算法。真正意義上 MD5 算法的破解,是 2004 年山東大學王小云教授提出的 MD5 碰撞方法。她所用到的方法正是差分攻擊。

這種方法概括起來說是這樣的:給定一個 1024 位的原文 M1,加上一個特定的常數(shù)得到的新的明文 M2。M1 和 M2 的 MD5 碼是一樣的。

7.3 降低MD5的破解概率

有一種方法可以降低MD5碰撞的概率,那就是在計算摘要的時候加,也就是

MD5(原文 + 鹽)

鹽可以是任意字母、數(shù)字、或是字母或數(shù)字的組合,但必須是隨機產(chǎn)生的,最好每次摘要加的鹽都不一樣。

例如網(wǎng)站用戶注冊,保存用戶密碼時,為每個用戶生成一個隨機的鹽,然后將 MD5( 明文密碼 + 鹽)摘要值存入用戶表,并且在用戶表中添加一個字段,用來保存鹽。

由于加了鹽,即便數(shù)據(jù)庫泄露了,但是由于密碼都是加了鹽之后的散列,數(shù)據(jù)字典已經(jīng)無法直接匹配,明文密碼被碰撞成功的概率也大大降低。

是不是加了鹽之后就絕對安全了呢?當然沒有。攻擊者還是可以他們數(shù)據(jù)字典中的密碼,加上我們泄露數(shù)據(jù)庫中的 Salt,然后散列,然后再匹配。這要就需要重新生成數(shù)據(jù)字典,但是由于我們的鹽是隨機產(chǎn)生的,假如我們的用戶數(shù)據(jù)表中有 100w 條數(shù)據(jù),那么就有100w個鹽。如數(shù)據(jù)字典中有 1000w 條數(shù)據(jù),那么如果要生成新的數(shù)據(jù)字典,那么數(shù)字典的明文加上鹽之后再散列的數(shù)據(jù)字典數(shù)據(jù)量就應該是 1,000,000* 10,000,000 = 10,000,000,000,000,共10兆條數(shù)據(jù),成本非常之高。

8 算法調(diào)用示例

下面的代碼將JDK提供的幾種信息摘要算法用枚枚舉類進行了封裝。

package com.qupeng.crypto.algorithm.oop;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class DigestAlgorithmTest {@Rule
    public final ExpectedException exception = ExpectedException.none();

    @Test
    public void digest() throws NoSuchAlgorithmException {Assert.assertEquals("Ow7l+x4vPrlj/ZrwYVPHjw==", DigestAlgorithm.MD2.digest("12345678901234567890"));
        Assert.assertEquals("/YXmLZvrRUKHcexohBiycQ==", DigestAlgorithm.MD5.digest("12345678901234567890"));
        Assert.assertEquals("fgoSQr2O+QRPJ9ykX19yrVoRJb8=", DigestAlgorithm.SHA_1.digest("12345678901234567890"));
        Assert.assertEquals("LGQud880sKr3FSrFxbJtG9c/24h0vLDZHHyRPw==", DigestAlgorithm.SHA_224.digest("12345678901234567890"));
        Assert.assertEquals("t72NaA22sXKHBeXh1BlYyTryjk2KKJ4A3DckaRxbXTw+RBznZieVycTGAgbzNWkp", DigestAlgorithm.SHA_384.digest("12345678901234567890"));
        Assert.assertEquals("btZF7w4avqG/Hk6TX/BPnhjTmBI4f2PNo0FbRiQPBAU=", DigestAlgorithm.SHA_256.digest("12345678901234567890"));
        Assert.assertEquals("qjt73ZjsRK8fOVu9X38npc2VadeU0DJ0cyO/SxUh++dyWHWmi0QKvfBVneUBW6+HO7nAHK5j7OqTrVR6c5dBbg==", DigestAlgorithm.SHA_512.digest("12345678901234567890"));
    }

    @Test(expected=NoSuchAlgorithmException.class)
    public void digestBySha512224() throws NoSuchAlgorithmException {DigestAlgorithm.SHA_512_224.digest("12345678901234567890");
    }

    @Test
    public void digestBySha512256() throws NoSuchAlgorithmException {exception.expect(NoSuchAlgorithmException.class);
        exception.expectMessage("SHA-512/256 MessageDigest not available");
        DigestAlgorithm.SHA_512_256.digest("12345678901234567890");
    }

    @Test
    public void digestMAC() throws InvalidKeyException, NoSuchAlgorithmException {String digestStr = DigestAlgorithm.HMAC_MD5.digestMAC("12345678901234567890", 128);
        Assert.assertEquals(DigestAlgorithm.HMAC_MD5.getDigestMessageLength(), Base64.getDecoder().decode(digestStr).length * 8);

        digestStr = DigestAlgorithm.HMAC_SHA1.digestMAC("12345678901234567890", 128);
        Assert.assertEquals(DigestAlgorithm.HMAC_SHA1.getDigestMessageLength(), Base64.getDecoder().decode(digestStr).length * 8);

        digestStr = DigestAlgorithm.HMAC_SHA224.digestMAC("12345678901234567890", 128);
        Assert.assertEquals(DigestAlgorithm.HMAC_SHA224.getDigestMessageLength(), Base64.getDecoder().decode(digestStr).length * 8);

        digestStr = DigestAlgorithm.HMAC_SHA256.digestMAC("12345678901234567890", 128);
        Assert.assertEquals(DigestAlgorithm.HMAC_SHA256.getDigestMessageLength(), Base64.getDecoder().decode(digestStr).length * 8);

        digestStr = DigestAlgorithm.HMAC_SHA384.digestMAC("12345678901234567890", 128);
        Assert.assertEquals(DigestAlgorithm.HMAC_SHA384.getDigestMessageLength(), Base64.getDecoder().decode(digestStr).length * 8);

        digestStr = DigestAlgorithm.HMAC_SHA512.digestMAC("12345678901234567890", 128);
        Assert.assertEquals(DigestAlgorithm.HMAC_SHA512.getDigestMessageLength(), Base64.getDecoder().decode(digestStr).length * 8);
    }
}
package com.qupeng.crypto.algorithm.oop;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public enum DigestAlgorithm {MD2("MD2", 128),
    MD5("MD5", 128),
    SHA_1("SHA-1", 160),
    SHA_224("SHA-224", 224),
    SHA_256("SHA-256", 256),
    SHA_384("SHA-384", 384),
    SHA_512("SHA-512", 512),
    SHA_512_224("SHA-512/224", 512),
    SHA_512_256("SHA-512/256", 512),
    HMAC_MD5("HmacMD5", 128),
    HMAC_SHA1("HmacSHA1", 160),
    HMAC_SHA224("HmacSHA224", 224),
    HMAC_SHA256("HmacSHA256", 256),
    HMAC_SHA384("HmacSHA384", 384),
    HMAC_SHA512("HmacSHA512", 512);

    private String algorithm = "";
    private int digestMessageLength = -1;

    DigestAlgorithm(String algorithm, int digestMessagLength) {this.algorithm = algorithm;
        this.digestMessageLength = digestMessagLength;
    }

    public String digest(String plainText) throws NoSuchAlgorithmException {MessageDigest messageDigest = MessageDigest.getInstance(this.algorithm);
        byte [] bytes = messageDigest.digest(plainText.getBytes());
        String digestStr = Base64.getEncoder().encodeToString(bytes);
        System.out.println(String.format("%s(%d) plain text: %s ->digest text: %s", this.algorithm, this.digestMessageLength, plainText, digestStr));
        return digestStr;
    }

    public String digestMAC(String plainText, int keyLength) throws NoSuchAlgorithmException, InvalidKeyException {KeyGenerator keyGenerator = KeyGenerator.getInstance(this.algorithm);
        keyGenerator.init(keyLength);
        SecretKey secretKey = keyGenerator.generateKey();
        Mac mac = Mac.getInstance(this.algorithm);
        mac.init(secretKey);
        byte[] hmacMD5Bytes = mac.doFinal(plainText.getBytes());
        String digestStr = Base64.getEncoder().encodeToString(hmacMD5Bytes);
        System.out.println(String.format("%s(%d) plain text: %s ->digest text: %s", this.algorithm, this.digestMessageLength, plainText, digestStr));
        return digestStr;
    }

    public int getDigestMessageLength() {return digestMessageLength;
    }
}

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


本文標題:Java加解密(五)信息摘要算法-創(chuàng)新互聯(lián)
文章URL:http://weahome.cn/article/esdji.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部