MAC 与密钥派生
消息认证码(MAC)、HMAC(基于哈希的消息认证码)和 KDF(密钥派生函数)在密码学中发挥着重要作用。下面介绍何时需要 MAC、如何计算 HMAC,以及它与密钥派生函数之间的关系。
消息认证码(MAC)
消息认证码(MAC)是一种根据给定密钥和给定消息计算出的密码学代码:
auth_code = MAC(key, msg)
它通常表现得像哈希函数:消息或密钥的细微变化都会产生完全不同的 MAC 值。在实践中,不应存在修改密钥或消息后仍得到相同 MAC 值的可行方法。MAC 码与哈希一样是不可逆的:无法从 MAC 码恢复原始消息或密钥。MAC 算法也称为“带密钥哈希函数”,因为它们的行为类似带有密钥的哈希函数。
例如,可以使用 HMAC-SHA256 算法按如下方式计算 MAC 码:
HMAC-SHA256('key', 'some msg') = 32885b49c8a1009e6d66662f8462e7dd5df769a7b725d1d546574e6d5d6e76ad
上述 HMAC-SHA256 计算可以用 Python 编写如下:
import hashlib, hmac, binascii
mac = hmac.new(b'key', b'some msg', hashlib.sha256).digest()
print(binascii.hexlify(mac))
运行上面的代码示例:https://repl.it/@nakov/HMAC-SHA256-in-Python。
MAC 是一种使用预共享密钥的数字认证码,作用类似于数字签名。后续将进一步介绍数字签名。
MAC 算法
现代密码学中存在许多计算消息认证码(MAC)的算法。最流行的算法基于哈希,例如 HMAC(基于哈希的 MAC,如 HMAC-SHA256)和 KMAC(基于 Keccak 的 MAC)。另一些算法基于对称密码,例如 CMAC(基于密码的 MAC)、GMAC(伽罗瓦 MAC)和 Poly1305(Bernstein 的一次性认证器)。其他 MAC 算法还包括 UMAC(基于通用哈希)、VMAC(基于高性能分组密码的 MAC)和 SipHash(简单、快速、安全的 MAC)。
何时需要 MAC 码?
使用 MAC 码的一个示例场景如下:
- 双方以某种方式交换一个秘密的 MAC 密钥(预共享密钥)。
- 我们从某处接收到 msg + auth_code(例如来自互联网、区块链或电子邮件)。
- 我们希望确认 msg 未被篡改,也就是说,密钥和 msg 都正确并与 MAC 码匹配。
- 如果消息遭到篡改,MAC 码将不正确。

认证加密:使用 MAC 加密/解密消息
使用 MAC 码的另一个场景是认证加密:当我们加密消息时,希望确认解密密码正确,并且解密后的消息与加密前的原始消息一致。
- 首先,从密码中派生密钥。可以直接将该密钥用于 MAC 计算算法,也可以先对其进行哈希以提高安全性。
- 接下来,使用派生密钥加密消息,并将密文存入输出。
- 最后,使用派生密钥和原始消息计算 MAC 码,并将其附加到输出中。
当我们解密加密消息(密文 + MAC)时,按以下步骤进行:
- 首先,从用户输入的密码中派生密钥。密码可能正确,也可能错误,稍后即可判断。
- 接下来,使用派生密钥解密消息。所得结果可能是原始消息,也可能是错误消息,具体取决于输入的密码。
- 最后,使用派生密钥 + 解密后的消息计算 MAC 码。
- 如果计算出的 MAC 码与加密消息中的 MAC 码匹配,则说明密码正确。
- 否则,便可证明解密后的消息不是原始消息,也就意味着密码不正确。
某些认证加密算法(如 AES-GCM 和 ChaCha20-Poly1305)将 MAC 计算集成到加密算法中,并将 MAC 验证集成到解密算法中。后续将进一步学习这些算法。
MAC 与密文一同存储,并且不会泄露密码或原始消息。公开存储任何人都能看到的 MAC 码是安全的;解密后,我们可以判断消息是否为原始消息(密码是否错误)。
基于 MAC 的伪随机生成器
MAC 码的另一个应用是伪随机生成器函数。可以从某个盐(常数、当前日期和时间或其他随机值)和某个种子值(上一次生成的随机数,如 0)开始,按如下方式计算 next_seed:
next_seed = MAC(salt, seed)
每次计算上述公式后,得到的伪随机数都会“随机变化”,我们可以用它生成特定范围内的下一个随机数。我们将在“安全随机数生成器”一章中演示一个完整可运行的示例。