欢迎光临
我们一直在努力

银行卡报文鉴别码(MAC)解析:ISO9797-1到HMAC

银行卡报文鉴别码(MAC)

ISO/IEC 9797-1、ANSI X9.9 / X9.19、AS 2805.4.1、TDES CBC-MAC、Retail、CMAC、HMAC —— 一次讲清楚它们都是什么、什么关系、怎么算。

0. 为什么需要 MAC

银行卡交易报文(ISO 8583 的 0200 请求 / 0210 响应)要经过网络传输。报文里带着卡号、金额、PIN 密文……如果只是明文传输,攻击者完全可以中途把 100 块改成 10000 块,双方都察觉不到。

解决这个问题的手段叫 MAC(Message Authentication Code,报文鉴别码 / 消息鉴别码)。你列出的这一串名词——ISO 9797-1、X9.9、X9.19、AS2805.4.1、TDES CBC-MAC、Retail、CMAC、HMAC——全都是"算 MAC"这件事的各种标准、算法和叫法。这篇文章就是帮你把它们的家族关系理清楚。

1. 什么是 MAC

MAC 是用一个只有通信双方共享的密钥,对消息算出一个固定长度的"指纹"(也叫认证标签 / tag)。

发送方: MAC = F(密钥 K, 报文 M) → 把 MAC 附在报文后面发出去
接收方: 用同一个 K 对收到的 M 重新算一遍,和收到的 MAC 比对
一致 → M 没被篡改 + 确实来自持有 K 的那一方
不一致 → 拒收

它同时提供两样东西:

属性

含义

靠什么保证

完整性 Integrity

报文没被改

改一个字节,MAC 就变了

数据源认证 Data origin authentication

报文确实来自持有密钥的一方

只有双方知道 K,别人算不出来

MAC ≠ 哈希SHA-256 也算"指纹",但它只需要消息本身,任何人都能算。攻击者改了消息顺手重算一个哈希就行。MAC 掺入了密钥,攻击者没有密钥就算不出来,所以能防篡改。

MAC ≠ 数字签名数字签名用公私钥对:私钥签名、公钥验证,可以公开验证、防抵赖。MAC 用对称密钥,收发双方都能算,所以无法向第三方证明"这消息是对方发的"(因为收方自己也能造出同样的 MAC)。银行卡支付要的是快、双方互认,对称 MAC 足够,不需要上签名。

比喻:MAC 就像"信封上的火漆印 + 一枚只有你和对方才有的私章"。别人没章,盖不出有效的印;谁要是在路上动了信封,印就坏了。

2. 地基:分组密码与 CBC 模式

  • 分组密码(Block Cipher):把数据按固定块大小加密。DES 是 8 字节一块,AES 是 16 字节一块
  • CBC 模式(Cipher Block Chaining,密码分组链接):每一块先和上一块的密文异或,再加密。这样同样的明文块,因位置和前面内容不同,得到不同的密文。

设 E(K, B) = 用密钥 K 加密一块 B

C1 = E(K, m1 ⊕ IV) IV = 0
C2 = E(K, m2 ⊕ C1)
C3 = E(K, m3 ⊕ C2)

C1, C2, C3 叫"链接值"(chaining value)。MAC 家族的很多算法,本质就是"把最后一个链接值拿来当指纹"

3. 朴素 CBC-MAC:最直觉的做法,和它的致命弱点

做法:把消息按块分组,从 IV=0 开始用密钥 K 做 CBC 加密,取最后一个密文块作为 MAC。

MAC = E(K, mn ⊕ C(n-1)) ← 也就是最后一个链接值

致命弱点:长度扩展攻击(length extension attack)。因为 MAC 就是链条末端的密文,攻击者虽然不知道密钥,但可以把:

( 收到的 M || 收到的 MAC ) ← 把它当成"已经加密好的前缀"

继续往后追加自己的块,一直加密到最后,就能构造出一条更长的新消息,并算出它对应的合法 MAC。于是攻击者凭空得到一条"伪造但 MAC 正确"的消息。

另外,单密钥 CBC-MAC 在消息长度可变时还有更一般的伪造攻击。所以业界必须给这个朴素方案"打补丁",下面这些标准就是补丁的不同形式。

4. ISO/IEC 9797-1:把 MAC 算法家族整理成标准的"菜谱"

