消息摘要、数字摘要的基本使用

207 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

消息摘要

消息摘要(Message Digest)又称为数字摘要(Digital Digest)

消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,可以被解密逆向的只有CRC32算法,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。

特点:

无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。

只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出

消息摘要是单向、不可逆的

常见消息摘要算法 :

MD5
SHA1
SHA256
SHA512

消息摘要的使用

MessageDigest类为应用程序提供消息摘要算法的功能,如SHA-1或SHA-256。 消息摘要是采用任意大小的数据并输出固定长度散列值的安全单向散列函数。

public static void main(String[] args) throws Exception {
        // 原文
        String input = "Hello World";

        System.out.println("--------------MD5---------------");
        String md5 = getDigest(input, "MD5");
        System.out.println(md5);

        System.out.println("--------------SHA-1---------------");
        String sha1 = getDigest(input, "SHA-1");
        System.out.println(sha1);

        System.out.println("--------------SHA-256---------------");
        String sha256 = getDigest(input, "SHA-256");
        System.out.println(sha256);

        System.out.println("--------------SHA-512---------------");
        String sha512 = getDigest(input, "SHA-512");
        System.out.println(sha512);
    }
    
	 /**
     * 消息数字摘要16进制数据
     */
    private static String getDigest(String input, String algorithm) throws Exception {
        // 获取数字摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 消息数字摘要
        byte[] digest = messageDigest.digest(input.getBytes());
        System.out.println("密文的字节长度:" + digest.length);
        return toHex(digest);
    }
    
	 /**
     * 消息数字摘要转16进制数据
     * @param digest 消息数字摘要字节数组
     */
    private static String toHex(byte[] digest) {
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            // 转成16进制
            String s = Integer.toHexString(b & 0xff);
            if (s.length() == 1) {
                // 如果生成的字符只有一个,,前面不够的用0补齐
                s = "0" + s;
            }
            sb.append(s);
        }
        System.out.println("16进制数据的长度:" + sb.toString().getBytes().length);
        return sb.toString();
    }
--------------MD5---------------
密文的字节长度:16
16进制数据的长度:32
b10a8db164e0754105b7a99be72e3fe5
--------------SHA-1---------------
密文的字节长度:20
16进制数据的长度:40
0a4d55a8d778e5022fab701977c5d840bbc486d0
--------------SHA-256---------------
密文的字节长度:32
16进制数据的长度:64
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
--------------SHA-512---------------
密文的字节长度:64
16进制数据的长度:128
2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b

获取文件消息摘要

sha1通常用来实现秒传功能

public static void main(String[] args) throws Exception {
        System.out.println("--------------SHA-1---------------");
        String sha1 = getDigestFile("Test.zip", "SHA-1");
        System.out.println(sha1);

        System.out.println("--------------SHA-512---------------");
        String sha512 = getDigestFile("Test.zip", "SHA-512");
        System.out.println(sha512);
    }

    private static String getDigestFile(String filePath, String algorithm) throws Exception {
        FileInputStream fis = new FileInputStream(filePath);
        int len;
        byte[] buffer = new byte[1024 * 5];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        while ((len = fis.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, len);
        }
        // 获取消息摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 获取消息摘要
        byte[] digest = messageDigest.digest(byteArrayOutputStream.toByteArray());
        System.out.println("密文的字节长度:" + digest.length);
        return toHex(digest);
    }


    /**
     * 消息摘要转16进制
     *
     * @param digest
     * @return
     */
    private static String toHex(byte[] digest) {
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            // 转成16进制
            String s = Integer.toHexString(b & 0xff);
            // 保持数据的完整性,前面不够的用0补齐
            if (s.length() == 1) {
                s = "0" + s;
            }
            sb.append(s);
        }
        System.out.println("16进制数据的长度:" + sb.toString().getBytes().length);
        return sb.toString();
    }
--------------SHA-1---------------
密文的字节长度:20
16进制数据的长度:40
826bc492c9f0749e79e877902d3c1f3bf0097c5c
--------------SHA-512---------------
密文的字节长度:64
16进制数据的长度:128
e33748b7f7e80f90666772300fd918936822d154eb7d88b3ca9750cec555a944fd78e367d40be7de2478b53850635f6e2d823886257e1ee41f3f514e3498f403