【密码学】一文读懂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的主要流程,文章最上面的例子可能些许的不恰当,还请各位读者海涵。

相关文章
|
6月前
|
算法 安全 关系型数据库
密码学系列之七:数字签名
密码学系列之七:数字签名
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂XTEA加密
本篇文章,我们来看一下上一次讲过的TEA加密算法的一个升级版XTEA, 相比于TEA, XTEA的安全性显然是更高的,其中的过程要比TEA稍微复杂一点点。
1265 0
【密码学】一文读懂XTEA加密
|
4月前
|
安全 算法 Java
密码学基础知识与加密算法解析
密码学基础知识与加密算法解析
|
6月前
|
算法 安全 网络安全
一文搞懂常见的加密算法
一文搞懂常见的加密算法
812 0
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂RSA的随机数生成器
本文接着来聊一个比较轻松的内容,再来说一个随机数生成器,对于这个随机数生成器呢,这里和之前讲到过的BBS有一些类似,直接来看具体的内容蛤。
1109 1
【密码学】一文读懂RSA的随机数生成器
|
算法 安全 数据安全/隐私保护
【密码学】 一篇文章讲透数字签名
数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是在使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。数字签名可以识别消息是否被篡改, 并验证消息的可靠性, 也可以防止否认。
720 0
【密码学】 一篇文章讲透数字签名
|
算法 数据安全/隐私保护
【密码学】一文读懂SHA-1
SHA-1(Secure Hash Algorithm 1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦资料处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。
1209 1
【密码学】一文读懂SHA-1
|
算法 Serverless 数据安全/隐私保护
【密码学】一文读懂SHA-2
SHA-2安全散列算法2(Secure Hash Algorithm 2)一种密码散列函数算法标准,由美国国家安全局研发,由美国国家标准与技术研究院(NIST)在2001年发布。属于SHA算法之一,是SHA-1的后继者。其下又可再分为六个不同的算法标准,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
1026 0
【密码学】一文读懂SHA-2
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂AES
AES加密算法 本文将不会讲述过多有关AES的数学知识, 如果有兴趣的可以自行了解。
1740 0
【密码学】一文读懂AES
|
Rust 算法 安全
【密码学】一文读懂RSA
本文来聊聊RSA, 这是一个非对称密码,和之前所提到的AES与DES不同的是,这个加密方式有两个密钥,一个是公钥,一个是私钥,公钥用来加密,私钥用来解密。相比于对称密码,非对称密码大多基于某个数学难题,比如接下来要谈论的RSA即基于大整数分解的困难性来的,因此为了说明白这个加密算法,首先要先补充&quot;一&quot;点点数学知识。