全名 《Information technology — Security techniques — Message Authentication Codes (MACs) — Part 1: Mechanisms using a block cipher》(信息技术 · 安全技术 · 用分组密码产生 MAC · 第 1 部分)。

它像一本菜谱系统,由两部分自由组合:

4.1 填充方法(Padding Method)—— 怎么把消息补成整块

消息长度不一定是块的整数倍,先填充:

方法

做法

特点

法 1(Pad 1)

末尾补0x00

最简单,X9.9 / X9.19 零售 MAC 常用;但与"本来长度就是整块"的消息

无法区分边界,单独用有安全隐患,必须靠"输出变换"补救

法 2(Pad 2)

先补一个0x80,再补0x00

永远能明确消息边界,现代标准更推荐

法 3(Pad 3)

补0x00,但把原始消息长度

作为一块放在消息最前面

天然防扩展攻击,但要求算 MAC 前就知道长度

法 4(Pad 4)

CMAC 专用

配合算法 5

4.2 算法(MAC Algorithm)—— 怎么跑 CBC + 最后一块怎么收尾

定义了两件事:中间怎么 CBC,以及最后一个链接值 On 怎么变换成 MAC。这个"输出变换"就是对付第 3 节那个弱点的补丁:

算法

密钥

最后变换

谁在用

算法 1

单密钥 K

直接E(K, On)

朴素 CBC-MAC;老标准 X9.9、ISO 8731-1

算法 2

双密钥

末块改用第二把密钥加密

E(K2, On)

双密钥 CBC-MAC

算法 3

双密钥

末块先

用 K2 解密、再用 K1 加密

E(K1, D(K2, On))

零售 MAC(Retail MAC)

,即 X9.19 

算法 4

双密钥

顺序反过来

D(K2, E(K1, On))

部分网络细则

算法 5

单密钥

CMAC

(配填充法 4)

现代标准、AES 方案

现行版(2011 年)还定义了第 6 种算法,是 CMAC 家族的变体,支付领域几乎见不到,不必关心。

关键结论"零售 MAC"不是谁新发明的算法,它就是 ISO 9797-1 算法 3 + 填充法 1,用双密钥 3DES。 业界常把"零售 MAC"和"双密钥 CBC-MAC"混着叫,说的是同一个东西。

5. Retail MAC / ANSI X9.19:支付行业最常用的 MAC

5.1 历史脉络

  • ANSI X9.9Financial Institution Message Authentication,批发 Wholesale):单密钥 DES 的 CBC-MAC,典型取 4 字节。56 位密钥,今天看太弱。
  • ANSI X9.19Financial Institution Retail Message Authentication,零售 Retail):银行卡支付用的,双密钥 3DES,MAC 8 字节(很多网络取前 4)。
    • 兼容设计:如果两半密钥相等(K1 = K2),X9.19 的算法结果恰好退化成 X9.9。所以一套硬件/软件同时支持两个标准——这也是很多 HSM 里同一个 MAC 服务能配"单长度/双长度密钥"的原因。
  • 国际对应关系:X9.9 ↔ ISO 8731-1,X9.19 ↔ ISO 9807。

5.2 零售 MAC 具体怎么算

设密钥为 16 字节双长度密钥,拆成 K1 = 前 8 字节,K2 = 后 8 字节:

① 填充 M' = M || 00…00 (按填充法 1 补到 8 字节整数倍)
② CBC On = E(K1, … E(K1, E(K1, m1 ⊕ IV)) … ) IV = 0,全部用 K1
③ 末变换 MAC = E(K1, D(K2, On))

① 填充:消息按填充法 1 补 0x00 到 8 字节的整数倍;

② CBC:从 IV=0 开始,用 K1 对消息做 DES-CBC,得到最后一个密文块 On

③ 末变换:先用 K2On 做 DES 解密,再用 K1 加密;

④ 输出:得到 8 字节 MAC。ISO 8583 的 F64 / F128 通常取前 4 字节或全 8 字节(各家网络规定不同)。

为什么最后要"解密再加密"这一下? 因为朴素 CBC-MAC 有长度扩展攻击。D(K2) ∘ E(K1) 这个输出变换把链条末端的链接值换了一把 K2 重新打散——攻击者不知道 K2,就没法把自己追加的块"接"上去,伪造立刻失效。

6. TDES CBC-MAC:到底是 3DES 还是 DES?

