加密与安全_深入了解Hmac算法(消息认证码)

news2024/11/16 10:17:04

文章目录

  • Pre
  • HMAC概述
  • 常见的Hmac算法
  • Code
    • 随机的key的生成 KeyGenerator
    • HmacMD5
      • 用Hmac算法取代原有的自定义的加盐算法
    • HmacMD5 VS MD5
    • HmacSHA256

在这里插入图片描述


Pre

加密与安全_深入了解哈希算法中我们提到,

存储用户的哈希口令时,要加盐存储,目的就在于抵御彩虹表攻击。

digest = hash(input)

正是因为相同的输入会产生相同的输出,我们加盐的目的就在于,使得输入有所变化:

digest = hash(salt + input)

这个salt可以看作是一个额外的“认证码”,同样的输入,不同的认证码,会产生不同的输出。因此,要验证输出的哈希,必须同时提供“认证码”。

Hmac算法就是一种基于密钥的消息认证码算法,它的全称是Hash-based Message Authentication Code,是一种更安全的消息摘要算法

Hmac算法总是和某种哈希算法配合起来用的。例如,我们使用MD5算法,对应的就是HmacMD5算法,它相当于“加盐”的MD5:

HmacMD5md5(secure_random_key, input)

HMAC概述

HMAC(Hash-based Message Authentication Code)算法是一种基于哈希函数的消息认证码算法,用于验证消息的完整性和认证消息的发送者。它结合了哈希函数和密钥,通过将密钥与消息进行哈希运算来生成消息认证码。

HMAC的计算过程如下:

  1. 首先,选择一个适当的哈希函数(如MD5、SHA-1、SHA-256等)和一个密钥。
  2. 将密钥进行适当的填充和处理,以满足哈希函数的输入长度要求。
  3. 将消息与填充后的密钥按照特定的方式进行组合。
  4. 对组合后的数据进行哈希运算。
  5. 将哈希结果作为消息认证码输出。

接收方在接收到消息后,也会使用相同的密钥和哈希函数来计算消息的HMAC值,并与发送方发送的HMAC值进行比较。如果两者一致,则消息完整且来自合法发送者;否则,可能存在消息被篡改或来自未经授权的发送者的风险。


通俗地讲,HMAC算法就像是一种“密码验证器”,它确保数据在传输过程中不被篡改。

想象你要给朋友寄一封信,但你担心信被别人篡改了。你可以用HMAC来解决这个问题。首先,你会在信封上写下你的签名。但这次不是用笔签名,而是用一种特殊的技巧来生成一个“密钥”。这个密钥就像是你的个人密码,只有你和你的朋友知道。

然后,你把这个签名和信一起寄出去。你的朋友收到信后,也知道这个密钥。他会用同样的方法再次生成签名,然后比对你寄来的签名。如果两个签名一样,说明信没有被篡改,因为只有你和你的朋友知道这个特殊的“密码”。

所以,HMAC就是通过一种双重的“密码”验证机制,确保数据的完整性和安全性。HMAC算法具有较强的安全性和广泛的应用,常用于网络通信、数据传输、数字签名等领域,以确保数据的完整性和安全性。


常见的Hmac算法

HMAC(Hash-based Message Authentication Code)算法可以与许多哈希函数结合使用,常用的哈希函数包括:

  1. HMAC-MD5:使用MD5哈希函数生成HMAC。
  2. HMAC-SHA1:使用SHA-1哈希函数生成HMAC。
  3. HMAC-SHA256:使用SHA-256哈希函数生成HMAC。
  4. HMAC-SHA512:使用SHA-512哈希函数生成HMAC。

这些算法提供了不同的哈希函数选项,可以根据安全性需求和性能考虑选择适合的算法。通常情况下,较新的SHA-256和SHA-512算法被认为比MD5和SHA-1更安全,因此在安全要求较高的场景中更常用。


Code

随机的key的生成 KeyGenerator

通过使用Java标准库中的KeyGenerator生成安全的随机密钥,可以确保密钥的随机性和安全性,从而增强了加密算法的安全性。

KeyGenerator类提供了生成对称密钥的功能,可以根据指定的算法和安全随机数生成器来生成密钥。通常情况下,可以使用

  • KeyGenerator.getInstance(String algorithm)方法来获取KeyGenerator实例,
  • 然后使用KeyGenerator.init(int keysize)方法指定密钥的长度,
  • 最后通过KeyGenerator.generateKey()方法生成密钥。

