当前位置:K88软件开发文章中心编程语言JavaJava01 → 文章内容

消息摘要MD/SHA/HMAC的使用方法

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-4 7:55:06

-->

[t]消息摘要的概念:[/t]

唯一对应一个消息或文本的固定长度的值,由一个单向Hash加密函数对消息进行作用而产生。

消息摘要的分类:

(1)MD(Message Digest):消息摘要算法

(2)SHA(Secure Hash Algorithm):安全散列算法

(3)MAC(Message Authentication Code):消息认证码算法

应用:

验证数据完整性(防止在传输途中被篡改)

[t]MD 算法的编程使用[/t]

MD 算法的基本概念

为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护

2. MD 算法的种类

MD 系列算法(JDK)

算法数据长度摘要长度
MD2任意128
MD5任意128

MD 算法编程使用:

1
2
3
4
5
6
// 初始化 MessageDigest
MessageDigest md5 = MessageDigest.getInstance("MD5");
// 更新
md5.update(data);
// 生成摘要
byte[] result= md5.digest();

[t]SHA 算法的编程使用[/t]

1. SHA 算法的基本概念

安全哈希算法,主要适用于数字签名标准里面定义的数字签名算法

2. SHA 算法的种类

SHA 系列算法(JDK)

算法数据长度摘要长度
SHA-1任意160
SHA-256256
SHA-384384
SHA-512512

SHA 系列算法编程使用:

/

1
2
3
4
5
6
/ 初始化MessageDigest
MessageDigest sha = MessageDigest.getInstance("SHA");
// 更新
sha.update(data);
// 生成摘要
byte[] result= sha.digest();

[t]HMAC 算法的编程使用[/t]

引言:单一MD或SHA算法缺点?

摘要值容易被篡改!

HMAC 算法的基本概念

结合了MD5和SHA算法的优势,同时用密钥对摘要加密,是一种更为安全的消息摘要算法。

HMAC 算法的种类

HMAC 系列算法(JDK)

算法数据长度摘要长度
?HmacMD5任意128
?HmacSHA1160
HmacSHA256256
HmacSHA384384
HmacSHA512512

如何生成密钥

2. 构建密钥

1
2
3
4
5
6
// 初始化 KeyGenerator
KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
// 产生密钥
SecretKey secretKey = keyGen.generateKey();
// 得到密钥字节数组
byte[] key = secretKey.getEncoded();

3. 执行消息摘要

1
2
3
4
5
6
7
8
// 从字节数组还原密钥
SecretKey secretKey = new SecretKeySpec(key, "HmacMD5");
// 实例化 Mac
Mac mac = Mac.getInstance("HmacMD5");
// 用密钥初始化 Mac
mac.init(secretKey);
// 执行消息摘要
byte[] result = mac.doFinal(data);

总结:

1. 散列函数特征:

(1)输入任意长度数据,输出固定长度散列值,计算很容易,过程不可逆

(2)对于某数据,其散列值固定

(3)两个数据不同,则对应的散列值也不同

(4)两个散列值不同,则对应的原始输入数据也不同

java代码实现

MessageDigestUtil.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
package cn.k88;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.DigestInputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;


public class MessageDigestUtil {
   
    public static String encryptMD5(byte[] data) throws NoSuchAlgorithmException{
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        md5.update(data);
        byte[] resultBytes = md5.digest();
       
        String resultString = BytesToHex.fromBytesToHex(resultBytes);
        return resultString;
    }
   
    public static String getMD5OfFile(String path) throws Exception{
        FileInputStream fis = new FileInputStream(new File(path));
        DigestInputStream dis = new DigestInputStream(fis, MessageDigest.getInstance("MD5"));
        // 流输入
        byte[] buffer = new byte[1024];
        int read = dis.read(buffer, 0, 1024);
        while (read != -1){
            read = dis.read(buffer, 0, 1024);
        }
       
        MessageDigest md = dis.getMessageDigest();
        byte[] resultBytes = md.digest();
        String resultString = BytesToHex.fromBytesToHex(resultBytes);
        return resultString;
    }
   
    public static String encryptSHA(byte[] data) throws NoSuchAlgorithmException{
        MessageDigest sha = MessageDigest.getInstance("SHA-512");
        sha.update(data);
        byte[] resultBytes = sha.digest();
       
        String resultString = BytesToHex.fromBytesToHex(resultBytes);
        return resultString;
    }
   
    public static byte[] initHmacKey() throws Exception{
        KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA512");
        SecretKey secretKey = keyGen.generateKey();
        return secretKey.getEncoded();
    }
   
    public static String encryptHmac(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException{
        SecretKey secretKey = new SecretKeySpec(key, "HmacSHA512");
        Mac mac = Mac.getInstance("HmacSHA512");
        mac.init(secretKey);
        byte[] resultBytes = mac.doFinal(data);
       
        String resultString = BytesToHex.fromBytesToHex(resultBytes);
        return resultString;
    }
   
}

Main.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
import java.io.IOException;
package cn.k88;

public class Main {

    //待加密的明文
    public static final String DATA = "www.k88.net";
    public static final String PATH = "mysql-installer-web-community-5.6.22.0.msi";
   
   
    public static void main(String[] args) throws Exception {
       
        /* Test MD5 */
        String md5Result = MessageDigestUtil.encryptMD5(DATA.getBytes());
        System.out.println(DATA + ">>>MD5>>>" + md5Result);
       
        /* Test MD5 of File */
        String fileMD5Result = MessageDigestUtil.getMD5OfFile(PATH);
        System.out.println("File MD5 : " + fileMD5Result);
       
        /* Test SHA */
        String shaResult = MessageDigestUtil.encryptSHA(DATA.getBytes());
        System.out.println(DATA + ">>>SHA>>>" + shaResult);
       
        /* Test HMAC */
        byte[] hmacKey = MessageDigestUtil.initHmacKey();
        System.out.println("HMAC KEY: " + BytesToHex.fromBytesToHex(hmacKey));
        String hmacResult = MessageDigestUtil.encryptHmac(DATA.getBytes(), hmacKey);
        System.out.println(DATA + ">>>HMAC>>>" + hmacResult);  
       
    }

}

消息摘要MD/SHA/HMAC的使用方法