
这张图想表达:Encoding(编码)解决“表示/传输/兼容”,Encryption(加密)解决“保密”,Tokenization(令牌化)解决“把敏感数据替换成无敏感意义的占位符,并把映射关系集中管控”。下面按图逐块拆开讲,并顺便指出图里一个常见“误导点”。
1) Encoding(编码)——“换个写法”,不是“上锁”
图中上半部分:plain text → algorithm →(图里写 cipher text)→ decoding → plain text
本质:把数据从一种表示转换成另一种表示,方便存储/传输/解析/跨系统。
关键点
不以保密为目标:通常不需要密钥,别人知道规则就能还原。
可逆:encode/decode 成对出现(只要规则一致)。
输出不是“密文”:图里把编码结果画成“cipher text + 锁”,容易让人误以为编码=加密;正确理解是:编码结果只是另一种表示。
典型用例(图右侧)
ASCII / UTF-8:字符到字节的编码。
Base64:把二进制变成可打印字符,便于放进 JSON/URL/邮件;Base64 绝不是加密。
Protocol Buffers(Protobuf):结构化数据的二进制序列化格式(更紧凑、跨语言)。
2) Encryption(加密)——“上锁”,需要密钥,目标是保密(以及完整性)
图中中间部分:plain text → algorithm + key → cipher text;cipher text → algorithm + key → plain text
本质:在攻击者可见数据的情况下,也尽量让其无法读懂内容。
关键点
必须有密钥:没有密钥就不能还原(理想情况下)。
两大类
对称加密:同一把密钥加/解(AES-GCM、ChaCha20-Poly1305),速度快,适合大数据。
非对称加密:公钥加密、私钥解密;或用于签名(RSA/ECDSA/Ed25519)。现实系统里常用于“协商对称密钥/身份认证”,而不是直接加密大文件。
别只谈“保密”:工程上更常用 AEAD(如 AES-GCM),同时保证机密性 + 完整性(防篡改)。
典型用例(图右侧)
HTTPS/TLS:传输加密 + 身份认证(证书)+ 完整性。
Email encryption:如 S/MIME、PGP。
Blockchain wallet:私钥保护/签名(钱包更核心是“签名证明所有权”,不只是加密)。
3) Tokenization(令牌化)——“替换”,让业务系统不再持有敏感明文
图中下半部分:PAN(卡号)→ 请求 token → TSP/Token Vault → 返回 token;需要时 lookup token → 得到 PAN
本质:用一个无敏感含义的 token替代敏感数据(如 PAN 卡号、身份证号)。真正的敏感值放在Token Vault(令牌库/保险库)里集中保管。
关键点
token 本身不等于密文:它通常不包含可解出的原文信息(很多实现是随机值或受控格式)。
可逆方式是“查表/解令牌”:通过 Token Service(TSP 或自建)进行 detokenize/lookup,而不是“拿密钥解密”。
安全边界在 Vault:Vault 的权限、审计、隔离、HSM/密钥、网络分区,比 token 字符串本身更重要。
合规价值:让大多数系统只处理 token,从而缩小 PCI DSS 等合规范围(注意:是否“降范围”取决于架构和审计口径,但这是 tokenization 的核心动机之一)。
典型用例(图右侧)
信用卡令牌化(PAN→token):电商/支付场景常见(Visa/Mastercard 的网络令牌化、或支付机构自建)。
PCI DSS:减少存储/处理真实 PAN 的系统数量。
Financial Data Sharing:给合作方/内部系统发 token,而不是发真实敏感字段。
4) 三者怎么选?一张“工程决策表”
| 维度 | 编码 Encoding | 加密 Encryption | 令牌化 Tokenization |
|---|---|---|---|
| 目的 | 兼容/表示/传输/序列化 | 保密(+完整性) | 替换敏感数据、降低暴露面/合规范围 |
| 是否需要密钥 | 通常不需要 | 必须需要(或证书体系) | 通常不靠“解密”,而靠“Vault/服务权限” |
| 是否可逆 | 可逆(decode) | 可逆(decrypt,需密钥) | 可逆(detokenize,需访问 Vault/服务) |
| 攻击者拿到结果 | 轻松还原 | 理论上很难还原 | token 本身没意义,但若 Vault 被攻破则风险大 |
| 常见例子 | UTF-8、Base64、Protobuf、JSON | TLS、AES-GCM、PGP | PAN token、SSN token、内部 ID token |
5) 常见误区(这张图最容易引发的)
把编码当加密:Base64、Hex、URL 编码都不是保密措施。
把“token”当“密文”:tokenization 更像“受控映射 + 权限隔离”,不是纯密码学变换。
以为加密就能大幅降低合规范围:很多合规里“你还在存真实敏感数据(即便加密)= 仍在范围内”,而 tokenization 才是“让业务系统根本不碰敏感原文”的思路。
漏掉哈希(Hashing):密码存储通常用哈希(带盐、慢哈希如 bcrypt/Argon2),它既不是编码也不是可逆加密/令牌化。
我用一个常见的“Delphi 后端 + PostgreSQL + Redis + 对外 REST API”的业务栈,把 编码 / 加密 / 令牌化分别放到哪些位置、怎么组合、踩坑点一次讲透(偏工程实践)。
1) 一张“从入口到落库”的放置地图(该用谁就用谁)
A. API 层(HTTP/REST)
传输层:用加密(TLS/HTTPS)
目的:防窃听、防篡改、服务器身份认证(证书)。
结论:只要走公网,就默认 HTTPS;内部服务也最好 mTLS 或至少 TLS。
报文格式:用编码/序列化(JSON / Protobuf)
JSON/UTF-8:可读、通用
Protobuf:更省带宽、更快、强 schema
不要把 Base64 当安全
Base64 只用于“让二进制能塞进文本协议”,例如上传图片、签名字段。
B. 应用层(业务逻辑/日志/缓存)
日志:尽量只记录 token 或脱敏后的片段
例如卡号只留 ,或只留 token。
**** **** **** 1234
这是最常见的数据泄露入口之一(比数据库还常见)。
缓存/消息队列:优先放 token,不放敏感原文
Redis、MQ、任务队列都属于“扩散面”,敏感数据一放进去就很难彻底清理与审计。
C. 数据库层(持久化)
这里按数据类型分三类最清晰:
密码(Password)→ 用哈希(不是编码/加密/令牌化)
存:(不可逆)
Argon2id/bcrypt + salt
验证:重算哈希比对
绝对不要:Base64、AES 直接加密密码、MD5/SHA1 直哈希
需要“可读明文”的敏感字段(例如地址、身份证、私密备注)→ 用加密
典型:应用层字段加密(Field-level encryption),落库存密文
推荐:AEAD(AES-GCM / ChaCha20-Poly1305),一条记录一个随机 nonce/IV
索引/查询:会变麻烦(见第 4 节“查询难题”)
高敏感且频繁流转的数据(例如 PAN 卡号)→ 用令牌化
库里只存 token(以及少量元数据:last4、brand、exp_month)
真正 PAN 在 Token Vault/支付机构/PCI 隔离区
业务系统处理“支付”只用 token 调支付网关
2) 三种“经典组合方案”(你选其一就很稳)
方案 1:大多数普通业务系统(无支付卡号自存)
HTTPS(加密传输)
DB:密码哈希;其余敏感字段用加密(可选)
日志/缓存:脱敏
优点:实现成本低
缺点:一旦业务要存 PAN,会立即进入高压合规/隔离
方案 2:有支付,但 不碰 PAN(推荐)
支付:走 PSP(Stripe/Adyen 等)或网络令牌(Visa/Mastercard token)
你系统里:只存 payment_token + last4
优点:合规压力最小;数据面最干净
缺点:依赖外部 token 服务
方案 3:你必须存极敏感数据(被迫 PCI/金融内控)
建 Token Vault(独立服务+独立库+最小人员权限+强审计)
业务库只存 token
Vault 内部的敏感原文也可以再加密(双保险)
优点:爆炸半径可控
缺点:工程、运维、审计成本高
3) “令牌化”在系统里到底怎么落地(按你图里的 TSP/Vault)
令牌化服务(Token Service)通常提供:
Tokenize(plaintext) -> token
(权限极严)
Detokenize(token) -> plaintext
(权限可更宽)
GetMetadata(token) -> last4/类型/有效期
强烈建议:业务系统默认只有“metadata 权限”,没有 detokenize 权限。
真正需要明文的场景(比如与银行侧清算)放到隔离域里跑。
Vault 的关键不是“表结构”,而是:
网络隔离(只允许少数服务访问)
强鉴权(mTLS + service identity + RBAC)
审计(谁在何时 detokenize 了什么)
HSM/密钥托管(如果 Vault 内还有加密)
4) 字段加密最难的点:怎么查询/排序/去重?(避坑指南)
你一旦把 加密存库,会遇到:
email/phone/idno
无法 where = ?(因为密文每次都不同:随机 IV/nonce)
无法做 LIKE 模糊查询
无法索引排序/范围查询
常见工程解法(按安全性从强到弱):
分层:明文不落库 + token 化(最推荐)
“加密字段 + 额外存一个哈希索引列”(常用折中)
存 AES-GCM 密文
email_ciphertext
存
email_hash
HMAC-SHA256(normalized_email, server_secret)
查询用 命中后再解密校验
email_hash = HMAC(...)
注意:不要用普通 SHA256(email) 这种容易被字典/撞库推断
确定性加密(Deterministic Encryption)(不太推荐)
好处:可等值查询/索引
坏处:相同明文→相同密文,泄露统计特征,风险更高
5) Delphi 落地要点(不写长代码也能把思路讲清)
加密库选择
Windows 上别自己“拼 AES + padding + MAC”,优先用成熟实现:
OpenSSL(你本来就很熟悉生态)
或 Windows CNG/BCrypt(系统自带,维护成本低)
AEAD 模式必备字段
ciphertext
nonce/iv
(如果库把 tag 单独给你)
tag
(可选,用来绑定记录上下文,如 user_id、version,防剪切粘贴攻击)
aad
密钥管理
密钥不要写死在 exe;至少环境变量/配置中心/密钥文件权限隔离
轮换:加密数据要带 /
key_id,便于逐步重加密
version
6) 一句话总结(你做架构决策时的“口诀”)
Encoding:为了“能传、能存、能互通”
Encryption:为了“别人拿到也看不懂(还难改)”
Tokenization:为了“业务系统压根就别碰敏感原文,把风险关进 Vault”





![[C++探索之旅] 第一部分第十一课:小练习,猜单词 - 鹿快](https://img.lukuai.com/blogimg/20251015/da217e2245754101b3d2ef80869e9de2.jpg)










暂无评论内容