【密码学】一文读懂HMAC

简介: 本文将来聊一聊基于哈希函数的消息认证码,在此之前,先来科普一下什么是 「消息认证码」 (MAC), 先来看一个简单的栗子

一文读懂HMAC


%PU9~C(V693(GZW[_@E_HAO.jpgHMAC

本文将来聊一聊基于哈希函数的消息认证码,在此之前,先来科普一下什么是 「消息认证码」 (MAC), 先来看一个简单的栗子


消息认证码

VZ5AX8XIZ`7KJ0FKW(NMXV8.jpg

image.gif消息认证码

中国第一家票号--日升昌,诞生于清道光三年的陕西省平遥县,它采用了汉字当做密码,即用汉字代表数字当中的0-9,以及采用汉字表示一年12个月和30天。比如: 全年12个月可以用"谨防假票冒取, 勿忘细视书章", 三十天可以表示为: "堪笑世情薄,天道最公平,昧心图自利,阴谋害他人,善恶终有报,到头必分明", 代表银两的10个数字代码为: "赵氏连城璧,由来天下传", 如上图所示, 5月15日汇银三百两可以表示为"冒利连通流", 这里我稍稍做一点点的修改,将明文和密文都放在了一块,这样如果某个人篡改了某个日期,那么对应的汉字就会不一致,这就可以判断原始消息有没有发生篡改。(虽然这个安全性实际上是没有比之前高的,但是因为剧情需要,各位读者凑合着看一下吧 ^.^)。

消息认证码,是一种认证技术,他利用密钥来生成一个固定长度的短数据块,并将该数据块附加在消息之后,正如上面的那个简单的栗子,密钥可以看做是数字对应的汉字,当然上面的那个长度实际上是不固定的, 有点差别, 仅做参考。

在这种方法中, 有请密码学的老演员Alice和Bob, 他们共享密钥K, 如果Alice向Bob发送消息,则由A计算MAC, 他是消息和密钥的函数, 即:

消息和MAC一同发给Bob, 接收方收到消息用相同的密钥和算法进行计算,得到新的MAC, 并将这两个进行对比, 如果这两个一样,表明消息没有被篡改, 否则说明消息已经被更改。

B]91Y_VK$RGRW55T{O`T_0P.png

image.gifAlice-Bob通信


基于Hash函数的MAC: HMAC

上面简单介绍了一下什么是MAC, 回到本文的主角,基于哈希函数设计的消息验证码(HMAC)。对于HMAC, 这实际上可以看做是一种结构,可以直接使用任意的现有的哈希函数,如果之前的哈希函数发现安全度不够了,则可以非常轻松的替换成为另一个安全性更高的哈希函数。

算法描述

6@62Z]6(E0)N]8GAUYRKQ$P.png算法描述

  • 如果KEY大于分组长度,则对原始的KEY取哈希值得到
  • 如果KEY小于分组长度,则在KEY后面填充0得到
  • 如果KEY就等于分组长度了,则KEY就是
  • 计算然后在后面拼接上原始消息后进行哈希得到新的值
  • 计算然后拼接上一步得到的新的值,最后进行哈希得到最终的结果

整个流程看起来应该还是比较清晰的,如果不能理解文字的描述,可以借助图来帮助理解一下。

算法实现

这里,还是用老演员rust来实现这个算法,有关哈希函数的实现,可以去参考我之前写的文章,这里就不去重复贴一遍哈希函数实现的代码了。

简单解释一下代码,因为HMAC是一种结构,所以这次实现就不能默认固定死哈希算法了,因此先来定义一个trait, 这个可以理解为一个接口。

pub trait Digest {
    fn digest(&self, message: impl AsRef<[u8]>) -> String;
}

这个trait接受任意消息然后输出对应的摘要, 然后让之前写过的hash函数实现这个trait。

impl Digest for MD5 {
    fn digest(&self, message: impl AsRef<[u8]>) -> String {
        let input = message.as_ref();
        MD5::hash(input)
    }
}

先来用MD5实现一下吧,这里实际上可以用任意的哈希函数。

pub fn decode_hex(s: &String) -> Result<Vec<u8>, ParseIntError> {
    (0..s.len())
        .step_by(2)
        .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
        .collect()
}
pub struct HMAC<D>
    where
        D: Digest + Default,
{
    digest: D,
}
impl<D> HMAC<D>
    where
        D: Digest + Default,
{
    fn new() -> Self {
        HMAC {
            digest: Default::default(),
        }
    }
    fn finalize(self, message: &mut Vec<u8>, key: &mut Vec<u8>) -> String {
        let mut padding_key = key.clone();
        if key.len() > BLOCK_SIZE {
            padding_key = Vec::from(self.digest.digest(key).as_bytes());
        }
        while padding_key.len() < BLOCK_SIZE {
            padding_key.push(0x0);
        }
        let mut o_key_pad = padding_key.iter().map(|&it| it ^ OPAD).collect::<Vec<_>>();
        let mut i_key_pad = padding_key.iter().map(|&it| it ^ IPAD).collect::<Vec<_>>();
        i_key_pad.append(message);
        let mut hash = decode_hex(&self.digest.digest(i_key_pad)).unwrap();
        o_key_pad.append(&mut hash);
        self.digest.digest(o_key_pad)
    }
}
#[cfg(test)]
mod tests {
    use crate::HMAC;
    use sha1::SHA1;
    use md5::MD5;
    #[test]
    fn it_works() {
        type HmacMD5 = HMAC<MD5>;
        let hmac = HmacMD5::new();
        let result = hmac.finalize(&mut "123456".as_bytes().to_vec(), &mut "123456".as_bytes().to_vec());
        println!("{}", result);
    }
}


小结

本文简单介绍了一下什么是MAC, 以及HMAC的主要流程,文章最上面的例子可能些许的不恰当,还请各位读者海涵。

相关文章
|
Rust 算法 网络安全
【密码学】一文读懂CMAC
介于上一篇文章比较水,然后这个和上一篇也比较相似,CMAC是为了解决DAA当中安全性不足的问题而出现的,这个算法一共有三个密钥,K, K1, K2, 其中K1和K2可以由K导出,接下来就来一起看一下CMAC的具体过程吧,这一篇文章其实也不长。
4877 0
【密码学】一文读懂CMAC
|
存储 Rust 并行计算
【密码学】一文读懂XTS模式
这篇文章的灵感来源于我偶然翻到的一个某U盘有关磁盘加密的一个介绍(这一篇不是广告蛤), 然后发现这个模式我之前还真没遇到过,因此呢,就学习了一下,就出来了这一篇文章。
7610 0
【密码学】一文读懂XTS模式
|
机器学习/深度学习 算法 安全
密码学系列之五:MD5、SHA1——一文搞懂哈希函数
密码学系列之五:MD5、SHA1——一文搞懂哈希函数
9482 0
|
算法 安全 网络安全
简单认识一下mbedTLS
简单认识一下mbedTLS
1789 0
|
Web App开发 Rust 算法
【密码学】一文读懂ChaCha20
好久没写新的加密算法的原理了, 这次所选取的加密算法结构比较简单, 一起来看一下吧。
9561 1
【密码学】一文读懂ChaCha20
|
并行计算 算法 搜索推荐
简单学习一下AES算法:GCM、ECB、CFB、OFB等
简单学习一下AES算法:GCM、ECB、CFB、OFB等
2015 0
|
算法 安全 Go
【密码学】一文读懂HKDF
我这又来水一篇文章,来聊一下HKDF(基于HMAC的密钥导出函数)。密钥派生函数是密钥管理的组成部分,他的目标是通过一些初始的数据派生出来密码学安全的随机密钥。
3678 1
【密码学】一文读懂HKDF
|
JavaScript 算法 前端开发
国标哈希算法基础:SHA1、SHA256、SHA512、MD5 和 HMAC,Python和JS实现、加盐、算法魔改
国标哈希算法基础:SHA1、SHA256、SHA512、MD5 和 HMAC,Python和JS实现、加盐、算法魔改
1430 1
|
Rust 搜索推荐 算法
【密码学】一文读懂GCM(Golais计数器模式)
GCM(Galois计数器模式)同样的也是NIST提出来的,这个模式基于并行化设计,下面来一起看一下这个模式具体是如何工作的吧。
3180 0
【密码学】一文读懂GCM(Golais计数器模式)
|
算法 安全 网络安全
信息安全: MAC(消息认证码)算法,保护数据完整性和真实性的利器
MAC 算法在保证数据完整性和真实性方面扮演着重要角色。HMAC 和 CMAC 作为两种主要的 MAC 算法,因其高安全性和广泛应用,已经成为现代通信和数据保护中不可或缺的一部分。通过本文的介绍,希望读者能够更好地理解和使用 MAC 算法,保障信息的安全性。