zoukankan      html  css  js  c++  java
  • Algorithm:Java加密解密之MAC(消息认证码)

    MD5 消息摘要(数字摘要)

    它是把一个文本/文件 通过摘要函数(hash函数)计算出一个结果。然后把文本/文件和摘要结果一同发给接受者
    接受者接收到文件之后,也进行摘要,把两个摘要结果进行对比。如果一致就说明文本/文件和摘要是一致的。
    问题

    假设A把文件和摘要发给B,中途被C截获了。C把文件改了,同时把改后的文件进行摘要。然后把改后的文件和重新生成的摘要发给B。

    B收到结果之后,进行摘要,对比发现,是一致的。但是此时文件是被篡改过的,B也不知道。接收方并不能察觉到数据被篡改。

    所以说,普通的消息摘要不能验证身份和防篡改!!

    解决这个问题,我们可以使用MAC(消息认证码(带密钥的hash函数))去解决。

    MAC (全称 Message Authentication Code),消息认证码(带密钥的Hash函数)

    通信实体双方使用的一种验证机制,保证消息数据完整性的一种工具,在发送数据之前,发送方首先使用通信双方协商好的散列函数计算其摘要值。在双方共享的会话密钥作用下,由摘要值获得消息验证码。

    之后,它和数据一起被发送。接收方收到报文后,首先利用会话密钥还原摘要值,同时利用散列函数在本地计算所收到数据的摘要值,并将这两个数据进行比对。若两者相等,则报文通过认证。

    计算摘要的时候,需要一个秘钥key,没有秘钥key就无法计算。

    注意:相同的消息,不同的key,摘要结果不同。

    java1.8代码演示

    下面使用Java(1.8.0_144)演示计算apache-tomcat-8.5.23.zip文件的消息摘要

    package com.security.dgst;
     
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.security.Key;
     
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
     
    import org.apache.commons.codec.binary.Hex;
     
    public class MacTest {
     
        //秘钥(必须要是通信双方共享的)
        static final String STR_KEY = "266f5fe18e714688a083df4ca9f78064";
        
        /**
         * 其中,Mac.getInstance支持的算法有:HmacMD5、HmacSHA1、HmacSHA256等等
         * 全部支持的算法见官方文档:
         * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac
         */
        public static byte[] mac(String algorithm, Key key, byte[] data) throws Exception {
            Mac mac = Mac.getInstance(algorithm);
            //这里是关键,需要一个key(这里就是和普通的消息摘要的区别点)
            mac.init(key);
            
            byte[] result = mac.doFinal(data);
            return result;
        }
        
        public static void main(String[] args) throws Exception {
            byte[] data = Files.readAllBytes(Paths.get("c:/tmp/apache-tomcat-8.5.23.zip"));
            
            Key key = new SecretKeySpec(STR_KEY.getBytes(), "");
            
            //使用MD5算法计算摘要
            byte[] md5Digest = mac("HmacMD5", key, data);
            
            //使用SHA256算法计算摘要
            byte[] shaDigest = mac("HmacSHA256", key, data);
            
            //把摘要后的结果转换成十六进制的字符串(也可以使用Base64进行编码)
            System.out.println(Hex.encodeHexString(md5Digest));
            System.out.println(Hex.encodeHexString(shaDigest));
        }
    }

    Mac.getInstance(algorithm)  参数algorithm可以支持的值除了参考官方文档,还可以通过如下代码得出:

    Security.getAlgorithms("Mac").forEach(System.out::println);

    Java8中,输出结果如下:
    PBEWITHHMACSHA512 PBEWITHHMACSHA224 PBEWITHHMACSHA256 HMACSHA384 PBEWITHHMACSHA384 HMACSHA256 HMACPBESHA1 HMACSHA224 HMACMD5 PBEWITHHMACSHA1 SSLMACSHA1 HMACSHA512 SSLMACMD5 HMACSHA1

    输出结果为:

    ce078fe3134fa8b50c595e4e984f88e0
    d90eec24b04b81cd235ff8d4e5a9aeb00183e253e44b6ed763328ff97f856200

    我们可以使用OpenSSL,加上上面使用的秘钥key,计算摘要。

    对比结果,发现是一致的。

    文章转载至:https://blog.csdn.net/mn960mn/article/details/78174234

    ----------------------------------- 作者:怒吼的萝卜 链接:http://www.cnblogs.com/nhdlb/ -----------------------------------
  • 相关阅读:
    java 运算符的优先级比较
    Java String类和StringBuffer类的区别
    Java 并发编程
    java构造函数和初始化
    Java 动态绑定
    Java day3
    Java day2
    Java day1
    计算机系统原理之程序是怎么运行的 【转】
    MemberCached 学习上【转】
  • 原文地址:https://www.cnblogs.com/nhdlb/p/14291925.html
Copyright © 2011-2022 走看看