最容易混的点:

  • 零售 MAC 的 CBC 阶段用的是单 DES(K1 那 8 字节),不是 3DES 跑三遍。所谓"双密钥 3DES"体现在最后变换的 E-D 结构上(K1 加密、K2 解密、K1 加密),合成一个 2-key 3DES 的等效效果。
  • "TDES CBC-MAC"这个词还经常被泛指:任何用 3DES 密钥做的 CBC-MAC 家族(ISO 9797-1 算法 2/3/4 的双长度甚至三长度密钥做法,HSM 里通常叫 M0 / M1 等 key variant)。IBM CCA 的 MAC 服务里,X9.19 双/三长度密钥就对应 ISO 9797-1 算法 3
  • 三密钥变体(24 字节 K1/K2/K3)各网络细则不同,一般是 CBC 用 K1,最后变换串上更多层 E/D。联调时先问清楚对方是 2-key 还是 3-key,K1/K2 各是哪一段。

7. AS 2805.4.1:澳大利亚的 EFTPOS 标准

  • 全名 《Electronic funds transfer — Requirements for interfaces, Part 4.1: Message authentication — Mechanisms using a block cipher》(电子资金转账 · 接口要求 · 第 4.1 部分 · 报文鉴别)。
  • 澳大利亚的银行卡网络(ATM / EFTPOS,即银联通道/收单体系之外的澳本土网)几乎独家用 AS 2805 系列。AS 2805.4.1 规定了用分组密码生成/校验 MAC,本质就是 ISO 9797-1 的零售 MAC(2-key 3DES),后来干脆改名 AS ISO/IEC 9797.1:2019(直接采用国际标准)。
  • 特点:澳洲网络要求 MAC 密钥单向使用——上行/下行各一把,分开用。这和 DUKPT 里"Msg Auth Req Key(请求方向)/ Msg Auth Rsp Key(响应方向)"的思路完全一致(见下文第 11 节)。
  • 对你的意义:做澳洲收单 / EFTPOS 联调时,听到"AS2805.4.1 MAC"不要慌——它就是拿一把 16 字节 3DES 密钥跑零售 MAC,跟你在 txn_sim 里 mac.c 的 mac_retail 是同一套东西。

8. CMAC:现代接班人(AES-CMAC,NIST SP 800-38B)

8.1 为什么还要有 CMAC

零售 MAC(算法 3)能防扩展攻击,但配合 Pad 1 时,"消息长度恰好是整块"和"差一块"这两种情况无法从密文上区分,边界仍有歧义,安全证明也不友好。CMAC 用一个统一的办法解决:从密钥派生两个子密钥 K1、K2,用来区分"最后一块是完整块还是部分块"。一个算法通吃,安全性有正式证明。

8.2 步骤

