首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java加密与解密之消息摘要算法

Java加密与解密之消息摘要算法

作者头像
布禾
发布2020-11-24 12:09:42
8060
发布2020-11-24 12:09:42
举报
概述

消息摘要算法又称为散列算法,其核心在于散列函数的单向性。即通过散列函数可获得对应的散列值,但不可通过该散列值反推其原始信息。这是消息摘要算法的安全性的根本所在。消息摘要算法主要分为三大类:MD(MessageDigest,消息摘要算法)SHA(Secure HashAlgorithm,安全散列算法)MAC(MessageAuthentication Code,消息认证码算法)。MD5、SHA和HMAC分别是三大类消息摘要算法中的代表。

MD5和SHA

1.MD5算法是典型的消息摘要算法,其前身有MD2、MD3和MD4算法,它由MD4、MD3、MD2算法改进而来,1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA。

2.SHA家族的五个算法,分别是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512。SHA与MD算法不同之处主要在于摘要长度,SHA算法的摘要长度更长,安全性更高。

MD5和SHA在实现代码上大部分是一致的,只是指定的算法不一样。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MdaUtil {
	
	/**
     * MD5/SHA消息摘要
     * @param content 数据
     * @param algorithm 消息摘要算法
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String messageDigestAlgorithm(String content, String algorithm) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        byte[] result = messageDigest.digest(content.getBytes());
        StringBuilder sb = new StringBuilder();
        for(byte b : result){
            //转16进制
            String a = Integer.toHexString(b & 0xff);
            //长度为1时在最高位补0
            if(a.length() == 1){
                a = "0" + a;
            }
            sb.append(a);
        }
        return sb.toString();
    }

    public static void main(String[] args) throws NoSuchAlgorithmException {
        System.out.println(messageDigestAlgorithm("消息摘要算法", "md5"));//b7c58f860f1add7de092b1f2931a3eb9
        System.out.println(messageDigestAlgorithm("消息摘要算法", "sha"));//ff0e2136bc6df62bbe0d9b6ad9d028852312aad5
    }
}
HMAC

HMAC算法结合了MD5和SHA算法的优势,并加入密钥的支持,是一种更为安全的消息摘要算法。

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class HmacUtil {

    /**
     * 生成base64编码后的密钥
     * @param algorithm 摘要算法
     * @return
     * @throws Exception
     */
    public static String generateKey(String algorithm) throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm);
        SecretKey secretKey = keyGenerator.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * HMAC消息摘要
     * @param algorithm 摘要算法
     * @param key 密钥
     * @param data 数据
     * @return
     * @throws Exception
     */
    public static String hmac(String algorithm, String key, String data) throws Exception {
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), algorithm);
        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);
        return Base64.getEncoder().encodeToString(mac.doFinal(data.getBytes()));
    }

    public static void main(String[] args) throws Exception {
        String algorithm = "HmacMD5";
        String data = "消息摘要算法";
        String key = generateKey(algorithm);
        System.out.println("Base64编码后的密钥:" + key);
        System.out.println("Base64编码后的HMAC消息摘要:" + hmac(algorithm, key, data));
    }
}
文件完整性验证

以tomcat为例,在官网上可以看到tomcat安装包以及它对应的经过消息摘要算法处理的后的值:

下载文件,通过计算文件的消息摘要值来验证文件的完整性,如果文件是完整的则计算出来的值和官网上的值是相同的。

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;

public class FileVerificationUtil {

    /**
     * 文件消息摘要验证
     *
     * @param digestData  原摘要数据
     * @param algorithm   摘要算法
     * @param inputStream 待验证文件
     * @return
     * @throws Exception
     */
    public static boolean fileVerification(String digestData, String algorithm, InputStream inputStream) throws Exception {
        DigestInputStream digestInputStream = new DigestInputStream(inputStream, MessageDigest.getInstance(algorithm));
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        int read = digestInputStream.read(buffer, 0, bufferSize);
        while (read > -1) {
            read = digestInputStream.read(buffer, 0, bufferSize);
        }
        digestInputStream.close();
        MessageDigest messageDigest = digestInputStream.getMessageDigest();
        byte[] result = messageDigest.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : result) {
            //转16进制
            String a = Integer.toHexString(b & 0xff);
            //长度为1时在最高位补0
            if (a.length() == 1) {
                a = "0" + a;
            }
            sb.append(a);
        }
        return sb.toString().equals(digestData);
    }

    public static void main(String[] args) throws Exception {
        String digestData = "8ee33ad87e40659e501517d8ac9915ee0b19ee0fa590feb80c85f0d93c6dfe2658cdc73d2a2545ace52b7896e8a96ba6a025dda8254d6c5d9cea563c1f9e4d77";
        String algorithm = "sha-512";
        System.out.println(fileVerification(digestData, algorithm, new FileInputStream("F:\\chrome_download\\apache-tomcat-10.0.0-M9-windows-x64.zip")));//true
    }
}

参考:Java加密与解密的艺术

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • MD5和SHA
  • HMAC
  • 文件完整性验证
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档