这样生成的密钥通常会具有足够的长度和随机性,能够抵御常见的密码攻击,如穷举搜索和字典攻击。因此,使用Java标准库中的KeyGenerator生成安全的随机密钥是一种推荐的做法,有助于提高系统的安全性。

HmacMD5

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

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

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

package com.artisan.securityalgjava.hmac;

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

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class HmacTest {

    public static void main(String[] args)  throws  Exception{
        // 创建 KeyGenerator 实例并指定算法为 HmacMD5
        KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");

        // 生成随机密钥
        SecretKey key = keyGen.generateKey();

        // 打印随机生成的密钥
        byte[] skey = key.getEncoded();
        System.out.println("随机生成的密钥:" + new BigInteger(1, skey).toString(16));

        // 创建 Mac 实例并指定算法为 HmacMD5
        Mac mac = Mac.getInstance("HmacMD5");

        // 初始化 Mac 实例
        mac.init(key);

        // 更新消息
        mac.update("HellArtisan".getBytes("UTF-8"));

        // 计算 HMAC 值
        byte[] result = mac.doFinal();

        // 打印 HMAC 值
        System.out.println("HMAC 值:" + new BigInteger(1, result).toString(16));
    }
}
    

使用Java标准库生成HmacMD5算法的随机密钥,并计算给定消息(“HellArtisan”)的HMAC值。


用Hmac算法取代原有的自定义的加盐算法

我们可以用Hmac算法取代原有的自定义的加盐算法,因此,存储用户名和口令的数据库结构如下:

| username | secret_key                        | password                              |
|----------|----------------------------------|---------------------------------------|
| bob      | a8c06e05f92e...5e16              | 7e0387872a57c85ef6dddbaa12f376de      |
| alice    | e6a343693985...f4be              | c1f929ac2552642b302e739bc0cdbaac      |
| tim      | f27a973dfdc0...6003              | af57651c3a8a73303515804d4af43790      |

每行包含用户名(username)、随机生成的密钥(secret_key,长度为64字节),以及使用Hmac算法生成的密码哈希值(password)。密钥用于计算Hmac,确保密码的安全性。

package com.artisan.securityalgjava.hmac;

import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;

/**
 * HMAC示例:使用预先生成的密钥计算HMAC值
 * @author artisan
 */
public class HmacVerifyTest {

    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对象
        SecretKey key = new SecretKeySpec(hkey, "HmacMD5");

        // 获取Mac实例并指定算法为HmacMD5
        Mac mac = Mac.getInstance("HmacMD5");

        // 使用密钥初始化Mac实例
        mac.init(key);

        // 更新消息
        mac.update("HelloArtisan".getBytes("UTF-8"));

        // 计算HMAC值
        byte[] result = mac.doFinal();

        // 打印HMAC值
        System.out.println(Arrays.toString(result));
        // [-22, 82, 110, 65, -70, -122, 93, 121, 48, 96, -40, -78, 126, 46, -47, 112]
    }
}

// 创建SecretKey对象,使用预先生成的密钥字节数组和算法名称"HmacMD5"
SecretKey key = new SecretKeySpec(hkey, "HmacMD5");

这行代码的作用是创建一个SecretKey对象,使用预先生成的密钥字节数组(hkey)作为密钥,同时指定算法名称为"HmacMD5"。

这就是恢复SecretKey的代码。


HmacMD5 VS MD5

相比于直接使用MD5哈希算法,使用HmacMD5算法需要经过一些额外的步骤来生成哈希值。

下面是使用HmacMD5算法生成哈希值的步骤:

  1. 通过名称"HmacMD5"获取KeyGenerator实例。
  2. 通过KeyGenerator创建一个SecretKey实例,这个密钥将用于初始化Mac实例。
  3. 通过名称"HmacMD5"获取Mac实例。
  4. SecretKey初始化Mac实例,以指定使用的密钥。
  5. Mac实例反复调用update(byte[])输入数据,可以多次调用update方法以输入数据的不同部分。
  6. 调用Mac实例的doFinal()方法获取最终的哈希值。

这些步骤确保了使用HmacMD5算法生成哈希值时的安全性和正确性。 HmacMD5算法结合了MD5哈希算法和密钥,提供了更高的安全性和防御性,适用于需要对消息进行完整性验证和身份认证的场景。


HmacSHA256

