本节摘要:对称加密用同一把密钥加密与解密,快但面临密钥分发难题;非对称加密用公钥加密、私钥解密,解决了分发问题但慢;哈希是单向压缩,用于完整性校验与口令存储,根本不是加密。本节鉴定三种原语的能力边界、典型误用与正确组合方式。承接 4.2 节的权限视角,本节下沉到密码学底座,是 4.4 节签名与证书的前置。
产品评审会上听到"这里记得加密一下",鉴定所的标准动作是追问四句:拿什么加密(对称还是非对称)?密钥放哪(分发与保管方案)?是要保密还是要校验(选加密还是选哈希)?要不要防抵赖(要不要签名)?四问过后的方案才算有轮廓。日常事故里最典型的三种错配:把口令"MD5 一下"当成加密(MD5 是哈希,且是已被攻破的哈希);用对称密钥硬扛密钥分发(密钥和密文走同一条不安全信道);以为加密能防篡改(加密只管看不懂,不管改没改)。
本节的任务就是把三种原语的能力边界钉死。先给结论表:
| 原语 | 输入输出 | 解决什么 | 不解决什么 | 典型算法 |
|---|---|---|---|---|
| 对称加密 | 密钥加密,同一密钥解密 | 大批量数据的保密 | 密钥分发、防篡改、防抵赖 | AES、ChaCha20 |
| 非对称加密 | 公钥加密,私钥解密 | 不安全信道的密钥交换 | 大数据量加密(慢) | RSA、ECC |
| 哈希 | 任意输入,定长摘要 | 完整性校验、口令存储 | 保密(不可逆也无密钥)、防抵赖 | SHA-256、bcrypt |
对称加密的逻辑是"同一把钥匙锁门开门"。它快——快到可以加密整块硬盘、全量数据库备份、每秒 GB 级的流量。它的死穴只有一个但致命:双方得先拿到同一把密钥。让密钥安全地到达对方手里,难度不亚于把保险柜本身安全地寄过去——这就是密钥分发难题。
非对称加密的破局思路是把钥匙拆成两半:公钥可以随便发(贴公告栏都行),私钥自己独存。任何人用你的公钥加密,只有你的私钥能解。分发难题就此瓦解——公钥不怕被看见,怕的是被调包(怎么确认公告栏上那把"公钥"真是你的?这个悬念留给 4.4 节的证书解决)。
非对称的代价是慢(比对称慢几个数量级),所以现实方案从来不是二选一,而是混合体制:用非对称解决"钥匙怎么送",用对称解决"数据怎么加密"。5.2 节的 TLS 握手就是标准样板——握手阶段用非对称协商出会话密钥,随后的海量数据全用对称加密跑。记住这个组合公式:非对称管会面,对称管运输。
一次 openssl 会话演示对称加密的实际操作与失败形态:
$ openssl enc -aes-256-cbc -salt -in 备份.tar -out 备份.tar.enc -k '我的口令' $ openssl enc -d -aes-256-cbc -in 备份.tar.enc -k '我的口令' | tar -t | head -3 etc/passwd etc/hosts usr/local/app/config.yml # 解密成功, 内容完整可读 # 事故现场: 口令错一个字 $ openssl enc -d -aes-256-cbc -in 备份.tar.enc -k '我的口令 ' | tar -t bad decrypt # 密钥不对, 得到的只有噪声
最后那个"空格口令"的例子值得放进运维教材:密钥材料差一个字节,结果全盘皆输。密钥管理的严肃性不在长度,在任何环节都不引入人为随意性。
哈希函数把任意输入压成定长摘要,单向、无密钥。它的三个特性决定了三种用途:确定性(同输入必同输出)支撑文件校验;雪崩效应(输入差一字,输出面目全非)支撑篡改检测;单向性(从摘要推不回原文)支撑口令存储。
口令存储的演进史是哈希误用的教科书。直接存明文(事故);MD5/SHA-256 直接哈希(攻击者拿彩虹表反查,等于半明文);加盐哈希(挡住彩虹表);慢哈希(bcrypt、Argon2 专门把单次计算拖到几十毫秒,让暴力猜测的成本膨胀百万倍)。正确姿势的唯一标准:慢、加盐、内存难(抗专用芯片)。1.1 节那个"哈希只答变没变"的定性,本节补全为:哈希答的是"输入是否一致",而保密问题它一概不问。
口令存储方案演进(按被攻破难度排序): 明文存储 出事即全灭 MD5(password) 彩虹表秒破 SHA-256(password) GPU 每秒数十亿次, 暴力可行 SHA-256(salt+password) 挡彩虹表, 挡不住暴力 bcrypt(cost=12) 单次几十毫秒, 暴力成本百万倍化 ← 当前合理水位
算法选择只认白名单。 加密选 AES-256-GCM 或 ChaCha20(GCM 这类认证加密模式顺带解决防篡改),哈希选 SHA-256 以上或口令专用慢哈希。MD5、SHA-1、DES、RC4 见到即要求替换计划——它们不是"不够好",是"已破"。
密钥管理优先于算法选择。 用 AES-256 配一把写在代码注释里的密钥,安全性为零。密钥的生成(真随机)、轮换(定期换)、保管(密钥管理服务或专用硬件)比算法名头重要得多。4.4 节的 PKI 本质上就是一套公钥侧的密钥管理体系。
⚠️ 常见坑:自己发明加密方案或"改进"现有模式。密码学工程的铁律是只用经过公开检验的标准组合,任何自创的"双重加密""简化流程"几乎必然引入协议级缺陷。这条不是保守,是行业数十年事故换来的共识。
💡 关键直觉:遇到任何"加密方案",先问三个问题——密钥从哪来到哪去(分发)、密钥存在哪(保管)、丢了怎么换(轮换)。三问答得出,方案是活的;答不出,方案是展示品。
本节正文给了能力边界,这里把常见误用收成一张对照表,评审与整改都能直接引用:
| 场景 | 错误用法 | 正确用法 |
|---|---|---|
| 用户口令存储 | MD5 或 SHA-256 直接哈希 | bcrypt/Argon2 加盐慢哈希 |
| 配置文件里的数据库口令 | 明文或 Base64"加密" | 密钥管理服务托管,启动注入 |
| 接口防篡改 | 只加密不签名(改了也解得开) | 认证加密模式或附加签名 |
| 文件下载完整性 | 告知用户"我们保证没改" | 公布哈希或签名供校验 |
| 两系统间数据同步 | 自创"异或加Base64"算法 | 标准 TLS 通道加应用层签名 |
| 会话令牌 | 用哈希当"不可猜"令牌 | 密码学随机数生成,足够长 |
表里最后一行藏着个经典误区:哈希的"不可逆"常被误当成"不可猜"。攻击者不需要逆推令牌,只需要猜测——如果令牌是时间戳加用户名的哈希,可猜空间小到秒破。不可猜性来自生成时的随机熵,与哈希函数无关。这类混淆的共同根源是本节反复强调的那句话:先分清要保密、要校验还是要防抵赖,再选原语;选错了原语,算法再新也是错的。
一个给运维的收尾提醒:密钥轮换要有"换钥不停机"的预案——双密钥并行期(新旧同时可解、只写新钥)、灰度切换、旧钥吊销,三步走完才算轮换完成。把轮换做成停机事件的团队,下一次轮换会被无限期推迟,密钥一用五年,安全性与可用性两头受损。