HMAC 单向散列消息认证码

消息认证码MAC是用于确认完整性并进行认证的技术,消息认证码的输入包括任意长度的消息和一个发送者和接收者之间共享的密钥(可能还需要共享盐值)。

HMAC是使用单向散列函数来构造消息认证码的方法,任何高强度单向散列函数都可以被用于HMAC,具体方法如下图所示。

发送者需要同时把消息和认证码发送给接收者,接收者接收了两者,并根据接收到的消息和共享的密钥生成认证码进行比较。如果相同则消息未被篡改且认证成功。

MAC不能保证信息的机密性!MAC无法对第三方"C"证明,因为"A","B"两者都有密钥,都可以生成消息和MAC。因此第三方不知道是谁生成的,更不知道消息的真实性。MAC无法防止否认。

加盐

盐是通过伪随机数生成器生成的随机数,会和密钥一起被输入单向散列函数。

主要目的是为了防御字典攻击。字典攻击是一种事先进行计算并准备好候选密钥列表的方法。是一种暴力攻击破解手段。加了盐,密钥便多了n个数量级的可能,加大破解难度。

HMAC利用单向散列函数的单向性和抗碰撞性来保证无法根据MAC值推测出密钥。

代码

package main

import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"fmt"
"hash"
"io"
) var secretKey = "114514abcdefghijklmn"
var salt = generateSalt() // 生成一个包含 16 字节数据的盐字符串
func generateSalt() string {
randomBytes := make([]byte, 16)
if _, err := rand.Read(randomBytes); err != nil {
return ""
}
return base64.URLEncoding.EncodeToString(randomBytes)
} // 提供散列函数、密钥、盐值、消息返回HMAC
func HMAC(h func() hash.Hash, secretKey string, salt string, message string) []byte {
hash := hmac.New(h, []byte(secretKey))
io.WriteString(hash, message+salt)
return hash.Sum(nil)
} func main() {
/* ----------------------------------- 发送方 ---------------------------------- */
message := "A请求B转账10000"
fmt.Println("\n\t消息: " + message)
fmt.Println("\t加盐: " + salt) fmt.Printf("\n\tHMAC-Sha256: %x", HMAC(sha256.New, secretKey, salt, message))
fmt.Printf("\n\tHMAC-Sha256: %x", HMAC(sha512.New, secretKey, salt, message)) /* ----------------------------------- 修改一个字母 ---------------------------------- */ messageChange := "C请求B转账10000" fmt.Printf("\n\n\tHMAC-Sha256: %x", HMAC(sha256.New, secretKey, salt, messageChange))
fmt.Printf("\n\tHMAC-Sha256: %x\n\n", HMAC(sha512.New, secretKey, salt, messageChange)) /* --------------------------- 接收方分别收到了发送者的消息、HMac值 -------------------------- */
// ^ 假定消息和HMAC均被黑客截获,黑客进行重放攻击
sendMessgage := message // @ 发送者发送消息
sendHMAC := string(HMAC(sha256.New, secretKey, salt, sendMessgage)) // @ 发送者计算HMAC并与消息一起发给接收者
hackerGetHMAC := sendHMAC // @ 黑客窃听到HMAC
hackerGetMessage := sendMessgage // @ 黑客窃听到消息
receiveHMAC := hackerGetHMAC // @ 接收者收到HMAC
receiveMessage := hackerGetMessage // @ 接收者收到MESSAGE
if string(HMAC(sha256.New, secretKey, salt, receiveMessage)) == receiveHMAC {
fmt.Println("\t第1次重放攻击" + message)
}
receiveHMAC = hackerGetHMAC // @ 接收者收到HMAC
receiveMessage = hackerGetMessage // @ 接收者收到MESSAGE
if string(HMAC(sha256.New, secretKey, salt, receiveMessage)) == receiveHMAC {
fmt.Println("\t第2次重放攻击" + message)
}
// ^ 假定消息和HMAC都是黑客发送的,但黑客并不知道密钥和盐值
sendMessgage = "今天是KFC V我小能喵喵喵50速速" // @ 发送者发送消息
sendHMAC = string(HMAC(sha256.New, "miyueshishenme", "114514", sendMessgage)) // @ 黑客计算HMAC并与消息一起发给接收者
receiveHMAC = sendHMAC // @ 接收者收到HMAC
receiveMessage = sendMessgage // @ 接收者收到MESSAGE
if string(HMAC(sha256.New, secretKey, salt, receiveMessage)) != receiveHMAC {
fmt.Println("\t消息不一致、认证失败")
}
}
PS C:\Users\小能喵喵喵\Desktop\Go\Cryptography\HMAC> go run .

    消息: A请求B转账10000
加盐: S_XlM8K_dhAvsgch_N3o1w== HMAC-Sha256: b8dd30d2a418262494f298bcdaf6c12f442c6e8f89a31822dad03561887f3bed
HMAC-Sha256: ba934567837ec98ba89853b09f6652ce56955cfeedd0c4495bd6cba7fc2f8293635fdc59b90180564bd0fdb1d1bffc52644fc2bd8164d6379ae11510e200954c HMAC-Sha256: 2db84d209e2418f314fc5bb0583cfb50cde90d954d8493d3ed0e3b369fb092d7
HMAC-Sha256: 7b192cedb1d89fd71889189a0094e1df06d26d977bc3bed4f53b16928aa2d58084cb8890d52cb40f665bb9ac62eeb4092495efe7d59292470ed597a3536dea56 第1次重放攻击A请求B转账10000
第2次重放攻击A请求B转账10000
消息不一致、认证失败

