从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • JavaSE

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

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

    • Java 核心类

    • IO

    • Java 与时间

    • 异常处理

    • 哈希和加密算法

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

    • 网络编程

  • JavaSenior

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

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

MAC 算法

# 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")。

上次更新: 2025/6/3 09:31:54
第三方库的哈希算法
加密算法介绍

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

最近更新
01
学点统计学:轻松识破一本正经的胡说八道
06-05
02
2025 年 5 月记
05-31
03
《贫穷的本质》很棒,但可能不适合你
05-27
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式