關(guān)于SHA算法原理與常用實(shí)現(xiàn)方式
看本文前,最好先看看之前的這一篇關(guān)于MD5算法的介紹。
定義
SHA算法(Secure Hash Algorithm),又叫安全散列算法。
SHA算法是基于MD4算法的基礎(chǔ)上,演變而來。
但SHA算法出生好,是美國國家安全局設(shè)計(jì)的。
SHA算法,是一個(gè)系列家族,包括SHA-1,SHA-2(SHA-224、SHA-256、SHA-384、SHA-512),括號(hào)中的四個(gè)通常被統(tǒng)稱為SHA-2。
JDK中對(duì)SHA-1、SHA-256、SHA-384、SHA-512都有實(shí)現(xiàn)。
- SHA-1的最終密碼長(zhǎng)度是160位。
- SHA-256的最終密碼長(zhǎng)度是256位。
- SHA-384的最終密碼長(zhǎng)度是384位。
- SHA-512的最終密碼長(zhǎng)度是512位。
SHA算法,實(shí)際上也是一種消息摘要算法,這個(gè)和MD算法是類似的。
本文主要介紹SHA-256算法。
任意長(zhǎng)度的消息文件,通過SHA-256算法加密,最終得到的密文都是256位(32字節(jié)),通常用一個(gè)長(zhǎng)度為64的十六進(jìn)制字符串來表示。
效果上,SHA算法,與MD5算法都差不多,主要特點(diǎn)都是不可逆。
MD5和SHA-1的碰撞問題
碰撞問題,就是指對(duì)于一個(gè)算法,由明文生成的密文,并不是唯一的,甚至可以人為的通過構(gòu)造新的明文去得到指定的密文。
對(duì)于能出現(xiàn)這種情況的算法,我們就說這個(gè)算法是有碰撞問題的,簡(jiǎn)單理解就是兩個(gè)不同的明文,通過算法加密,卻得到了同樣的密文。
目前為止,MD5算法和SHA-1算法,都被證實(shí)了存在碰撞問題。
所以在安全性特別高的場(chǎng)景下,都不會(huì)用MD5算法和SHA-1算法,至少都用SHA-256算法了。
常見應(yīng)用場(chǎng)景
1、類似MD5的應(yīng)用場(chǎng)景
MD5的應(yīng)用場(chǎng)景,SHA算法基本也都可以使用。
2、比特幣
比特幣中,挖礦算法其實(shí)就是SHA-256算法,礦工們根據(jù)不斷修改隨機(jī)數(shù),不斷的進(jìn)行SHA-256運(yùn)算,最終算的快的挖到礦。
3、https簽名算法會(huì)用到
打開瀏覽器,以谷歌為例,查看任意一個(gè)整數(shù)的詳情:
簽名算法就是:帶 RSA 加密的 SHA-256,如下圖:
SHA-256算法原理
SHA家族的基本算法思想,都和MD5一樣,先定義常量,然后循環(huán)計(jì)算,最后組裝,不同的就是循環(huán)里面的計(jì)算方式。
1、填補(bǔ)信息
類似MD5
2、拿到初始值
MD5中有4個(gè)初始值,而SHA-256中,有8個(gè)。
h0 := 0x6a09e667 h1 := 0xbb67ae85 h2 := 0x3c6ef372 h3 := 0xa54ff53a h4 := 0x510e527f h5 := 0x9b05688c h6 := 0x1f83d9ab h7 := 0x5be0cd19
3、真正的計(jì)算
計(jì)算分為多次循環(huán),每次循環(huán),都是用ABCD和原文在第一步填補(bǔ)完的信息,進(jìn)行計(jì)算,最終得到新的ABCD。最后將最后一次ABCD拼成字符串,就是最終的密文。
- 循環(huán)先分為主循環(huán),每個(gè)主循環(huán)中又套有子循環(huán)。
- 主循環(huán)次數(shù) = 原文長(zhǎng)度/512。
- 子循環(huán)次數(shù) = 64次。
我們看看單次子循環(huán)都做了什么:
下面是單次子循環(huán)真正的計(jì)算邏輯(這段實(shí)現(xiàn)摘自網(wǎng)友):
java實(shí)現(xiàn)和使用
其實(shí)看過上一篇MD5介紹的,就會(huì)發(fā)現(xiàn),其實(shí)SHA的java實(shí)現(xiàn),和MD5的java實(shí)現(xiàn),幾乎一模一樣。
唯一的不同,就是MessageDigest.getInstance(“SHA”);這個(gè)方法中:
- SHA-1算法的入?yún)⑹荢HA
- SHA-256算法的入?yún)⑹荢HA-256
- SHA-384算法的入?yún)⑹荢HA-384
- SHA-512算法的入?yún)⑹荢HA-512
MD5的入?yún)⑹荕D5
public class SHA1Util { public static void main(String[] args) throws IOException { System.out.println(encodeString("123")); } public static String encodeString(String plainText) throws UnsupportedEncodingException { return encodeBytes(plainText.getBytes("UTF-8")); } public static String encodeBytes(byte[] bytes) { try { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(bytes); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < b.length; offset++) { i = b[offset]; if (i < 0) { i += 256; } if (i < 16) { buf.append("0"); } buf.append(Integer.toHexString(i)); } return buf.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)之實(shí)現(xiàn)雙向鏈表的示例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)雙向鏈表的示例,需要的朋友可以參考下2014-03-03springboot配置多數(shù)據(jù)源(靜態(tài)和動(dòng)態(tài)數(shù)據(jù)源)
在開發(fā)過程中,很多時(shí)候都會(huì)有垮數(shù)據(jù)庫操作數(shù)據(jù)的情況,需要同時(shí)配置多套數(shù)據(jù)源,本文主要介紹了springboot配置多數(shù)據(jù)源(靜態(tài)和動(dòng)態(tài)數(shù)據(jù)源),感興趣的可以了解一下2023-09-09Android 資源 id詳解及的動(dòng)態(tài)獲取
這篇文章主要介紹了Android 資源 id詳解及的動(dòng)態(tài)獲取的相關(guān)資料,需要的朋友可以參考下2016-12-12一篇文章教你如何用多種迭代寫法實(shí)現(xiàn)二叉樹遍歷
這篇文章主要介紹了C語言實(shí)現(xiàn)二叉樹遍歷的迭代算法,包括二叉樹的中序遍歷、先序遍歷及后序遍歷等,是非常經(jīng)典的算法,需要的朋友可以參考下2021-08-08解決ObjectMapper.convertValue() 遇到的一些問題
這篇文章主要介紹了解決ObjectMapper.convertValue() 遇到的一些問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法
這篇文章主要介紹了SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11關(guān)于SpringMVC請(qǐng)求域?qū)ο蟮臄?shù)據(jù)共享問題
這篇文章主要介紹了SpringMVC請(qǐng)求域?qū)ο蟮臄?shù)據(jù)共享問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02