① 子密钥 L = AES_K(0^128) (用 K 加密 16 个 0 字节)
K1 = 2·L (左移一位,最高位进位则异或 0x87)
K2 = 2·K1
② CBC 对前 n-1 块用 K 做 CBC,得链接值 X
③ 末块 完整块 → 用 K 加密(末块 ⊕ X ⊕ K1)
部分块 → 补 0x80 00… 后,用 K 加密(末块 ⊕ X ⊕ K2)
④ 输出 16 字节(可截断)

  • 用密钥 K 加密全 0 块,得到 L;
  • 生成子密钥:K1 = L << 1(最高位进位则异或 0x87);K2 = K1 << 1,同样处理进位;
  • 消息按 16 字节分组,用 K 做 CBC,一直加密到倒数第二块
  • 最后一块:完整块 → 异或 K1 后加密;部分块 → 补 0x80 00… 后异或 K2 再加密;
  • 输出 16 字节(可截断到需要的长度)。
  • 出现场合:EMV 的部分数据认证、AES 迁移方案、新 HSM API。ISO 9797-1 算法 5 就是它。

    9. HMAC:另一条技术路线(基于哈希,不碰分组密码)

    • HMAC(RFC 2104)不基于 DES/AES,而基于哈希函数(SHA-1 / SHA-256 / SHA-512)。结构是"密钥做两次填充、两次哈希":

    HMAC(K, M) = H( (K ⊕ opad) ‖ H( (K ⊕ ipad) ‖ M ) )
    ipad = 0x36 opad = 0x5C (按哈希块长重复填充)

    ipad/opad 的作用是把密钥摊到两个独立输入里,从而防住长度扩展之类的攻击。

    • 特点:软件实现快、OpenSSL / Java 到处都有,是互联网世界的 MAC 主角——TLS、JWT、API 签名、支付回调验签里全是它。
    • 但在传统银行卡报文(ISO 8583 / 零售 MAC)生态里几乎不用:因为既有网络是用分组密码 + 3DES 一路铺过来的,主机侧的 HSM(加密机)也都是按分组 MAC(M0/M1…)实现的,改哈希不现实。

    一句话总结:HMAC 是"互联网世界"的 MAC,零售 MAC / CMAC 是"银行卡世界"的 MAC。 做支付别拿 HMAC 去和银行对 MAC,对不上。

    10. 一张表看懂全部

    名称

    本质

    密钥

    典型输出

    主要场景

    对应关系

    ANSI X9.9

    单密钥 DES 的 CBC-MAC

    1×DES(8B)

    4 / 8 B

    批发(Wholesale)报文、老零售

    ISO 9797-1

    算法1 + Pad1

    ANSI X9.19

    双密钥 3DES 的 CBC-MAC + ED 变换

    2×DES(16B)

    8 B(常取前 4)

    银行卡支付主力

    ISO 9797-1

    算法3 + Pad1

    零售 MAC / Retail

    = X9.19 的行业叫法

    同上

    同上

    POS / ATM 交易报文

    ISO 9807;同左

    ISO/IEC 9797-1

    通用"菜谱"标准

    1~2 把

    任意长度

    标准框架

    算法 1/2/3/4/5 × 填充 1/2/3/4

    AS 2805.4.1

    澳洲版零售 MAC

    2-key 3DES

    8 B

    澳大利亚 ATM / EFTPOS

    同算法 3,已并入 AS ISO/IEC 9797.1:2019

    CMAC

    子密钥版 CBC-MAC

    AES / 3DES

    16 B

    现代标准、EMV、AES 迁移

    NIST SP 800-38B;ISO 9797-1 算法5 + Pad4

    HMAC

    基于哈希的 MAC

    任意长密钥

    哈希输出长

    互联网、TLS、API 签名

    RFC 2104

    12. 避坑清单

  • MAC ≠ 加密:MAC 只认证、不保密。报文正文通常仍是明文(PIN 才单独加密成 PIN block)。
  • MAC ≠ 哈希:哈希谁都能算;MAC 需要密钥。别在报文里塞个 SHA-256 冒充 MAC。
  • 三个名字是一个东西:Retail MAC = ANSI X9.19 = ISO 9797-1 算法 3 + 填充法 1(双密钥 3DES)。
  • 别默认"对整条报文算 MAC":先确认各网络/MAC 数据域的字段拼接规则。
  • 填充方式要先问:Pad 1(补 0)vs Pad 2(补 80 00)算出来完全不同。联调对不上,先看填充。
  • 注意截断长度:F64 可能是前 4 字节。你把 8 字节全比了,遇到"对方按 4 字节截断"就会验不过。
  • K1/K2 顺序别反:零售 MAC 是 E(K1, D(K2, On)),反成 E(K2, D(K1, On)) 结果完全不同。
  • 密钥分方向:上行/下行 MAC 密钥可能不同(DUKPT 的 GEN / BOTH 角色、AS2805 的单向密钥)。混用会"时好时坏",很难排查。
  • 长度扩展攻击是理解这一切的主线:把"最后链接值 + 输出变换"理解透,ISO 9797-1 各种算法就都会了。
  • 13. 参考

    • ISO/IEC 9797-1:2011《Information technology — Security techniques — MACs — Part 1: Mechanisms using a block cipher》
    • ANSI X9.9 / ANSI X9.19(零售报文鉴别)
    • AS 2805.4.1 / AS ISO/IEC 9797.1:2019(澳大利亚 EFTPOS 报文鉴别)
    • NIST SP 800-38B《Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication》
    • RFC 2104《HMAC: Keyed-Hashing for Message Authentication》
    • RSA Labs: What are ANSI X9 standards?
    • IBM z/OS 文档:MAC keys
    • AusPayNet IAC 规范(澳洲 EFTPOS 强制 AS 2805.4.1)
    • AWS Payment Cryptography:AS2805 MAC 概述
    赞(0)
    未经允许不得转载:171主机测评 » 银行卡报文鉴别码(MAC)解析:ISO9797-1到HMAC
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址