Java 詳解單向加密--MD5、SHA和HMAC及簡單實現實例
概要:
MD5、SHA、HMAC這三種加密算法,可謂是非可逆加密,就是不可解密的加密方法。
MD5
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于確保信息傳輸完整一致。MD5是輸入不定長度信息,輸出固定長度128-bits的算法。
MD5算法具有以下特點:
1、壓縮性:任意長度的數據,算出的MD5值長度都是固定的。
2、容易計算:從原數據計算出MD5值很容易。
3、抗修改性:對原數據進行任何改動,哪怕只修改1個字節,所得到的MD5值都有很大區別。
4、強抗碰撞:已知原數據和其MD5值,想找到一個具有相同MD5值的數據(即偽造數據)是非常困難的。
MD5還廣泛用于操作系統的登陸認證上,如Unix、各類BSD系統登錄密碼、數字簽名等諸多方面。如在Unix系統中用戶的密碼是以MD5(或其它類似的算法)經Hash運算后存儲在文件系統中。當用戶登錄的時候,系統把用戶輸入的密碼進行MD5 Hash運算,然后再去和保存在文件系統中的MD5值進行比較,進而確定輸入的密碼是否正確。通過這樣的步驟,系統在并不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統的合法性。這可以避免用戶的密碼被具有系統管理員權限的用戶知道。MD5將任意長度的“字節串”映射為一個128bit的大整數,并且通過該128bit反推原始字符串是非常困難的。
SHA
SHA(Secure Hash Algorithm,安全散列算法),數字簽名等密碼學應用中重要的工具,被廣泛地應用于電子商務等信息安全領域。雖然SHA與MD5通過碰撞法都被破解了, 但是SHA仍然是公認的安全加密算法,較之MD5更為安全。
SHA所定義的長度
下表中的中繼散列值(internal state)表示對每個數據區塊壓縮散列過后的中繼值(internal hash sum)。
算法 | 輸出散列值長度(bits) | 中繼散列值長度(bits) | 數據區塊長度(bits) | 最大輸入消息長度(bits) | 一個Word長度(bits) | 循環次數 | 使用到的運算符 | 碰撞攻擊 |
---|---|---|---|---|---|---|---|---|
SHA-0 | 160 | 160 | 512 | 264 − 1 | 32 | 80 | +,and,or,xor,rotl | 是 |
SHA-1 | 160 | 160 | 512 | 264 − 1 | 32 | 80 | +,and,or,xor,rotl | 存在263的攻擊 |
SHA-256/224 | 256/224 | 256 | 512 | 264 − 1 | 32 | 64 | +,and,or,xor,shr,rotr | 尚未出現 |
SHA-512/384 | 512/384 | 512 | 1024 | 2128 − 1 | 64 | 80 | +,and,or,xor,shr,rotr | 尚未出現 |
HMAC
HMAC(Hash Message Authentication Code),散列消息鑒別碼,基于密鑰的Hash算法的認證協議。消息鑒別碼實現鑒別的原理是,用公開函數和密鑰產生一個固定長度的值作為認證標識,用這個標識鑒別消息的完整性。使用一個密鑰生成一個固定大小的小數據塊,即MAC,并將其加入到消息中,然后傳輸。接收方利用與發送方共享的密鑰進行鑒別認證等。
Java示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
package com.zzj.encryption; import java.security.MessageDigest; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; /** * 單向加密(非可逆加密) * @author lenovo * */ public class OneWayEncryption { static final String ALGORITHM_MD5 = "MD5" ; static final String ALGORITHM_SHA = "SHA" ; /** * MAC算法可選以下多種算法 * <pre> * HmacMD5 * HmacSHA1 * HmacSHA256 * HmacSHA384 * HmacSHA512 * </pre> */ static final String ALGORITHM_MAC = "HmacMD5" ; /** 密鑰 **/ static final String MAC_KEY = "abcdef" ; public static void main(String[] args) throws Exception { String source = "我是程序猿!我很驕傲!" ; // MD5加密 printBase64(encryptionMD5(source)); // SHA加密 printBase64(encryptionSHA(source)); // HMAC加密 printBase64(encryptionHMAC(source)); } static void printBase64( byte [] out) throws Exception { System.out.println(encodeBase64(out)); } /** * MD5加密 * @param source * @return * @throws Exception */ static byte [] encryptionMD5(String source) throws Exception { MessageDigest md = MessageDigest.getInstance(ALGORITHM_MD5); md.update(source.getBytes( "UTF-8" )); return md.digest(); } /** * SHA加密 * @param source * @return * @throws Exception */ static byte [] encryptionSHA(String source) throws Exception { MessageDigest md = MessageDigest.getInstance(ALGORITHM_SHA); md.update(source.getBytes( "UTF-8" )); return md.digest(); } /** * HMAC加密 * @return * @throws Exception */ static byte [] encryptionHMAC(String source) throws Exception { SecretKey secretKey = new SecretKeySpec(MAC_KEY.getBytes( "UTF-8" ), ALGORITHM_MAC); Mac mac = Mac.getInstance(ALGORITHM_MAC); mac.init(secretKey); mac.update(source.getBytes( "UTF-8" )); return mac.doFinal(); } /** * base64編碼 * @param source * @return * @throws Exception */ static String encodeBase64( byte [] source) throws Exception{ return new String(Base64.encodeBase64(source), "UTF-8" ); } } |
結果:
1
2
3
|
1cNbZhnhFsFV3BFPLA71wA== kl5KI61Xq44E/SzSPa2sUntMAEc= JF2v/u9td5l8yGAImNvTZw== |
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
原文鏈接:http://blog.csdn.net/zhangzeyuaaa/article/details/49982289