https://github.com/aperezdc/hmac-sha256/blob/master/hmac-sha256.c

 package com.artisan.securityalgjava.hmac;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */


public class HmacSHA256Example {
    public static void main(String[] args) {
        // 要加密的消息
        String message = "Hello, HMAC!";
        // 密钥
        String key = "secretKey";

        try {
            // 计算HMAC-SHA256值
            byte[] result = calculateHmacSHA256(message, key);
            // 将字节数组转换成十六进制字符串
            String hmacSHA256 = bytesToHex(result);
            // 打印HMAC-SHA256值
            System.out.println("HMAC-SHA256: " + hmacSHA256);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 计算HMAC-SHA256值
     * @param message
     * @param key
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public static byte[] calculateHmacSHA256(String message, String key)
            throws NoSuchAlgorithmException, InvalidKeyException {
        // 创建HmacSHA256实例
        Mac hmacSHA256 = Mac.getInstance("HmacSHA256");
        // 创建密钥对象
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
        // 使用密钥初始化Mac实例
        hmacSHA256.init(secretKey);
        // 计算消息的HMAC-SHA256值并返回
        return hmacSHA256.doFinal(message.getBytes());
    }

    /**
     * 将字节数组转换成十六进制字符串
     * @param bytes
     * @return
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }
}

首先定义了要加密的消息和密钥。然后,使用calculateHmacSHA256方法计算消息的HMAC-SHA256值。最后,将计算得到的字节数组转换成十六进制字符串,并打印输出。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1482638.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Zabbix 系统告警“More than 75% used in the configuration cache”处理办法

Zabbix系统报错提示 Zabbix 系统告警“More than 75% used in the configuration cache”,看了一下意思是可用的配置缓存超过75%。 修改缓存大小 vim /etc/zabbix/zabbix_server.confesc : /CacheSize 找到配置 将64M改大一点,保存退出。 重启zabbix…

14.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-数据包分析工具界面与通信设计

内容参考于: 易道云信息技术研究院VIP课 上一个内容:13.如果没有工具就创造工具 码云地址(master 分支):https://gitee.com/dye_your_fingers/titan 码云版本号:fef5089bd11dfb86ae8b4e26f25cf59e85f896…

练习 3 Web [ACTF2020 新生赛]Upload

[ACTF2020 新生赛]Upload1 中间有上传文件的地方,试一下一句话木马 txt 不让传txt 另存为tlyjpg,木马文件上传成功 给出了存放目录: Upload Success! Look here~ ./uplo4d/06a9d80f64fded1e542a95e6d530c70a.jpg 下一步尝试改木马文件后缀…

Qt应用软件【测试篇】vargrid内存检查工具

文章目录 vargrid介绍vargrid官网vargrid安装常用命令Valgrind的主要命令vargrid介绍 Valgrind是一个用于构建动态分析工具的框架,能自动检测许多内存管理和线程错误,并详细分析程序性能。Valgrind发行版包括七个成熟工具:内存错误检测器、两个线程错误检测器、缓存和分支预…

autoware.universe中跟踪模块详解,一看就懂!

目录 问题:阅读关键点:总结问题: 根据对预测模块代码的分析,发现预测框出现在点云前方的原因在于跟踪框出现在点云前方 对rviz上的目标进行观察后发现 车辆的检测框先出来一段时间后,跟踪框和预测框同步一块出来 跟踪框总是超出点云一部分 阅读关键点: 每个跟踪器最少要统计…

【JSON2WEB】07 Amis可视化设计器CRUD增删改查

总算到重点中的核心内容,CRUD也就是增删改查,一个设计科学合理的管理信息系统,95%的就是CRUD,达不到这个比例要重新考虑一下你的数据库设计了。 1 新增页面 Step 1 启动amis-editor Setp 2 新增页面 名称和路径随便命名&#xf…

网络安全、信息安全、计算机安全,有何区别?

这三个概念都存在,一般人可能会混为一谈。 究竟它们之间是什么关系?并列?交叉? 可能从广义上来说它们都可以用来表示安全security这样一个笼统的概念。 但如果从狭义上理解,它们应该是有区别的,区别在哪呢&…

08、关于语法:resp?.data?.data 的含义与实际操作中可能遇到的问题

1、数据情况: 其一、从后端拿到的数据为: let resp.data {"data": [],"lag_mode": 3,"totol": 0 }或: let resp.data {"data": [],"totol": 0 }其二、目标数据为: // 想要…

git拉取代码提示403

错误提示信息 remote: Access denied 拒绝访问 fatal: unable to access ‘ https:/ /gitee. cohe requested URL 403解决 找到凭据管理器 找到git的信息,删掉,重新拉取代码,就会提示输入用户名密码

CentOS的yum报错except OSError, e:

报错信息 Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile base: mirrors.cloud.aliyuncs.comextras: mirrors.cloud.aliyuncs.comupdates: mirrors.cloud.aliyuncs.com File “/usr/libexec/urlgrabber-ext-down”, line 28 except OSError, e: ^…

Git源码管理

参考视频:16-git的日志以及版本管理_哔哩哔哩_bilibili 参考博客:Git && Docker 学习笔记-CSDN博客 目录 简介 个人操作初始化 初始化git目录 查看生成的git目录文件 配置git工作目录的用户信息 查看工作区的状态,生成文件的…

Nacos环境搭建 -- 服务注册与发现

为什么需要服务治理 在未引入服务治理模块之前,服务之间的通信是服务间直接发起并调用来实现的。只要知道了对应服务的服务名称、IP地址、端口号,就能够发起服务通信。比如A服务的IP地址为192.168.1.100:9000,B服务直接向该IP地址发起请求就…

Linux网络编程——网络基础

Linux网络编程——网络基础 1. 网络结构模式1.1 C/S 结构1.2 B/S 结构 2. MAC 地址3. IP地址3.1 简介3.2 IP 地址编址方式 4. 端口4.1 简介4.2 端口类型 5. 网络模型5.1 OSI 七层参考模型5.2 TCP/IP 四层模型 6. 协议6.1 简介6.2 常见协议6.3 UDP 协议6.4 TCP 协议6.5 IP 协议6…

05 OpenCV图像混合技术

文章目录 理论算子示例 理论 其中 的取值范围为0~1之间 算子 addWeighted CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2, double beta,double gamma, OutputArray dst, int dtype -1 ); 参数1:输入图像Mat …

进程操作(Win32, C++)

CProcessUtils.h #pragma once#include <wtypesbase.h> #include <tchar.h> #include <vector> #include <map> #include <string>#ifdef _UNICODE using _tstring std::wstring; #else using _tstring std::string; #endif// 进程信息 typed…

element-plus表格合并

要实现这样的表格&#xff0c; 怎么做呢&#xff1f; 甚至是这种三级的呢&#xff1f; 官网的案例也是通过这个方法进行配置的&#xff0c;也就是说表格长什么样&#xff0c;关键在怎么处理的方法上。 这是官网的方法&#xff0c;可参考拓展&#xff1a; const arraySpanMeth…

SLAM ORB-SLAM2(21)基础矩阵的计算和评分

SLAM ORB-SLAM2&#xff08;21&#xff09;基础矩阵的计算和评分 1. 前言2. 基础矩阵2.1. 对级约束2.2. 推导2.3. 计算原理 3. ComputeF214. CheckFundamental 1. 前言 在 《SLAM ORB-SLAM2&#xff08;20&#xff09;查找基础矩阵》 中了解到 查找基础矩阵主要过程&#xff1…

nginx 配置浏览器不缓存文件 每次都会从服务器 请求新的文件

目录 解决问题方法说明 测试html环境js环境第一步然后修改内容 打开带有js缓存的页面强制刷新 配置nginx 每次打开页面都会重新请求index.js 文件重启nginx再次修改index.js 总结设置为全局 解决问题 适用于实时更新数据的&#xff0c;网页 可以让用户每次都是重新请求&#x…

《从0开始搭建实现apollo9.0》系列三 CANBUS模块解读

二、CANBUS代码 1、canbus模块的软件架构如下&#xff1a; 主要输入输出 输入&#xff1a;apollo::control::ControlCommand | 控制指令 输出&#xff1a; /apollo/chassis | apollo::canbus::Chassis | 车辆底盘信息接口数据&#xff0c;包括车辆速度、方向盘转角、档位、底盘…

Vue Html中插入本地视频(Video 标签)

在 Vue 中插入本地视频可以通过使用标签来实现。你可以将视频文件放在你的项目中的合适位置&#xff08;比如assets文件夹&#xff09;&#xff0c;然后在 Vue 组件中引用这个视频文件。html同理 首先&#xff0c;在你的 Vue 项目中的assets文件夹下放入你的视频文件&#xff…