如何确保消息的完整性,即没有被篡改,一种方式是用哈希算法计算一个摘要,但如果哈希值的来源变得不可行,那么它也就无法确保数据的完整性!

消息认证这个密码学原语可以满足我们的要求,与哈希函数的相同之处在于将消息作为输入,不同之处是还需要输入对称密钥,最后算法会输出一个唯一的消息认证码(Message Authentication Code,MAC)。这个算法是确定性的,即给定相同的对称密钥和消息,将产生相同的认证标签。

消息认证算法就像一个私有的哈希函数,只有拥有密钥的人才能计算消息在该密钥下对应的哈希值。

所以,为了验证消息的完整性,可以让我们与通信的用户使用相同的密钥来计算消息的 MAC。

MAC 的安全属性:

  • 可以防止伪造认证标签。只要消息认证码算法的密钥是保密的,就可以防止伪造认证标签。此外,为了避免模糊攻击,在使用消息认证码算法之前应将其序列化。

    模糊攻击:“Alice" + ”Bob" + "100" + "15" 生成的哈希值与 “Alice" + ”Bob" + "1001" + "5" 相同,因此在计算哈希值之前,应先对数进行序列化。

  • 认证标签长度不应小于 128 比特,避免出现认证标签碰撞和伪造的问题。我们对哈希函数的输出要求是 256 比特,但哈希函数是可以离线计算的公开算法,而消息认证码算法这类带有密钥对算法是不能离线计算的,只能直接向服务器请求认证标签。
  • 如果只使用消息认证码对消息进行简单的认证,无法检测重放的消息。可以在消息认证码算法的输入中增加递增计数器。或者频繁更换共享密钥。
  • 在恒定时间内完成两个认证标签的比较。否则,攻击者可通过服务器响应的时间推断伪造的认证标签首次出现错误的位置,从而逐字节地重构有效的认证标签,称为时序攻击(Timing Attack)。

实际应用中的消息认证码:

  • HMAC,基于哈希函数的消息认证码算法,使用最广泛。使用的哈希函数主要是 SHA-2,SHA-2 不能直接计算秘密消息的哈希值,因为容易受到长度扩展攻击。那么如何将哈希函数转为密钥算法:将密钥 k1 和待认证的消息串联并计算哈希值,然后将密钥 k2 与前一步骤输出串联并计算哈希值。k1 和 k2 都是从密钥 k 派生来的。

    长度扩展攻击:如果拥有一个消息的哈希值,就可以计算更多由该消息扩展的消息的哈希值。例如,算出 SHA-256(key || cookie) 后,就可以算出 SHA-256(cookie || PADDING || "&adming=true")。

  • KMAC,基于 cSHAKE 的消息认证码算法。SHA-3 不易遭到长度扩展攻击,所以使用 SHA-3 构造 HMAC 算法还不如直接使用 SHA-3-256(key || message),这正是 KMAC 的做法。KMAC 对密钥、输入和输出长度进行编码。

参考

戴维-王. 深入浅出密码学[M]