2. 支付 SDK 的持卡人数据识别:数据要素、存储位置、传输路径
2.1 合规要求拆解
PCI DSS 将持卡人数据严格区分为两类:持卡人数据要素(Cardholder Data, CHD)与敏感认证数据(Sensitive Authentication Data, SAD)。支付 SDK 在集成时必须从合规视角逐一识别、定位并管控这些数据,否则将面临高额罚款、断链甚至吊销支付牌照的风险。
| PCI DSS 要求编号 | 核心条款 | 对支付 SDK 的约束 |
|---|---|---|
| Req 3.2 | 禁止存储敏感认证数据(SAD) | SDK 不得在内存、日志、数据库、缓存中持久化或暂存 CVV2/PIN/磁条数据 |
| Req 3.3 | 屏蔽 PAN(展示时仅显示前六后四) | SDK 界面、日志、调试输出中必须对 PAN 做截断或脱敏 |
| Req 3.4 | 存储的 PAN 必须加密或使用不可逆哈希 | SDK 若缓存 PAN(如重试队列),必须使用 AES-256 或更强算法 |
| Req 4.2 | 持卡人数据在公共网络传输必须使用强加密(TLS 1.2+) | SDK 与收单机构间、SDK 与商户 App 间的通信链路必须满足 TLS 要求 |
合规证据要点:支付 SDK 需要提供一份《持卡人数据分类清单》,明确每个字段是否属于 CHD / SAD,并注明存储位置、保留期限、加密方式。该清单是 QSA(授权安全评估机构)现场审查的第一核对物。
2.2 持卡人数据要素识别
支付 SDK 在交易全生命周期中可能接触以下数据字段。必须按 PCI DSS 标准逐一标记,并建立数据要素台账。
| 数据字段 | CHD | SAD | PCI DSS 存储限制 | SDK 中是否出现 | 合规处置要求 |
|---|---|---|---|---|---|
| 主账号(PAN) | ✓ | ✗ | 存储须加密、展示须屏蔽 | 是 | 加密存储,日志脱敏 |
| 持卡人姓名 | ✓ | ✗ | 允许存储 | 是 | 无特殊加密要求,但需控制访问权限 |
| 服务代码 | ✓ | ✗ | 允许存储 | 是 | 与 PAN 一起加密 |
| 有效期 | ✓ | ✗ | 允许存储 | 是 | 与 PAN 一起加密 |
| CVV2 / CVC2 | ✗ | ✓ | 禁止存储 | 否(应屏蔽) | SDK 必须确保不在任何位置持久化 |
| PIN / 离线 PIN | ✗ | ✓ | 禁止存储 | 否 | 仅通过硬件加密键盘传递,SDK 不可获取明文 |
| 磁条数据(轨道 1/2/3) | ✗ | ✓ | 禁止存储 | 否 | SDK 不得读取或缓存磁条原始数据 |
| CAV2 / CVC2 令牌 | — | — | 允许存储(如符合 tokenization 标准) | 是 | 须通过 PCI 认证的令牌系统生成 |
实操提醒:许多 SDK 在调试日志中无意记录了完整 PAN 或 CVV2,这直接违反 Req 3.2 和 Req 3.3。建议在 SDK 构建脚本中增加编译期注解或静态代码扫描规则,自动拦截 log 方法中出现的 pan / cvv 关键字。
2.3 存储位置与风险识别
支付 SDK 在运行过程中会将持卡人数据暂存于不同介质。必须建立存储位置台账,逐一评估风险等级并实施管控。
| 存储位置 | 持卡人数据风险 | PCI DSS 合规要求 | 审计检查方法 | 证据类型 |
|---|---|---|---|---|
| 应用堆内存 / 栈内存 | 高 | 使用后立即清零(Zeroize) | 内存快照分析、代码审查 | 内存清零函数调用记录 |
| 日志文件(Logcat / 日志系统) | 极高 | 禁止输出完整 PAN 及任何 SAD | 日志内容扫描工具 | 日志脱敏策略配置 + 扫描报告 |
| 本地数据库(SQLite / SharedPreferences) | 中 | PAN 必须加密存储(AES-256) | 数据库文件加密验证 | 加密字段 Schema + 加密算法证书 |
| 系统缓存(剪贴板 / 图片缓存) | 中 | 禁止缓存 SAD;PAN 缓存须加密 | 缓存目录遍历检查 | 缓存策略设计文档 |
| 临时文件(TMP / 下载目录) | 高 | 禁止明文写入;使用后立即删除 | 文件系统监控 | 临时文件清理脚本 + 审计日志 |
常见违规场景:开发阶段在 onSaveInstanceState() 中持久化 PAN;使用 Log.d() 打印卡号用于调试;将 PAN 作为图片水印写入缓存。这些行为在 QSA 审计中会被直接判定为 “不符合”,需立即整改。
2.4 传输路径分析
持卡人数据在支付 SDK 内部及外部通信中会经过多条传输路径。必须绘制数据流拓扑图,并对每条路径实施加密与访问控制。
| 传输路径 | 通信方式 | 传输的数据 | 加密要求 | 审计证据 |
|---|---|---|---|---|
| 商户 App → SDK 接口 | Binder / AIDL / JNI | PAN、有效期、CVV2 | 进程间通信须使用 TLS 或加密管道 | IPC 加密策略文档 + 代码审计 |
| SDK 内部模块间 | 函数调用 / 消息队列 | PAN、令牌 | 内存中避免明文传递;使用安全缓冲区 | 内部数据流设计文档 |
| SDK → 收单机构网关 | HTTPS / REST | PAN、加密令牌 | TLS 1.2+,证书链验证 | SSL/TLS 配置截图 + 证书有效性报告 |
| SDK → 日志 / 分析服务 | HTTPS | 脱敏后的统计信息 | 不允许包含完整 CHD 或 SAD | 日志发送策略配置 + 数据采样样本 |
TLS 合规配置示例(证据材料):
{
"transport_security": {
"protocol": "TLSv1.2",
"min_version": "1.2",
"cipher_suites": [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
],
"certificate_pinning": true,
"verify_hostname": true,
"session_resumption": false
},
"logging": {
"mask_pan": true,
"mask_cvv": true,
"output_level": "warn"
}
}
证据链关键证据:上述 JSON 配置文件应纳入 SDK 的合规交付件,并由安全团队签字确认。同时配合网络抓包(Wireshark/tcpdump)确认实际传输链路使用了指定加密套件,抓包文件作为补充证据归档。
2.5 材料清单与台账
为支撑审计检查,支付 SDK 项目必须维护以下合规材料清单,并建立版本化的台账记录。
| 材料编号 | 材料名称 | 责任方 | 更新频率 | 保存期限 |
|---|---|---|---|---|
| MAT-02-01 | 持卡人数据分类清单 | 安全工程团队 | 每次数据接口变更 | ≥审计周期 |
| MAT-02-02 | 存储位置台账 | 运维 + 开发 | 每月 | ≥12 个月 |
| MAT-02-03 | 传输路径拓扑图 | 架构师 | 每季度 | ≥2 个审计周期 |
| MAT-02-04 | 日志脱敏策略配置 | DevOps | 每次发布前 | 随版本存档 |
| MAT-02-05 | 加密算法与密钥管理方案 | 安全工程团队 | 年度 / 加密算法变更 | ≥5 年 |
| MAT-02-06 | 静态代码扫描报告(数据泄露专项) | QA | 每次 CI 构建 | ≥6 个月 |
2.6 证据链与审计检查
QSA 在审查支付 SDK 时,会围绕“识别 → 定位 → 管控 → 验证”四阶段索取证据。以下是最常见的审计检查点及对应的证据链设计。
| 审计阶段 | 检查点 | QSA 提问示例 | 必需证据 |
|---|---|---|---|
| 识别 | 数据分类是否完整 | “请出示 SDK 涉及的所有持卡人数据字段清单” | MAT-02-01 签字版 |
| 存储 | 所有存储位置是否已标记 | “PAN 在 SDK 中存储在哪些位置?如何加密?” | MAT-02-02 + 加密方案文档 |
| 传输 | 传输路径是否全覆盖 | “SDK 与收单机构之间使用什么协议?” | MAT-02-03 + TLS 配置截图 |
| 日志 | 日志是否包含 CHD/SAD | “请提供最近一周的日志样本用于审查” | 日志脱敏策略 + 扫描工具报告 |
| 清零 | 内存使用后是否清零 | “请展示 PAN 使用完毕后内存清零的代码路径” | 代码审查记录 + 单元测试 |
构建证据链的技巧:每个审计检查点对应一个独立证据文件夹,命名规则为 EVIDENCE-02-<检查点编号>-<版本号>。例如 EVIDENCE-02-01-v2.3 存放第 2 章“持卡人数据分类清单”第 2.3 版的签字扫描件。文件夹内同时放入 README.md 说明证据生成时间、工具、责任人。
2.7 整改闭环
针对审计或自检中发现的数据识别、存储、传输问题,必须建立整改闭环跟踪表,确保每项风险可追踪、可验证、可复现。
| 风险编号 | 风险描述 | 发现来源 | 整改措施 | 验证方法 | 负责人 | 闭环日期 | 闭环证据 |
|---|---|---|---|---|---|---|---|
| RISK-02-01 | 日志输出完整 PAN | 代码扫描 | 增加日志脱敏过滤器,替换 Log.d() 为安全日志类 | 扫描工具复检通过 | 张三 | 2025-02-10 | 扫描报告 + MR 记录 |
| RISK-02-02 | CVV2 暂存在 SharedPreferences | 设计评审 | 移除 SAD 存储逻辑,改用内存临时变量并在使用后清零 | 代码审查 + 内存分析 | 李四 | 2025-02-14 | 代码 diff + 清零函数测试用例 |
| RISK-02-03 | TLS 配置未启用证书固定 | 安全测试 | 在 SDK 初始化配置中添加 certificate_pinning 证书哈希 | 中间人攻击测试 | 王五 | 2025-02-18 | 配置变更记录 + 渗透测试报告 |
日志脱敏整改代码示例(证据材料):
// SafeLogger.java —— 支付 SDK 安全日志工具
public class SafeLogger {
private static final String TAG = "PaymentSDK";
public static void d(String message) {
// 自动屏蔽 PAN 和 CVV2 模式
String safe = message
.replaceAll("\\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})\\b", "****PAN_MASKED****")
.replaceAll("\\b[0-9]{3,4}\\b(?=.*(?:cvv|cvc))", "***");
Log.d(TAG, safe);
}
public static void writeAuditLog(String event, String maskedPan) {
// 只记录脱敏后的 PAN(前六后四)
if (maskedPan != null && maskedPan.length() >= 10) {
String safePan = maskedPan.substring(0, 6) + "****" + maskedPan.substring(maskedPan.length() - 4);
Log.i(TAG, "audit:" + event + "|pan=" + safePan);
}
}
}
整改验证硬规则:所有整改措施必须经过“三重验证”——① 自动化测试通过;② 安全团队 Code Review 通过;③ QSA 或内部审计员抽样确认。缺少任意一环,该风险项不得标记为“已闭环”。