如何防止重放攻击

  • 给消息加序号,收发双方约定好
  • 时间戳,收发双方必须考虑到通信延迟,还是会存在重放攻击的空间。
  • 接收者发送一次性随机数,发送者HMAC该随机数后发送。确保当前消息只能发一次。

密码学奇妙之旅、03 HMAC单向散列消息认证码、Golang代码的更多相关文章

  1. 【Java-加密算法】对称加密、非对称加密、单向散列(转)

    一提到加密,就会联想到数字签名,这两个经常被混淆的概念到底是什么呢? 加密:加密是一种以密码方式发送信息的方法.只有拥有正确密钥的人才能解开这个信息的密码.对于其他人来说,这个信息看起来就像是一系列随 ...

  2. 29.密码学知识-消息认证码MAC-6——2019年12月19日

    1. 消息认证码 1.1 消息认证 消息认证码(message authentication code)是一种确认完整性并进行认证的技术,取三个单词的首字母,简称为MAC. 思考改进方案? 从哈希函数 ...

  3. 密码学初级教程(五)消息认证码MAC-Message Authentication Code

    密码学家工具箱中的6个重要的工具: 对称密码 公钥密码 单向散列函数 消息认证码 数字签名 伪随机数生成器 MAC能识别出篡改和伪装,也就是既可以确认消息的完整性,也可以进行认证. 消息认证码的输入包 ...

  4. Shiro+springboot+mybatis+EhCache(md5+salt+散列)认证与授权-03

    从上文:Shiro+springboot+mybatis(md5+salt+散列)认证与授权-02 当每次进行刷新时,都会从数据库重新查询数据进行授权操作,这样无疑给数据库造成很大的压力,所以需要引入 ...

  5. hmac库 密钥相关的哈希运算消息认证码

    # -*- coding: cp936 -*- #xiaodeng #python 2.7.10 #HMAC是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一 ...

  6. HMAC哈希消息认证码

    收藏 137 14   hmac 编辑 HMAC是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出.   中文名 哈希消息认证码 外文名 H ...

  7. Shiro+springboot+mybatis(md5+salt+散列)认证与授权-02

    代码延续地址:Shiro+springboot+mybatis(md5+salt+散列)认证与授权-01 1.创建t_role角色表(比如管理员admin,普通用户user等),创建t_pers权限表 ...

  8. 密码学奇妙之旅、02 混合加密系统、AES、RSA标准、Golang代码

    CTR 计数器模式 计数器模式CTR是分组密码模式中的一种.通过将逐次累加的计数器进行加密来生成密钥流的流密码.每次加密时会生成一个不同的值来作为计数器的初始值. 可以事先进行加密.解密的准备. 加密 ...

  9. Shiro+springboot+mybatis(md5+salt+散列)认证与授权-01

    这个小项目包含了注册与登录,使用了springboot+mybatis+shiro的技术栈:当用户在浏览器登录时发起请求时,首先这一系列的请求会被拦截器进行拦截(ShiroFilter),然后拦截器根 ...

随机推荐

  1. Solution -「校内题」Xorequ

    0x00 前置芝士 数位dp考试里出现的小神题?? 显然考场会选择打表找规律. 数位dp + 矩阵快速幂 0x01 题目描述 给定正整数 \(n\),现有如下方程 \(x \bigoplus 3x = ...

  2. 常见加密算法C#实现(一)

    前言:最近项目中需要用到字符串加解密,遂研究了一波,发现密码学真的是博大精深,好多算法的设计都相当巧妙,学到了不少东西,在这里做个小小的总结,方便后续查阅. 文中关键词: 明文(P,Plaintext ...

  3. Flink Window&Time 原理

    Flink 中可以使用一套 API 完成对有界数据集以及无界数据的统一处理,而无界数据集的处理一般会伴随着对某些固定时间间隔的数据聚合处理.比如:每五分钟统计一次系统活跃用户.每十秒更新热搜榜单等等 ...

  4. 基于Caffe ResNet-50网络实现图片分类(仅推理)的实验复现

    摘要:本实验主要是以基于Caffe ResNet-50网络实现图片分类(仅推理)为例,学习如何在已经具备预训练模型的情况下,将该模型部署到昇腾AI处理器上进行推理. 本文分享自华为云社区<[CA ...

  5. 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...

  6. 清理忽略springboot控制台启动的banner和启动日志

    清理忽略springboot控制台启动的banner和启动日志 1.springboot的banner spring: main: banner-mode: off 2.mybatis-plus的ba ...

  7. V8中的快慢属性(图文分解更易理解)

    出于好奇:js中使用json存数据查找速度快,还是使用数组存数据查找快? 探究V8中对象的实现原理,熟悉数组索引属性.命名属性.对象内属性.隐藏类.描述符数组.快慢属性等等. D8调试工具使用请来这里 ...

  8. SpringMvc 如何同时支持 Jsp 和 Json 接口?

    后端同学基本都会见过这种场景:在同一个工程中,有些页面使用jsp模版渲染,同时还有其他接口提供Json格式的返回值.为了同时支持这两种场景,我们一般是如何处理的呢? 其实非常简单: 1.在项目中为 S ...

  9. java中list集合的几种去重方式

    public class ListDistinctExample { public static void main(String[] args) { List<Integer> list ...

  10. CF-1453B

    Problem - 1453B - Codeforces 题意: 一个数组,每次可以选择一个后缀,将其加一或者减一,开始的时候可以免费改变一个数的数值,判断让所有数字相等所需要的最小操作数. 题解: ...