【密码学】一文读懂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 算法 数据安全/隐私保护
【密码学】一文读懂XTEA加密
本篇文章,我们来看一下上一次讲过的TEA加密算法的一个升级版XTEA, 相比于TEA, XTEA的安全性显然是更高的,其中的过程要比TEA稍微复杂一点点。
1285 0
【密码学】一文读懂XTEA加密
|
Rust 算法 Go
【密码学】一文读懂MurMurHash3
本文应该是MurMurHash算法介绍的最后一篇,来一起看一下最新的MurMurHash算法的具体过程,对于最新的算法来说,整个流程和之前的其实也比较相似,这里从维基百科当中找到了伪代码,也就不贴出来Google官方给出的推荐代码了,先来看一下维基百科给出的伪代码,这里只有32位的伪代码。
2191 0
【密码学】一文读懂MurMurHash3
|
5月前
|
安全 算法 Java
密码学基础知识与加密算法解析
密码学基础知识与加密算法解析
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂RSA的随机数生成器
本文接着来聊一个比较轻松的内容,再来说一个随机数生成器,对于这个随机数生成器呢,这里和之前讲到过的BBS有一些类似,直接来看具体的内容蛤。
1124 1
【密码学】一文读懂RSA的随机数生成器
|
算法 数据安全/隐私保护
【密码学】一文读懂SHA-1
SHA-1(Secure Hash Algorithm 1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦资料处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。
1224 1
【密码学】一文读懂SHA-1
|
算法 搜索推荐 安全
【密码学】一文读懂CCM
本文简单介绍了CCM模式下的认证和加密机制,实际上这个是AES-CTR模式和CMAC的一个组合,如果理解了前面这两个,本文应该还是比较好理解的。
3417 0
【密码学】一文读懂CCM
|
算法 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。
1056 0
【密码学】一文读懂SHA-2
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂AES
AES加密算法 本文将不会讲述过多有关AES的数学知识, 如果有兴趣的可以自行了解。
1763 0
【密码学】一文读懂AES
|
算法 安全
【密码学】一文读懂MD2
MD2是Ranald Rivest在1989年提出的哈希函数,本文主要介绍一下MD2算法的基本原理,尽管现在MD2已经并不安全,作为一个结构比较简单的哈希函数,学习一下还是十分有必要的。
1463 0
【密码学】一文读懂MD2
|
算法 安全 数据安全/隐私保护
【密码学】一文读懂MD4
MD4是麻省理工学院教授Ronald Rivest于1990年设计的一种信息摘要算法。它是一种用来测试信息完整性的密码散列函数的实行。其摘要长度为128位。这个算法影响了后来的算法如MD5、SHA家族和RIPEMD等。
1469 0
【密码学】一文读懂MD4