跳转到主要内容
  1. 安全洞察与公告/

低熵数据与信用卡哈希的安全边界(APAC)

一个令人不安的事实:哈希不等于保护。你可以存储信用卡号的 SHA-256 哈希值,完全符合 PCI DSS,却实际上毫无保护可言,因为你哈希的那个值根本不含足以抵御暴力破解的熵。

这会让平时很严谨的工程团队栽跟头,因为哈希感觉上是安全的。哈希是单向的,原值无法通过反推函数还原,所以数据理应是受保护的。问题不在哈希本身,而在于你喂给它的是什么。

用真实数字看熵的问题 #

16 位卡号不是随机的。它的结构是公开且固定的:

  • 前 4 到 6 位是发卡行识别码(IIN):银行前缀,完全公开。
  • 最后一位是校验位,由 Luhn 算法计算得出,这个公式 1954 年就发表了。它不是秘密,只是错误检测。

再按 PCI DSS 常见允许的方式遮蔽 PAN:前 4 到 6 位和后 4 位可见,中间 6 到 8 位隐藏:

4532 AAXX XXXX 1234

IIN 已知 4 位的情况下,未知部分是8 位数字,即至多 100,000,000 种可能。套用 Luhn 校验后只有十分之一能存活。你真正的搜索空间是 1,000 万个值。这不是一个密码,这是一份很短的清单。

测试 1,000 万个哈希需要多久? #

接下来情况会更糟。SHA-256 在设计上就是的。它是为千兆级速度的完整性校验而生,而不是为存储秘密。现代 GPU 破解跑分是公开且可复现的:

硬件大致 SHA-256 吞吐
1× RTX 4090 GPU约 85 亿次哈希/秒
4× RTX 4090 集群约 340 亿次哈希/秒
8× RTX 4090 集群约 680 亿次哈希/秒

1,000 万次猜测除以每秒 85 亿次,大约是千分之一秒。一块消费级显卡就够了。甚至一台单 GPU 的电脑都能用彩虹表在眨眼之间"反解"出一个信用卡号。

结论很直白:合规不等于安全。**对于低熵字段,即便是 SHA-2(或 SHA-3)也不安全,即使它合规。**函数确实是单向的,但当输入空间极小时,它会被轻而易举地穷举殆尽。把 SHA-256 换成 SHA-512 或 SHA-3 解决不了问题,因为它们同样快。

“合规"真正允许的是什么 #

PCI DSS 其实并没有要求你用 SHA-256 哈希 PAN。要求 3.5 说的是你必须用强密码学使 PAN 不可读,并明确点名了带密钥的哈希和加密,同时指出:只要盐值保密、哈希不具备现实可逆性,加盐哈希索引是可以接受的。问题在于,对一个只有 1,000 万值空间的裸 SHA-256 而言,穷举在实践中就等于可逆,因此它违背了要求的本意,哪怕检查表上打了勾。

遮蔽(显示前 4-6 位和/或后 4 位)是另一项独立控制:它保护的是操作员看到的内容,而不是你存储的内容。两者极易混淆,而这种混淆正是"已遮蔽但未加盐哈希"的 PAN 混进生产环境的原因。

如何正确保护这类数据 #

修复方法是用对待密码的态度对待低熵字段,因为在数学上它们一样弱。按优先级排序:

  1. **干脆不要存储它。**将 PAN 令牌化,把真实号码保存在独立的保险库或 HSM 中。如果你从不存储这个值,就没有什么可以被暴力破解。
  2. **带秘密 pepper 的 keyed hashing(HMAC)。**如果必须以 PAN 为索引,使用 HMAC,并将高熵密钥保存在数据库之外。没有密钥,无论输入熵多低,暴力破解在算力上都不可行。
  3. **内存困难型密码哈希。**当你只能靠值本身来保护值时,使用 Argon2id(RFC 9106)或 scrypt,配合每个值的随机盐和调校过的参数,让每一次猜测都消耗真实的时间和内存。比如 64 MB 内存成本的 Argon2id,能把那次 0.001 秒的穷举变成数月的 GPU 时间。
  4. **到处使用盐和 pepper。**每个值的随机盐可以击败预计算的彩虹表;只要保守住秘密,pepper 可以彻底击溃离线攻击。 OWASP 密码存储速查表NIST SP 800-63B 正是出于同样的原因,推荐对低熵机密使用内存困难型函数。
flowchart TD A[存储 PAN] --> B{索引用?} B -- 否 --> C[令牌化 / 保险库 / HSM] B -- 是 --> D{有密钥可用?} D -- 是 --> E[HMAC + pepper] D -- 否 --> F[Argon2id / scrypt + 盐] style C stroke:#10B981,stroke-width:2px style E stroke:#10B981,stroke-width:2px style F stroke:#10B981,stroke-width:2px

卡片之外的启示 #

这条原则适用于一切熵受限的定长标识符:国民身份证号、电话号码、出生日期,甚至是生成不佳的 API 密钥。如果输入空间很小,哈希函数的速度就是你的敌人,而"合规"绝不是"安全"的同义词。

担心你目前保护 PAN 或其他标识符的方式? 欢迎联系我们做一个直接的可行性判断。通过 LINE(@PureSecurity)或电子邮件(hello@puresecurity.com)联系我。

我们的 API 与应用安全审查 会检视你的代码实际如何存储和传输敏感值,并且我们会直截了当地告诉你:哪里通过了检查表,却仍在暴露真实数据。