从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • JavaSE

    • 我的Java学习路线
    • 安装Java
    • Java数据类型

    • Java多版本配置
    • 面向对象

    • Java核心类

    • IO

    • Java与时间

    • 异常处理

    • 哈希和加密算法

      • 什么是哈希算法
      • 第三方库的哈希算法
      • MAC算法
        • Hash算法的缺点
        • MAC算法
        • *MAC算法的种类*
        • HMAC算法
        • 恢复SecretKey
      • 加密算法介绍
      • 对称加密算法
      • 口令加密算法
      • 非对称加密算法介绍
      • RSA算法原理(一):数学知识
      • RSA算法原理(二):概述
      • RSA算法原理(三):补充知识
      • Java中的RSA算法
      • DH算法
      • 数字签名
      • SSL和TLS协议介绍
    • Java8新特性

    • 网络编程

    • Java
  • JavaSenior

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java并发

  • Java源码

  • JVM

  • 韩顺平

  • Java
  • Java
  • JavaSE
  • 哈希和加密算法
2023-03-20
目录

MAC算法

# 10.MAC算法

MAC算法,可以理解为是一种带密钥的Hash算法   ‍

# Hash算法的缺点

考虑以下场景:

  • 我们需要发送一段消息,先通过Hash算法计算出Hash值(也叫摘要值),然后一起发送给接收方;
  • 接收方收到消息后,对消息进行计算,也得到一个哈希值,然后两个摘要值比较,如果一样,则说明数据是对的。

​Hash算法​

‍

‍

乍一看,好像上述的示例是没什么问题的,但是一旦遇到“中间人攻击”:

​中间人攻击​

直接将你消息和摘要都改了,你是无法知道数据在传输过程被篡改了。

‍

一句话:Hash算法只可以验证数据的完整性,在传输过程中数据没有被别人篡改过部分内容,或者因网络问题丢失部分数据;但是无法保证传输过程中,整体的数据有没有篡改。

‍

# MAC算法

MAC算法,全称Message Authentication Codes,也是一种消息摘要算法,也叫消息认证码算法。这种算法的核心是基于秘钥的散列函数。可以简单这样理解,MAC算法是MD5算法和SHA算法的升级版,是在这两种算法的基础上,又加入了秘钥的概念,所以会更加安全。

密钥就好比是我们之前讲的盐,然后通过哈希算法,对密钥+消息 计算出摘要值

严格来说,MAC有很多实现方式,比较常见的是基于哈希算法的MAC。

​

使用MAC算法后,数据校验的过程:

MAC算法​

发送方根据消息和密钥,生成MAC值;然后发送消息和MAC值。

接收方收到消息和MAC值,也根据消息和密钥算出MAC值,然后比较。

如果中间有人修改消息,那么计算出来的MAC值是不同的,因此保护了消息的完整性和真实性(没有被人篡改过)

MAC 密钥通常是共享的秘密密钥,只有消息的发送方和接收方知道。保护MAC key的安全性非常重要,一旦泄露,攻击者可以使用它来伪造或篡改消息,从而破坏消息的完整性和可信性。

至于MAC密钥怎么传输,我们暂且不表,先知道MAC算法是什么。

‍

‍

‍

# MAC算法的种类

MAC算法是含有密钥的散列算法的总称,就好比哈希算法分为MD系列和SHA系列等。MAC算法也是依赖具体某个哈希算法的,并在其基础上添加了密钥支持,因此也被称为HMAC算法,可以划分为:

  • MD分支:Hmac-MD2、Hmac-MD4、Hmac-MD5。
  • SHA分支:Hmac-SHA1、Hmac-SHA256、Hmac-SHA512、Hmac-SHA224等

MAC算法应用于很多场景,如Linux客户端的SecureCRT,Google身份验证器、银联pos机终端等,都可以看到MAC算法的影子,现在已经成为事实上的Internet安全标准。

‍

‍

# HMAC算法

Hmac,全称Hash-based Message Authentication Code,是一种更安全的消息摘要算法。

HmacMD5可以看作带有一个安全的key(盐)的MD5。使用HmacMD5而不是用MD5加salt,有如下好处:

  • HmacMD5使用的key长度是64字节,更安全;
  • Hmac是标准算法,同样适用于SHA-1等其他哈希算法;
  • Hmac输出和原有的哈希算法长度一致。

可见,Hmac本质上就是把key混入摘要的算法。验证此哈希时,除了原始的输入数据,还要提供key。

‍

为了保证安全,我们不会自己指定key,而是通过Java标准库的KeyGenerator生成一个安全的随机的key。下面是使用HmacMD5的代码:

package chapter12Hash;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import java.math.BigInteger;

public class Hash5HMAC {
    public static void main(String[] args) throws Exception{
        KeyGenerator keygen = KeyGenerator.getInstance("HmacMD5");
        SecretKey key = keygen.generateKey();   //随机生成一个key
        Mac mac = Mac.getInstance("HmacMD5");
        mac.init(key);
        mac.update("HelloWorld".getBytes("UTF-8"));
        byte[] result = mac.doFinal();
        System.out.println(new BigInteger(1, result).toString(16));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

‍

和MD5相比,使用HmacMD5的步骤是:

  1. 通过名称HmacMD5​获取KeyGenerator​实例;
  2. 通过KeyGenerator​创建一个SecretKey​实例;
  3. 通过名称HmacMD5​获取Mac​实例;
  4. 用SecretKey​初始化Mac​实例;
  5. 对Mac​实例反复调用update(byte[])​输入数据;
  6. 调用Mac​实例的doFinal()​获取最终的哈希值。

我们可以用Hmac算法取代原有的自定义的加盐算法,然后就可以用来存储密码了,此时表结构类似:

username secret_key (64 bytes) password
bob a8c06e05f92e...5e16 7e0387872a57c85ef6dddbaa12f376de
alice e6a343693985...f4be c1f929ac2552642b302e739bc0cdbaac
tim f27a973dfdc0...6003 af57651c3a8a73303515804d4af43790

‍

# 恢复SecretKey

除了从KeyGenerator​生成SecretKey​之外,我们还可以从一个​byte[]​数组恢复​SecretKey​:

package chapter12Hash;


import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
public class HashDemo6SecretKeySpec  {
    public static void main(String[] args) throws Exception{
        byte[] hkey = new byte[] { 106, 70, -110, 125, 39, -20, 52, 56, 85, 9, -19, -72, 52, -53, 52, -45, -6, 119, -63,
                30, 20, -83, -28, 77, 98, 109, -32, -76, 121, -106, 0, -74, -107, -114, -45, 104, -104, -8, 2, 121, 6,
                97, -18, -13, -63, -30, -125, -103, -80, -46, 113, -14, 68, 32, -46, 101, -116, -104, -81, -108, 122,
                89, -106, -109 };

        SecretKey key = new SecretKeySpec(hkey, "HmacMD5");
        Mac mac = Mac.getInstance("HmacMD5");
        mac.init(key);
        mac.update("HelloWorld".getBytes("UTF-8"));
        byte[] result = mac.doFinal();
        System.out.println(Arrays.toString(result));
        //[126, 59, 37, 63, 73, 90, 111, -96, -77, 15, 82, -74, 122, -55, -67, 54]
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

恢复SecretKey​的语句就是new SecretKeySpec(hkey, "HmacMD5")​。

在GitHub上编辑此页 (opens new window)
上次更新: 2023/3/22 11:24:45
第三方库的哈希算法
加密算法介绍

← 第三方库的哈希算法 加密算法介绍→

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式