一篇讲清楚加密、签名、证书和 SSH 密钥
平时听到 AES、RSA、SHA-256、HMAC、ECDSA、Ed25519、HTTPS、CA 证书、SSH key,很容易觉得它们都在"加密"。其实它们解决的问题并不一样。
最好的理解方式不是背算法名,而是先问:它到底在解决什么问题?
- 想让别人看不懂内容:加密。
- 想知道内容有没有被改:哈希、MAC、AEAD。
- 想证明是谁发的:数字签名、证书、公钥认证。
- 想安全地产生会话密钥:密钥交换、密钥派生。
- 想让浏览器相信某个公钥属于某个域名:CA 和证书链。
下面按这个思路,把常见名词放到一张地图里。
1. 总览:这些名词分别管什么
#mermaid-svg-57wsagRKDSCHt39V{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-57wsagRKDSCHt39V .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-57wsagRKDSCHt39V .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-57wsagRKDSCHt39V .error-icon{fill:#552222;}#mermaid-svg-57wsagRKDSCHt39V .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-57wsagRKDSCHt39V .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-57wsagRKDSCHt39V .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-57wsagRKDSCHt39V .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-57wsagRKDSCHt39V .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-57wsagRKDSCHt39V .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-57wsagRKDSCHt39V .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-57wsagRKDSCHt39V .marker{fill:#333333;stroke:#333333;}#mermaid-svg-57wsagRKDSCHt39V .marker.cross{stroke:#333333;}#mermaid-svg-57wsagRKDSCHt39V svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-57wsagRKDSCHt39V p{margin:0;}#mermaid-svg-57wsagRKDSCHt39V .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-57wsagRKDSCHt39V .cluster-label text{fill:#333;}#mermaid-svg-57wsagRKDSCHt39V .cluster-label span{color:#333;}#mermaid-svg-57wsagRKDSCHt39V .cluster-label span p{background-color:transparent;}#mermaid-svg-57wsagRKDSCHt39V .label text,#mermaid-svg-57wsagRKDSCHt39V span{fill:#333;color:#333;}#mermaid-svg-57wsagRKDSCHt39V .node rect,#mermaid-svg-57wsagRKDSCHt39V .node circle,#mermaid-svg-57wsagRKDSCHt39V .node ellipse,#mermaid-svg-57wsagRKDSCHt39V .node polygon,#mermaid-svg-57wsagRKDSCHt39V .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-57wsagRKDSCHt39V .rough-node .label text,#mermaid-svg-57wsagRKDSCHt39V .node .label text,#mermaid-svg-57wsagRKDSCHt39V .image-shape .label,#mermaid-svg-57wsagRKDSCHt39V .icon-shape .label{text-anchor:middle;}#mermaid-svg-57wsagRKDSCHt39V .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-57wsagRKDSCHt39V .rough-node .label,#mermaid-svg-57wsagRKDSCHt39V .node .label,#mermaid-svg-57wsagRKDSCHt39V .image-shape .label,#mermaid-svg-57wsagRKDSCHt39V .icon-shape .label{text-align:center;}#mermaid-svg-57wsagRKDSCHt39V .node.clickable{cursor:pointer;}#mermaid-svg-57wsagRKDSCHt39V .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-57wsagRKDSCHt39V .arrowheadPath{fill:#333333;}#mermaid-svg-57wsagRKDSCHt39V .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-57wsagRKDSCHt39V .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-57wsagRKDSCHt39V .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-57wsagRKDSCHt39V .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-57wsagRKDSCHt39V .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-57wsagRKDSCHt39V .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-57wsagRKDSCHt39V .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-57wsagRKDSCHt39V .cluster text{fill:#333;}#mermaid-svg-57wsagRKDSCHt39V .cluster span{color:#333;}#mermaid-svg-57wsagRKDSCHt39V div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-57wsagRKDSCHt39V .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-57wsagRKDSCHt39V rect.text{fill:none;stroke-width:0;}#mermaid-svg-57wsagRKDSCHt39V .icon-shape,#mermaid-svg-57wsagRKDSCHt39V .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-57wsagRKDSCHt39V .icon-shape p,#mermaid-svg-57wsagRKDSCHt39V .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-57wsagRKDSCHt39V .icon-shape .label rect,#mermaid-svg-57wsagRKDSCHt39V .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-57wsagRKDSCHt39V .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-57wsagRKDSCHt39V .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-57wsagRKDSCHt39V :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 密码学工具箱
保密性
完整性
身份认证
对称加密
AES, ChaCha20
非对称加密
RSA-OAEP 等
哈希摘要
SHA-256, SHA-512, SHA-3
消息认证码
HMAC, Poly1305
AEAD
AES-GCM, ChaCha20-Poly1305
数字签名
RSA-PSS, ECDSA, Ed25519
证书体系
X.509, CA, 证书链
SSH 公钥认证
authorized_keys, known_hosts
#mermaid-svg-IYwwXJtlvQLkUP4d{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IYwwXJtlvQLkUP4d .error-icon{fill:#552222;}#mermaid-svg-IYwwXJtlvQLkUP4d .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IYwwXJtlvQLkUP4d .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IYwwXJtlvQLkUP4d .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IYwwXJtlvQLkUP4d .marker.cross{stroke:#333333;}#mermaid-svg-IYwwXJtlvQLkUP4d svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IYwwXJtlvQLkUP4d p{margin:0;}#mermaid-svg-IYwwXJtlvQLkUP4d .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IYwwXJtlvQLkUP4d .cluster-label text{fill:#333;}#mermaid-svg-IYwwXJtlvQLkUP4d .cluster-label span{color:#333;}#mermaid-svg-IYwwXJtlvQLkUP4d .cluster-label span p{background-color:transparent;}#mermaid-svg-IYwwXJtlvQLkUP4d .label text,#mermaid-svg-IYwwXJtlvQLkUP4d span{fill:#333;color:#333;}#mermaid-svg-IYwwXJtlvQLkUP4d .node rect,#mermaid-svg-IYwwXJtlvQLkUP4d .node circle,#mermaid-svg-IYwwXJtlvQLkUP4d .node ellipse,#mermaid-svg-IYwwXJtlvQLkUP4d .node polygon,#mermaid-svg-IYwwXJtlvQLkUP4d .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IYwwXJtlvQLkUP4d .rough-node .label text,#mermaid-svg-IYwwXJtlvQLkUP4d .node .label text,#mermaid-svg-IYwwXJtlvQLkUP4d .image-shape .label,#mermaid-svg-IYwwXJtlvQLkUP4d .icon-shape .label{text-anchor:middle;}#mermaid-svg-IYwwXJtlvQLkUP4d .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IYwwXJtlvQLkUP4d .rough-node .label,#mermaid-svg-IYwwXJtlvQLkUP4d .node .label,#mermaid-svg-IYwwXJtlvQLkUP4d .image-shape .label,#mermaid-svg-IYwwXJtlvQLkUP4d .icon-shape .label{text-align:center;}#mermaid-svg-IYwwXJtlvQLkUP4d .node.clickable{cursor:pointer;}#mermaid-svg-IYwwXJtlvQLkUP4d .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IYwwXJtlvQLkUP4d .arrowheadPath{fill:#333333;}#mermaid-svg-IYwwXJtlvQLkUP4d .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IYwwXJtlvQLkUP4d .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IYwwXJtlvQLkUP4d .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IYwwXJtlvQLkUP4d .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IYwwXJtlvQLkUP4d .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IYwwXJtlvQLkUP4d .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IYwwXJtlvQLkUP4d .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IYwwXJtlvQLkUP4d .cluster text{fill:#333;}#mermaid-svg-IYwwXJtlvQLkUP4d .cluster span{color:#333;}#mermaid-svg-IYwwXJtlvQLkUP4d div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IYwwXJtlvQLkUP4d .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IYwwXJtlvQLkUP4d rect.text{fill:none;stroke-width:0;}#mermaid-svg-IYwwXJtlvQLkUP4d .icon-shape,#mermaid-svg-IYwwXJtlvQLkUP4d .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IYwwXJtlvQLkUP4d .icon-shape p,#mermaid-svg-IYwwXJtlvQLkUP4d .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IYwwXJtlvQLkUP4d .icon-shape .label rect,#mermaid-svg-IYwwXJtlvQLkUP4d .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IYwwXJtlvQLkUP4d .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IYwwXJtlvQLkUP4d .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IYwwXJtlvQLkUP4d :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 密码学工具箱
密钥协商与派生
编码与封装
密钥交换
DH, ECDH, X25519
密钥派生
HKDF, Argon2id, bcrypt
编码
Base64, Hex
文件格式
PEM, DER, PKCS#12, OpenSSH key
| 类别 | 解决的问题 | 常见算法/名词 | 典型场景 |
|---|---|---|---|
| 对称加密 | 用同一把密钥加密和解密 | AES、ChaCha20 | HTTPS 数据传输、磁盘加密、文件加密 |
| 非对称密码体系 | 公钥和私钥成对使用 | RSA、ECC、X25519、Ed25519 | TLS 握手、签名、密钥交换、证书 |
| 哈希摘要 | 给数据生成固定长度指纹 | SHA-256、SHA-512、SHA-3、BLAKE2/3 | 文件校验、证书指纹、Git 对象 |
| 消息认证码 | 用共享密钥验证消息完整性和来源 | HMAC、Poly1305、CMAC | API 签名、Webhook 签名、Cookie 防篡改 |
| 数字签名 | 私钥签名,公钥验证 | RSA-PSS、ECDSA、Ed25519 | Git 签名、软件包签名、SSH 登录、证书签发 |
| 密钥交换 | 双方协商出共享秘密,但不直接传输密钥 | DH、ECDH、X25519 | HTTPS/TLS、端到端加密 |
| 密钥派生 | 从密码或共享秘密派生安全密钥 | HKDF、PBKDF2、bcrypt、scrypt、Argon2id | TLS 会话密钥、密码存储 |
| 编码/封装 | 数据表示格式,本身不提供安全性 | Base64、Hex、PEM、DER | 证书、密钥文件、JWT、SSH key |
2. 加密:解决"别人看不懂"
加密关注的是保密性。没有密钥的人即使拿到密文,也不应该知道明文。
对称加密
对称加密是同一把密钥负责加密和解密。
#mermaid-svg-QV17RShlXYBqg4ih{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QV17RShlXYBqg4ih .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QV17RShlXYBqg4ih .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QV17RShlXYBqg4ih .error-icon{fill:#552222;}#mermaid-svg-QV17RShlXYBqg4ih .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QV17RShlXYBqg4ih .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QV17RShlXYBqg4ih .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QV17RShlXYBqg4ih .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QV17RShlXYBqg4ih .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QV17RShlXYBqg4ih .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QV17RShlXYBqg4ih .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QV17RShlXYBqg4ih .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QV17RShlXYBqg4ih .marker.cross{stroke:#333333;}#mermaid-svg-QV17RShlXYBqg4ih svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QV17RShlXYBqg4ih p{margin:0;}#mermaid-svg-QV17RShlXYBqg4ih .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QV17RShlXYBqg4ih .cluster-label text{fill:#333;}#mermaid-svg-QV17RShlXYBqg4ih .cluster-label span{color:#333;}#mermaid-svg-QV17RShlXYBqg4ih .cluster-label span p{background-color:transparent;}#mermaid-svg-QV17RShlXYBqg4ih .label text,#mermaid-svg-QV17RShlXYBqg4ih span{fill:#333;color:#333;}#mermaid-svg-QV17RShlXYBqg4ih .node rect,#mermaid-svg-QV17RShlXYBqg4ih .node circle,#mermaid-svg-QV17RShlXYBqg4ih .node ellipse,#mermaid-svg-QV17RShlXYBqg4ih .node polygon,#mermaid-svg-QV17RShlXYBqg4ih .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QV17RShlXYBqg4ih .rough-node .label text,#mermaid-svg-QV17RShlXYBqg4ih .node .label text,#mermaid-svg-QV17RShlXYBqg4ih .image-shape .label,#mermaid-svg-QV17RShlXYBqg4ih .icon-shape .label{text-anchor:middle;}#mermaid-svg-QV17RShlXYBqg4ih .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QV17RShlXYBqg4ih .rough-node .label,#mermaid-svg-QV17RShlXYBqg4ih .node .label,#mermaid-svg-QV17RShlXYBqg4ih .image-shape .label,#mermaid-svg-QV17RShlXYBqg4ih .icon-shape .label{text-align:center;}#mermaid-svg-QV17RShlXYBqg4ih .node.clickable{cursor:pointer;}#mermaid-svg-QV17RShlXYBqg4ih .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QV17RShlXYBqg4ih .arrowheadPath{fill:#333333;}#mermaid-svg-QV17RShlXYBqg4ih .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QV17RShlXYBqg4ih .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QV17RShlXYBqg4ih .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QV17RShlXYBqg4ih .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QV17RShlXYBqg4ih .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QV17RShlXYBqg4ih .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QV17RShlXYBqg4ih .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QV17RShlXYBqg4ih .cluster text{fill:#333;}#mermaid-svg-QV17RShlXYBqg4ih .cluster span{color:#333;}#mermaid-svg-QV17RShlXYBqg4ih div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QV17RShlXYBqg4ih .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QV17RShlXYBqg4ih rect.text{fill:none;stroke-width:0;}#mermaid-svg-QV17RShlXYBqg4ih .icon-shape,#mermaid-svg-QV17RShlXYBqg4ih .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QV17RShlXYBqg4ih .icon-shape p,#mermaid-svg-QV17RShlXYBqg4ih .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QV17RShlXYBqg4ih .icon-shape .label rect,#mermaid-svg-QV17RShlXYBqg4ih .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QV17RShlXYBqg4ih .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QV17RShlXYBqg4ih .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QV17RShlXYBqg4ih :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 明文
用同一把密钥加密
密文
用同一把密钥解密
明文
常见算法:
| 算法 | 状态 | 说明 |
|---|---|---|
| AES | 推荐 | 最常见的对称加密标准,常见密钥长度 128/192/256 bit |
| ChaCha20 | 推荐 | 软件实现性能好,移动端和无 AES 硬件加速环境常见 |
| 3DES | 不推荐新系统 | 老算法,性能和安全边际都不理想 |
| DES | 禁用 | 密钥太短,已经不安全 |
| RC4 | 禁用 | 存在严重缺陷 |
对称加密适合加密大量数据,因为速度快。HTTPS 真正传输网页内容时,用的也是对称加密算法,而不是一直用 RSA 之类的非对称算法加密所有数据。
分组模式和 AEAD
实际使用时,很少只说"我用了 AES"就够了。AES 更像一个底层加密积木,真正落地时还要回答:
- 数据比一个分组长怎么办?
- 每次加密相同内容会不会得到相同密文?
- 密文被人改了,接收方能不能发现?
这就需要"模式"。
AES 是分组加密算法,每次只处理固定大小的数据块。模式负责把 AES 这个底层算法组织起来,用来加密任意长度的数据。
可以粗略理解成:
text
AES:底层加密算法
GCM/CBC/CTR/ECB:使用 AES 的方式
AES-GCM:AES + GCM 模式
实际使用时,优先关注 AEAD 这类方案。
推荐优先使用:
- AES-GCM
- ChaCha20-Poly1305
它们都属于 AEAD,也就是 Authenticated Encryption with Associated Data,带认证的加密。
AEAD 通常属于对称加密方案:发送方和接收方使用同一把会话密钥完成加密、解密和完整性验证。它解决的是"拿到密钥后怎么安全传数据",不解决"密钥最初怎么安全给到双方"。在 TLS/HTTPS 里,这把会话密钥通常先通过 ECDHE/X25519 这类密钥交换协商出来。
AEAD 可以理解为"加密 + 防篡改"打包好的方案。它不只是把明文变成密文,还会生成一个认证标签 tag。解密时,如果密文、nonce、附加数据或 tag 任何一个对不上,就会验证失败,不应该输出明文。
AEAD 同时提供:
- 保密性:别人看不懂密文。
- 完整性:密文被改过会验证失败。
- 附加数据认证:一些不加密但需要防篡改的数据也能参与验证。
#mermaid-svg-N0pGBvbwrOP6FZqq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-N0pGBvbwrOP6FZqq .error-icon{fill:#552222;}#mermaid-svg-N0pGBvbwrOP6FZqq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-N0pGBvbwrOP6FZqq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-N0pGBvbwrOP6FZqq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-N0pGBvbwrOP6FZqq .marker.cross{stroke:#333333;}#mermaid-svg-N0pGBvbwrOP6FZqq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-N0pGBvbwrOP6FZqq p{margin:0;}#mermaid-svg-N0pGBvbwrOP6FZqq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-N0pGBvbwrOP6FZqq .cluster-label text{fill:#333;}#mermaid-svg-N0pGBvbwrOP6FZqq .cluster-label span{color:#333;}#mermaid-svg-N0pGBvbwrOP6FZqq .cluster-label span p{background-color:transparent;}#mermaid-svg-N0pGBvbwrOP6FZqq .label text,#mermaid-svg-N0pGBvbwrOP6FZqq span{fill:#333;color:#333;}#mermaid-svg-N0pGBvbwrOP6FZqq .node rect,#mermaid-svg-N0pGBvbwrOP6FZqq .node circle,#mermaid-svg-N0pGBvbwrOP6FZqq .node ellipse,#mermaid-svg-N0pGBvbwrOP6FZqq .node polygon,#mermaid-svg-N0pGBvbwrOP6FZqq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-N0pGBvbwrOP6FZqq .rough-node .label text,#mermaid-svg-N0pGBvbwrOP6FZqq .node .label text,#mermaid-svg-N0pGBvbwrOP6FZqq .image-shape .label,#mermaid-svg-N0pGBvbwrOP6FZqq .icon-shape .label{text-anchor:middle;}#mermaid-svg-N0pGBvbwrOP6FZqq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-N0pGBvbwrOP6FZqq .rough-node .label,#mermaid-svg-N0pGBvbwrOP6FZqq .node .label,#mermaid-svg-N0pGBvbwrOP6FZqq .image-shape .label,#mermaid-svg-N0pGBvbwrOP6FZqq .icon-shape .label{text-align:center;}#mermaid-svg-N0pGBvbwrOP6FZqq .node.clickable{cursor:pointer;}#mermaid-svg-N0pGBvbwrOP6FZqq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-N0pGBvbwrOP6FZqq .arrowheadPath{fill:#333333;}#mermaid-svg-N0pGBvbwrOP6FZqq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-N0pGBvbwrOP6FZqq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-N0pGBvbwrOP6FZqq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N0pGBvbwrOP6FZqq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-N0pGBvbwrOP6FZqq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N0pGBvbwrOP6FZqq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-N0pGBvbwrOP6FZqq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-N0pGBvbwrOP6FZqq .cluster text{fill:#333;}#mermaid-svg-N0pGBvbwrOP6FZqq .cluster span{color:#333;}#mermaid-svg-N0pGBvbwrOP6FZqq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-N0pGBvbwrOP6FZqq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-N0pGBvbwrOP6FZqq rect.text{fill:none;stroke-width:0;}#mermaid-svg-N0pGBvbwrOP6FZqq .icon-shape,#mermaid-svg-N0pGBvbwrOP6FZqq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N0pGBvbwrOP6FZqq .icon-shape p,#mermaid-svg-N0pGBvbwrOP6FZqq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-N0pGBvbwrOP6FZqq .icon-shape .label rect,#mermaid-svg-N0pGBvbwrOP6FZqq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N0pGBvbwrOP6FZqq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-N0pGBvbwrOP6FZqq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-N0pGBvbwrOP6FZqq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 密钥
AEAD 加密
nonce/IV
明文
附加数据
不加密但防篡改
密文
认证标签 tag
AEAD 解密并验证
验证通过才输出明文
谨慎使用:
- AES-CBC:需要正确处理 IV、padding、MAC,否则容易出问题。
- AES-CTR:必须保证 nonce/计数器不重复。
不要使用:
- AES-ECB:相同明文块会得到相同密文块,会泄露数据结构。
3. 哈希:解决"生成指纹"
哈希函数把任意长度的数据变成固定长度摘要。
#mermaid-svg-uUtjU3Q0gtjspF8n{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uUtjU3Q0gtjspF8n .error-icon{fill:#552222;}#mermaid-svg-uUtjU3Q0gtjspF8n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uUtjU3Q0gtjspF8n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uUtjU3Q0gtjspF8n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uUtjU3Q0gtjspF8n .marker.cross{stroke:#333333;}#mermaid-svg-uUtjU3Q0gtjspF8n svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uUtjU3Q0gtjspF8n p{margin:0;}#mermaid-svg-uUtjU3Q0gtjspF8n .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uUtjU3Q0gtjspF8n .cluster-label text{fill:#333;}#mermaid-svg-uUtjU3Q0gtjspF8n .cluster-label span{color:#333;}#mermaid-svg-uUtjU3Q0gtjspF8n .cluster-label span p{background-color:transparent;}#mermaid-svg-uUtjU3Q0gtjspF8n .label text,#mermaid-svg-uUtjU3Q0gtjspF8n span{fill:#333;color:#333;}#mermaid-svg-uUtjU3Q0gtjspF8n .node rect,#mermaid-svg-uUtjU3Q0gtjspF8n .node circle,#mermaid-svg-uUtjU3Q0gtjspF8n .node ellipse,#mermaid-svg-uUtjU3Q0gtjspF8n .node polygon,#mermaid-svg-uUtjU3Q0gtjspF8n .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uUtjU3Q0gtjspF8n .rough-node .label text,#mermaid-svg-uUtjU3Q0gtjspF8n .node .label text,#mermaid-svg-uUtjU3Q0gtjspF8n .image-shape .label,#mermaid-svg-uUtjU3Q0gtjspF8n .icon-shape .label{text-anchor:middle;}#mermaid-svg-uUtjU3Q0gtjspF8n .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uUtjU3Q0gtjspF8n .rough-node .label,#mermaid-svg-uUtjU3Q0gtjspF8n .node .label,#mermaid-svg-uUtjU3Q0gtjspF8n .image-shape .label,#mermaid-svg-uUtjU3Q0gtjspF8n .icon-shape .label{text-align:center;}#mermaid-svg-uUtjU3Q0gtjspF8n .node.clickable{cursor:pointer;}#mermaid-svg-uUtjU3Q0gtjspF8n .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uUtjU3Q0gtjspF8n .arrowheadPath{fill:#333333;}#mermaid-svg-uUtjU3Q0gtjspF8n .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uUtjU3Q0gtjspF8n .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uUtjU3Q0gtjspF8n .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uUtjU3Q0gtjspF8n .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uUtjU3Q0gtjspF8n .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uUtjU3Q0gtjspF8n .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uUtjU3Q0gtjspF8n .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uUtjU3Q0gtjspF8n .cluster text{fill:#333;}#mermaid-svg-uUtjU3Q0gtjspF8n .cluster span{color:#333;}#mermaid-svg-uUtjU3Q0gtjspF8n div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uUtjU3Q0gtjspF8n .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uUtjU3Q0gtjspF8n rect.text{fill:none;stroke-width:0;}#mermaid-svg-uUtjU3Q0gtjspF8n .icon-shape,#mermaid-svg-uUtjU3Q0gtjspF8n .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uUtjU3Q0gtjspF8n .icon-shape p,#mermaid-svg-uUtjU3Q0gtjspF8n .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uUtjU3Q0gtjspF8n .icon-shape .label rect,#mermaid-svg-uUtjU3Q0gtjspF8n .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uUtjU3Q0gtjspF8n .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uUtjU3Q0gtjspF8n .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uUtjU3Q0gtjspF8n :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 任意长度输入
文件、字符串、证书
哈希函数
固定长度摘要
例如 SHA-256
好的哈希函数应该具备:
- 单向性:很难从摘要反推出原文。
- 抗碰撞:很难找到两个不同输入得到相同摘要。
- 雪崩效应:输入变一点,输出大变。
常见算法:
| 算法 | 建议 |
|---|---|
| SHA-256 | 通用安全场景的常见默认选择 |
| SHA-512 | 输出更长,在 64 位平台上性能通常不错 |
| SHA-3 | 另一套标准化哈希设计 |
| BLAKE2/BLAKE3 | 现代高性能哈希,很多工程场景很好用 |
| MD5 | 不适合安全场景,只能用于非安全校验或兼容旧系统 |
| SHA-1 | 不适合安全签名和证书场景 |
哈希不是加密,因为它不能解密回原文。说"MD5 加密""SHA256 加密"通常是不严谨的。
4. HMAC:解决"消息来自共享密钥持有方,且没被改"
普通哈希只能说明数据摘要是什么,不能说明"是谁生成的"。HMAC 多了一把共享密钥。
#mermaid-svg-Z8dC7sp9Z0p7XzX3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .error-icon{fill:#552222;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .marker.cross{stroke:#333333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 p{margin:0;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .cluster-label text{fill:#333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .cluster-label span{color:#333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .cluster-label span p{background-color:transparent;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .label text,#mermaid-svg-Z8dC7sp9Z0p7XzX3 span{fill:#333;color:#333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node rect,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node circle,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node ellipse,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node polygon,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .rough-node .label text,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node .label text,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .image-shape .label,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .rough-node .label,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node .label,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .image-shape .label,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .icon-shape .label{text-align:center;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node.clickable{cursor:pointer;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .arrowheadPath{fill:#333333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .cluster text{fill:#333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .cluster span{color:#333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .icon-shape,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .icon-shape p,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .icon-shape .label rect,#mermaid-svg-Z8dC7sp9Z0p7XzX3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Z8dC7sp9Z0p7XzX3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
共享密钥 secret
HMAC-SHA256
消息 message
tag
接收方重新计算 HMAC
是否一致
来自共享密钥持有方
且未被篡改
拒绝
常见用途:
- API 请求签名。
- Webhook 签名。
- Cookie/session 防篡改。
- 内部服务调用鉴权。
注意:HMAC 不是数字签名。HMAC 的验证方也持有同一把 secret,所以验证方理论上也能伪造同样的 HMAC。它适合"双方共享秘密"的场景,不适合证明"只有某个私钥持有人签过"。
5. 数字签名:解决"谁签的、有没有被改"
数字签名是私钥签名,公钥验证。
#mermaid-svg-wNe561uQoiNz8hB3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wNe561uQoiNz8hB3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wNe561uQoiNz8hB3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wNe561uQoiNz8hB3 .error-icon{fill:#552222;}#mermaid-svg-wNe561uQoiNz8hB3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wNe561uQoiNz8hB3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wNe561uQoiNz8hB3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wNe561uQoiNz8hB3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wNe561uQoiNz8hB3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wNe561uQoiNz8hB3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wNe561uQoiNz8hB3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wNe561uQoiNz8hB3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wNe561uQoiNz8hB3 .marker.cross{stroke:#333333;}#mermaid-svg-wNe561uQoiNz8hB3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wNe561uQoiNz8hB3 p{margin:0;}#mermaid-svg-wNe561uQoiNz8hB3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wNe561uQoiNz8hB3 .cluster-label text{fill:#333;}#mermaid-svg-wNe561uQoiNz8hB3 .cluster-label span{color:#333;}#mermaid-svg-wNe561uQoiNz8hB3 .cluster-label span p{background-color:transparent;}#mermaid-svg-wNe561uQoiNz8hB3 .label text,#mermaid-svg-wNe561uQoiNz8hB3 span{fill:#333;color:#333;}#mermaid-svg-wNe561uQoiNz8hB3 .node rect,#mermaid-svg-wNe561uQoiNz8hB3 .node circle,#mermaid-svg-wNe561uQoiNz8hB3 .node ellipse,#mermaid-svg-wNe561uQoiNz8hB3 .node polygon,#mermaid-svg-wNe561uQoiNz8hB3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wNe561uQoiNz8hB3 .rough-node .label text,#mermaid-svg-wNe561uQoiNz8hB3 .node .label text,#mermaid-svg-wNe561uQoiNz8hB3 .image-shape .label,#mermaid-svg-wNe561uQoiNz8hB3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-wNe561uQoiNz8hB3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wNe561uQoiNz8hB3 .rough-node .label,#mermaid-svg-wNe561uQoiNz8hB3 .node .label,#mermaid-svg-wNe561uQoiNz8hB3 .image-shape .label,#mermaid-svg-wNe561uQoiNz8hB3 .icon-shape .label{text-align:center;}#mermaid-svg-wNe561uQoiNz8hB3 .node.clickable{cursor:pointer;}#mermaid-svg-wNe561uQoiNz8hB3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wNe561uQoiNz8hB3 .arrowheadPath{fill:#333333;}#mermaid-svg-wNe561uQoiNz8hB3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wNe561uQoiNz8hB3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wNe561uQoiNz8hB3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wNe561uQoiNz8hB3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wNe561uQoiNz8hB3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wNe561uQoiNz8hB3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wNe561uQoiNz8hB3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wNe561uQoiNz8hB3 .cluster text{fill:#333;}#mermaid-svg-wNe561uQoiNz8hB3 .cluster span{color:#333;}#mermaid-svg-wNe561uQoiNz8hB3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wNe561uQoiNz8hB3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wNe561uQoiNz8hB3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-wNe561uQoiNz8hB3 .icon-shape,#mermaid-svg-wNe561uQoiNz8hB3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wNe561uQoiNz8hB3 .icon-shape p,#mermaid-svg-wNe561uQoiNz8hB3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wNe561uQoiNz8hB3 .icon-shape .label rect,#mermaid-svg-wNe561uQoiNz8hB3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wNe561uQoiNz8hB3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wNe561uQoiNz8hB3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wNe561uQoiNz8hB3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
失败
原文
哈希
用私钥签名
私钥
只由签名者保存
签名值
重新计算哈希
用公钥验证
公钥
可以公开
验证结果
身份和完整性成立
内容被改或签名不匹配
数字签名提供:
- 身份认证:确实是某个私钥持有人签的。
- 完整性:内容没有被改。
- 不可抵赖性:在合适的密钥管理和制度前提下,签名者难以否认。
常见算法:
| 算法 | 说明 |
|---|---|
| RSA-PSS | 现代 RSA 签名方案,通常优先于老的 RSA PKCS#1 v1.5 签名 |
| ECDSA | 椭圆曲线签名,常见曲线如 P-256、secp256k1 |
| Ed25519 | EdDSA 的常见实例,现代、快、使用简单,SSH 和很多新系统常用 |
常见用途:
- SSH 公钥登录。
- Git commit/tag 签名。
- 软件包发布签名。
- TLS 证书签发和握手认证。
- JWT 的 RS256、ES256、EdDSA。
一个重要区别:
- 签名不隐藏内容。
- 加密才隐藏内容。
6. 非对称算法:别把 RSA、ECDSA、X25519 混成一类
非对称密码体系的核心是公钥和私钥,但不同算法用途不同。
| 名词 | 类型 | 主要用途 |
|---|---|---|
| RSA | 非对称算法族 | 可用于加密和签名,具体要看填充方案,如 RSA-OAEP、RSA-PSS |
| ECDSA | 椭圆曲线签名 | 签名,不是加密 |
| Ed25519 | EdDSA 签名算法实例 | 签名,不是加密 |
| ECDH | 椭圆曲线密钥交换 | 协商共享秘密 |
| X25519 | 基于 Curve25519 的密钥交换 | 协商共享秘密,不是签名 |
| secp256k1 | 椭圆曲线 | 常见于区块链签名场景 |
| P-256 / prime256v1 | 椭圆曲线 | TLS 证书、ECDSA、ECDH 常见 |
容易混的点:
- Ed25519 是签名算法。
- X25519 是密钥交换算法。
- ECDSA 和 ECDH 都可能使用椭圆曲线,但一个用于签名,一个用于密钥交换。
7. 密钥交换:HTTPS 为什么不直接把密钥发过去
HTTPS/TLS 最终传大量数据时需要对称密钥。问题是:客户端和服务器一开始并没有共同密钥,怎么安全地得到同一把密钥?
这就是密钥交换解决的问题。
服务端 客户端 服务端 客户端 #mermaid-svg-C6aHWNOiyhikOAjU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-C6aHWNOiyhikOAjU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-C6aHWNOiyhikOAjU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-C6aHWNOiyhikOAjU .error-icon{fill:#552222;}#mermaid-svg-C6aHWNOiyhikOAjU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-C6aHWNOiyhikOAjU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-C6aHWNOiyhikOAjU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-C6aHWNOiyhikOAjU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-C6aHWNOiyhikOAjU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-C6aHWNOiyhikOAjU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-C6aHWNOiyhikOAjU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-C6aHWNOiyhikOAjU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-C6aHWNOiyhikOAjU .marker.cross{stroke:#333333;}#mermaid-svg-C6aHWNOiyhikOAjU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-C6aHWNOiyhikOAjU p{margin:0;}#mermaid-svg-C6aHWNOiyhikOAjU .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-C6aHWNOiyhikOAjU text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-C6aHWNOiyhikOAjU .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-C6aHWNOiyhikOAjU .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-C6aHWNOiyhikOAjU .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-C6aHWNOiyhikOAjU .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-C6aHWNOiyhikOAjU #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-C6aHWNOiyhikOAjU .sequenceNumber{fill:white;}#mermaid-svg-C6aHWNOiyhikOAjU #sequencenumber{fill:#333;}#mermaid-svg-C6aHWNOiyhikOAjU #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-C6aHWNOiyhikOAjU .messageText{fill:#333;stroke:none;}#mermaid-svg-C6aHWNOiyhikOAjU .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-C6aHWNOiyhikOAjU .labelText,#mermaid-svg-C6aHWNOiyhikOAjU .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-C6aHWNOiyhikOAjU .loopText,#mermaid-svg-C6aHWNOiyhikOAjU .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-C6aHWNOiyhikOAjU .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-C6aHWNOiyhikOAjU .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-C6aHWNOiyhikOAjU .noteText,#mermaid-svg-C6aHWNOiyhikOAjU .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-C6aHWNOiyhikOAjU .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-C6aHWNOiyhikOAjU .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-C6aHWNOiyhikOAjU .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-C6aHWNOiyhikOAjU .actorPopupMenu{position:absolute;}#mermaid-svg-C6aHWNOiyhikOAjU .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-C6aHWNOiyhikOAjU .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-C6aHWNOiyhikOAjU .actor-man circle,#mermaid-svg-C6aHWNOiyhikOAjU line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-C6aHWNOiyhikOAjU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 双方用 ECDHE/X25519 算出同一个共享秘密 之后用派生出的会话密钥进行 AEAD 加密通信 ClientHello:支持的 TLS 版本、算法、客户端临时公钥 ServerHello:选择算法、服务端临时公钥 Certificate:服务器证书链 CertificateVerify:用证书私钥签名握手 transcript Finished Finished
现代 TLS 通常使用临时密钥交换,例如 ECDHE 或 X25519。临时的意思是每次连接都生成新的密钥交换材料。
好处是前向安全:
即使将来服务器证书私钥泄露,过去抓包保存下来的历史流量也不应该因此被解密。
8. 密钥派生:把共享秘密或密码变成真正可用的密钥
密钥派生函数 KDF 用来把"还不能直接当密钥用"的材料,变成适合具体算法使用的密钥。
HKDF
HKDF 常用于从共享秘密派生多个会话密钥。
TLS 1.3 的密钥调度就基于 HKDF 思路,把握手阶段得到的秘密逐步派生成不同用途的密钥。
#mermaid-svg-xkVtfPesbP4Q8kbA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xkVtfPesbP4Q8kbA .error-icon{fill:#552222;}#mermaid-svg-xkVtfPesbP4Q8kbA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xkVtfPesbP4Q8kbA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xkVtfPesbP4Q8kbA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xkVtfPesbP4Q8kbA .marker.cross{stroke:#333333;}#mermaid-svg-xkVtfPesbP4Q8kbA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xkVtfPesbP4Q8kbA p{margin:0;}#mermaid-svg-xkVtfPesbP4Q8kbA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xkVtfPesbP4Q8kbA .cluster-label text{fill:#333;}#mermaid-svg-xkVtfPesbP4Q8kbA .cluster-label span{color:#333;}#mermaid-svg-xkVtfPesbP4Q8kbA .cluster-label span p{background-color:transparent;}#mermaid-svg-xkVtfPesbP4Q8kbA .label text,#mermaid-svg-xkVtfPesbP4Q8kbA span{fill:#333;color:#333;}#mermaid-svg-xkVtfPesbP4Q8kbA .node rect,#mermaid-svg-xkVtfPesbP4Q8kbA .node circle,#mermaid-svg-xkVtfPesbP4Q8kbA .node ellipse,#mermaid-svg-xkVtfPesbP4Q8kbA .node polygon,#mermaid-svg-xkVtfPesbP4Q8kbA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xkVtfPesbP4Q8kbA .rough-node .label text,#mermaid-svg-xkVtfPesbP4Q8kbA .node .label text,#mermaid-svg-xkVtfPesbP4Q8kbA .image-shape .label,#mermaid-svg-xkVtfPesbP4Q8kbA .icon-shape .label{text-anchor:middle;}#mermaid-svg-xkVtfPesbP4Q8kbA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xkVtfPesbP4Q8kbA .rough-node .label,#mermaid-svg-xkVtfPesbP4Q8kbA .node .label,#mermaid-svg-xkVtfPesbP4Q8kbA .image-shape .label,#mermaid-svg-xkVtfPesbP4Q8kbA .icon-shape .label{text-align:center;}#mermaid-svg-xkVtfPesbP4Q8kbA .node.clickable{cursor:pointer;}#mermaid-svg-xkVtfPesbP4Q8kbA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xkVtfPesbP4Q8kbA .arrowheadPath{fill:#333333;}#mermaid-svg-xkVtfPesbP4Q8kbA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xkVtfPesbP4Q8kbA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xkVtfPesbP4Q8kbA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xkVtfPesbP4Q8kbA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xkVtfPesbP4Q8kbA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xkVtfPesbP4Q8kbA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xkVtfPesbP4Q8kbA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xkVtfPesbP4Q8kbA .cluster text{fill:#333;}#mermaid-svg-xkVtfPesbP4Q8kbA .cluster span{color:#333;}#mermaid-svg-xkVtfPesbP4Q8kbA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xkVtfPesbP4Q8kbA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xkVtfPesbP4Q8kbA rect.text{fill:none;stroke-width:0;}#mermaid-svg-xkVtfPesbP4Q8kbA .icon-shape,#mermaid-svg-xkVtfPesbP4Q8kbA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xkVtfPesbP4Q8kbA .icon-shape p,#mermaid-svg-xkVtfPesbP4Q8kbA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xkVtfPesbP4Q8kbA .icon-shape .label rect,#mermaid-svg-xkVtfPesbP4Q8kbA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xkVtfPesbP4Q8kbA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xkVtfPesbP4Q8kbA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xkVtfPesbP4Q8kbA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ECDHE/X25519 共享秘密
HKDF Extract
握手密钥
客户端写密钥
服务端写密钥
Finished 验证密钥
应用数据密钥
密码存储专用 KDF
用户密码通常熵不高,不能直接哈希后入库。密码存储要使用专门的慢哈希/密码哈希方案。
#mermaid-svg-zEqMKmKNQAssho1R{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zEqMKmKNQAssho1R .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zEqMKmKNQAssho1R .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zEqMKmKNQAssho1R .error-icon{fill:#552222;}#mermaid-svg-zEqMKmKNQAssho1R .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zEqMKmKNQAssho1R .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zEqMKmKNQAssho1R .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zEqMKmKNQAssho1R .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zEqMKmKNQAssho1R .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zEqMKmKNQAssho1R .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zEqMKmKNQAssho1R .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zEqMKmKNQAssho1R .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zEqMKmKNQAssho1R .marker.cross{stroke:#333333;}#mermaid-svg-zEqMKmKNQAssho1R svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zEqMKmKNQAssho1R p{margin:0;}#mermaid-svg-zEqMKmKNQAssho1R .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zEqMKmKNQAssho1R .cluster-label text{fill:#333;}#mermaid-svg-zEqMKmKNQAssho1R .cluster-label span{color:#333;}#mermaid-svg-zEqMKmKNQAssho1R .cluster-label span p{background-color:transparent;}#mermaid-svg-zEqMKmKNQAssho1R .label text,#mermaid-svg-zEqMKmKNQAssho1R span{fill:#333;color:#333;}#mermaid-svg-zEqMKmKNQAssho1R .node rect,#mermaid-svg-zEqMKmKNQAssho1R .node circle,#mermaid-svg-zEqMKmKNQAssho1R .node ellipse,#mermaid-svg-zEqMKmKNQAssho1R .node polygon,#mermaid-svg-zEqMKmKNQAssho1R .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zEqMKmKNQAssho1R .rough-node .label text,#mermaid-svg-zEqMKmKNQAssho1R .node .label text,#mermaid-svg-zEqMKmKNQAssho1R .image-shape .label,#mermaid-svg-zEqMKmKNQAssho1R .icon-shape .label{text-anchor:middle;}#mermaid-svg-zEqMKmKNQAssho1R .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zEqMKmKNQAssho1R .rough-node .label,#mermaid-svg-zEqMKmKNQAssho1R .node .label,#mermaid-svg-zEqMKmKNQAssho1R .image-shape .label,#mermaid-svg-zEqMKmKNQAssho1R .icon-shape .label{text-align:center;}#mermaid-svg-zEqMKmKNQAssho1R .node.clickable{cursor:pointer;}#mermaid-svg-zEqMKmKNQAssho1R .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zEqMKmKNQAssho1R .arrowheadPath{fill:#333333;}#mermaid-svg-zEqMKmKNQAssho1R .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zEqMKmKNQAssho1R .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zEqMKmKNQAssho1R .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zEqMKmKNQAssho1R .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zEqMKmKNQAssho1R .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zEqMKmKNQAssho1R .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zEqMKmKNQAssho1R .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zEqMKmKNQAssho1R .cluster text{fill:#333;}#mermaid-svg-zEqMKmKNQAssho1R .cluster span{color:#333;}#mermaid-svg-zEqMKmKNQAssho1R div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zEqMKmKNQAssho1R .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zEqMKmKNQAssho1R rect.text{fill:none;stroke-width:0;}#mermaid-svg-zEqMKmKNQAssho1R .icon-shape,#mermaid-svg-zEqMKmKNQAssho1R .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zEqMKmKNQAssho1R .icon-shape p,#mermaid-svg-zEqMKmKNQAssho1R .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zEqMKmKNQAssho1R .icon-shape .label rect,#mermaid-svg-zEqMKmKNQAssho1R .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zEqMKmKNQAssho1R .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zEqMKmKNQAssho1R .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zEqMKmKNQAssho1R :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户密码
Argon2id / bcrypt / scrypt / PBKDF2
随机 salt
成本参数
时间/内存/迭代次数
password hash
数据库
常见选择可以按下面的优先级理解:
- Argon2id:现代优先选择,兼顾抗 GPU/ASIC 破解和侧信道风险。
- scrypt:内存硬化,也常见。
- bcrypt:经典可靠,仍广泛使用。
- PBKDF2:兼容性好,但需要足够高的迭代成本;在新系统里通常不是首选。
不要这样存密码:
text
password -> SHA256 -> 数据库
应该这样理解:
text
password + salt + cost -> Argon2id/bcrypt/scrypt/PBKDF2 -> password hash
相关名词:
- salt:盐,每个密码一份随机值,防止相同密码得到相同结果,也防彩虹表。
- pepper:额外的全局秘密,通常放在数据库之外。
- cost/work factor:计算成本参数,用来增加离线暴力破解成本。
9. HTTPS/TLS:证书、签名、密钥交换和对称加密的组合拳
HTTPS = HTTP over TLS。
TLS 主要提供:
- 加密:旁观者看不到 HTTP 内容。
- 完整性:传输内容被改会被发现。
- 身份认证:客户端能确认自己连的是目标网站,而不是中间人。
一个简化心智模型:
#mermaid-svg-Vnih6NsvW9FeWOU0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Vnih6NsvW9FeWOU0 .error-icon{fill:#552222;}#mermaid-svg-Vnih6NsvW9FeWOU0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Vnih6NsvW9FeWOU0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .marker.cross{stroke:#333333;}#mermaid-svg-Vnih6NsvW9FeWOU0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Vnih6NsvW9FeWOU0 p{margin:0;}#mermaid-svg-Vnih6NsvW9FeWOU0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .cluster-label text{fill:#333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .cluster-label span{color:#333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .cluster-label span p{background-color:transparent;}#mermaid-svg-Vnih6NsvW9FeWOU0 .label text,#mermaid-svg-Vnih6NsvW9FeWOU0 span{fill:#333;color:#333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .node rect,#mermaid-svg-Vnih6NsvW9FeWOU0 .node circle,#mermaid-svg-Vnih6NsvW9FeWOU0 .node ellipse,#mermaid-svg-Vnih6NsvW9FeWOU0 .node polygon,#mermaid-svg-Vnih6NsvW9FeWOU0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Vnih6NsvW9FeWOU0 .rough-node .label text,#mermaid-svg-Vnih6NsvW9FeWOU0 .node .label text,#mermaid-svg-Vnih6NsvW9FeWOU0 .image-shape .label,#mermaid-svg-Vnih6NsvW9FeWOU0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Vnih6NsvW9FeWOU0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Vnih6NsvW9FeWOU0 .rough-node .label,#mermaid-svg-Vnih6NsvW9FeWOU0 .node .label,#mermaid-svg-Vnih6NsvW9FeWOU0 .image-shape .label,#mermaid-svg-Vnih6NsvW9FeWOU0 .icon-shape .label{text-align:center;}#mermaid-svg-Vnih6NsvW9FeWOU0 .node.clickable{cursor:pointer;}#mermaid-svg-Vnih6NsvW9FeWOU0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .arrowheadPath{fill:#333333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Vnih6NsvW9FeWOU0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vnih6NsvW9FeWOU0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Vnih6NsvW9FeWOU0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vnih6NsvW9FeWOU0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Vnih6NsvW9FeWOU0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Vnih6NsvW9FeWOU0 .cluster text{fill:#333;}#mermaid-svg-Vnih6NsvW9FeWOU0 .cluster span{color:#333;}#mermaid-svg-Vnih6NsvW9FeWOU0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Vnih6NsvW9FeWOU0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Vnih6NsvW9FeWOU0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Vnih6NsvW9FeWOU0 .icon-shape,#mermaid-svg-Vnih6NsvW9FeWOU0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Vnih6NsvW9FeWOU0 .icon-shape p,#mermaid-svg-Vnih6NsvW9FeWOU0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Vnih6NsvW9FeWOU0 .icon-shape .label rect,#mermaid-svg-Vnih6NsvW9FeWOU0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Vnih6NsvW9FeWOU0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Vnih6NsvW9FeWOU0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Vnih6NsvW9FeWOU0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
浏览器访问 https://example.com
服务器发送证书链
浏览器验证证书链、域名、有效期、用途
验证通过?
浏览器警告或拒绝连接
双方进行 ECDHE/X25519 密钥交换
HKDF 派生会话密钥
用 AES-GCM 或 ChaCha20-Poly1305 传输 HTTP 数据
HTTPS 里的角色:
| 名词 | 作用 |
|---|---|
| 浏览器/客户端 | 验证服务器证书,协商会话密钥 |
| 服务器 | 提供证书,证明自己拥有对应私钥 |
| CA | 证书颁发机构,负责给域名或组织签发证书 |
| 根证书 | 预置在操作系统或浏览器里的信任锚 |
| 中间证书 | 根 CA 授权出来的下级 CA 证书 |
| 服务器证书 | 把域名和服务器公钥绑定起来 |
一个常见误解是"HTTPS 用证书加密数据"。更准确地说:
- 证书主要负责身份认证和公钥绑定。
- 握手阶段会用证书私钥证明服务器身份。
- 双方通过密钥交换和密钥派生得到会话密钥。
- 真正传输 HTTP 内容时,通常使用 AEAD 对称加密算法。
10. CA 证书与证书链:我怎么相信这个公钥属于这个域名
PKI 是 Public Key Infrastructure,公钥基础设施。它解决的问题是:我怎么相信某个公钥真的属于某个主体?
证书可以粗略理解为:
text
CA 说:这个域名/组织的公钥是这个。
CA 对这句话做了数字签名。
证书链长这样:
#mermaid-svg-UXbZ6OJgxTuQZPtW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UXbZ6OJgxTuQZPtW .error-icon{fill:#552222;}#mermaid-svg-UXbZ6OJgxTuQZPtW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UXbZ6OJgxTuQZPtW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .marker.cross{stroke:#333333;}#mermaid-svg-UXbZ6OJgxTuQZPtW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UXbZ6OJgxTuQZPtW p{margin:0;}#mermaid-svg-UXbZ6OJgxTuQZPtW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .cluster-label text{fill:#333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .cluster-label span{color:#333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .cluster-label span p{background-color:transparent;}#mermaid-svg-UXbZ6OJgxTuQZPtW .label text,#mermaid-svg-UXbZ6OJgxTuQZPtW span{fill:#333;color:#333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .node rect,#mermaid-svg-UXbZ6OJgxTuQZPtW .node circle,#mermaid-svg-UXbZ6OJgxTuQZPtW .node ellipse,#mermaid-svg-UXbZ6OJgxTuQZPtW .node polygon,#mermaid-svg-UXbZ6OJgxTuQZPtW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UXbZ6OJgxTuQZPtW .rough-node .label text,#mermaid-svg-UXbZ6OJgxTuQZPtW .node .label text,#mermaid-svg-UXbZ6OJgxTuQZPtW .image-shape .label,#mermaid-svg-UXbZ6OJgxTuQZPtW .icon-shape .label{text-anchor:middle;}#mermaid-svg-UXbZ6OJgxTuQZPtW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UXbZ6OJgxTuQZPtW .rough-node .label,#mermaid-svg-UXbZ6OJgxTuQZPtW .node .label,#mermaid-svg-UXbZ6OJgxTuQZPtW .image-shape .label,#mermaid-svg-UXbZ6OJgxTuQZPtW .icon-shape .label{text-align:center;}#mermaid-svg-UXbZ6OJgxTuQZPtW .node.clickable{cursor:pointer;}#mermaid-svg-UXbZ6OJgxTuQZPtW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .arrowheadPath{fill:#333333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UXbZ6OJgxTuQZPtW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UXbZ6OJgxTuQZPtW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UXbZ6OJgxTuQZPtW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UXbZ6OJgxTuQZPtW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UXbZ6OJgxTuQZPtW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UXbZ6OJgxTuQZPtW .cluster text{fill:#333;}#mermaid-svg-UXbZ6OJgxTuQZPtW .cluster span{color:#333;}#mermaid-svg-UXbZ6OJgxTuQZPtW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UXbZ6OJgxTuQZPtW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UXbZ6OJgxTuQZPtW rect.text{fill:none;stroke-width:0;}#mermaid-svg-UXbZ6OJgxTuQZPtW .icon-shape,#mermaid-svg-UXbZ6OJgxTuQZPtW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UXbZ6OJgxTuQZPtW .icon-shape p,#mermaid-svg-UXbZ6OJgxTuQZPtW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UXbZ6OJgxTuQZPtW .icon-shape .label rect,#mermaid-svg-UXbZ6OJgxTuQZPtW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UXbZ6OJgxTuQZPtW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UXbZ6OJgxTuQZPtW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UXbZ6OJgxTuQZPtW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 服务器证书
example.com 的公钥
中间 CA 证书
Intermediate CA
根 CA 证书
Root CA
系统/浏览器信任库
签名验证方向
信任锚在本机
浏览器验证证书时,会检查很多东西:
- 证书链能否一路验证到本机信任库中的根 CA。
- 当前时间是否在证书有效期内。
- 访问的域名是否出现在证书的 SAN 中。
- 证书用途是否允许作为 TLS 服务器证书。
- 证书是否被吊销,具体依赖 CRL、OCSP、浏览器策略等机制。
- 服务器是否真的持有证书公钥对应的私钥。
X.509 证书常见字段:
| 字段 | 含义 |
|---|---|
| Subject | 证书主体,旧系统里常看 CN |
| SAN | Subject Alternative Name,现代 Web PKI 主要用它匹配域名 |
| Issuer | 谁签发的证书 |
| Subject Public Key Info | 证书绑定的公钥 |
| Validity | 有效期 |
| Key Usage | 这把钥匙允许做什么 |
| Extended Key Usage | 更具体的用途,如 TLS Web Server Authentication |
| Signature Algorithm | CA 用什么算法给证书签名 |
| Serial Number | 证书序列号 |
| Fingerprint | 证书摘要指纹,不是证书身份本身 |
CSR 是什么
CSR 是 Certificate Signing Request,证书签名请求。
申请证书的常见流程:
#mermaid-svg-2vXg2lNMqWTvwQlf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2vXg2lNMqWTvwQlf .error-icon{fill:#552222;}#mermaid-svg-2vXg2lNMqWTvwQlf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2vXg2lNMqWTvwQlf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2vXg2lNMqWTvwQlf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2vXg2lNMqWTvwQlf .marker.cross{stroke:#333333;}#mermaid-svg-2vXg2lNMqWTvwQlf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2vXg2lNMqWTvwQlf p{margin:0;}#mermaid-svg-2vXg2lNMqWTvwQlf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2vXg2lNMqWTvwQlf .cluster-label text{fill:#333;}#mermaid-svg-2vXg2lNMqWTvwQlf .cluster-label span{color:#333;}#mermaid-svg-2vXg2lNMqWTvwQlf .cluster-label span p{background-color:transparent;}#mermaid-svg-2vXg2lNMqWTvwQlf .label text,#mermaid-svg-2vXg2lNMqWTvwQlf span{fill:#333;color:#333;}#mermaid-svg-2vXg2lNMqWTvwQlf .node rect,#mermaid-svg-2vXg2lNMqWTvwQlf .node circle,#mermaid-svg-2vXg2lNMqWTvwQlf .node ellipse,#mermaid-svg-2vXg2lNMqWTvwQlf .node polygon,#mermaid-svg-2vXg2lNMqWTvwQlf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2vXg2lNMqWTvwQlf .rough-node .label text,#mermaid-svg-2vXg2lNMqWTvwQlf .node .label text,#mermaid-svg-2vXg2lNMqWTvwQlf .image-shape .label,#mermaid-svg-2vXg2lNMqWTvwQlf .icon-shape .label{text-anchor:middle;}#mermaid-svg-2vXg2lNMqWTvwQlf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2vXg2lNMqWTvwQlf .rough-node .label,#mermaid-svg-2vXg2lNMqWTvwQlf .node .label,#mermaid-svg-2vXg2lNMqWTvwQlf .image-shape .label,#mermaid-svg-2vXg2lNMqWTvwQlf .icon-shape .label{text-align:center;}#mermaid-svg-2vXg2lNMqWTvwQlf .node.clickable{cursor:pointer;}#mermaid-svg-2vXg2lNMqWTvwQlf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2vXg2lNMqWTvwQlf .arrowheadPath{fill:#333333;}#mermaid-svg-2vXg2lNMqWTvwQlf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2vXg2lNMqWTvwQlf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2vXg2lNMqWTvwQlf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2vXg2lNMqWTvwQlf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2vXg2lNMqWTvwQlf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2vXg2lNMqWTvwQlf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2vXg2lNMqWTvwQlf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2vXg2lNMqWTvwQlf .cluster text{fill:#333;}#mermaid-svg-2vXg2lNMqWTvwQlf .cluster span{color:#333;}#mermaid-svg-2vXg2lNMqWTvwQlf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2vXg2lNMqWTvwQlf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2vXg2lNMqWTvwQlf rect.text{fill:none;stroke-width:0;}#mermaid-svg-2vXg2lNMqWTvwQlf .icon-shape,#mermaid-svg-2vXg2lNMqWTvwQlf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2vXg2lNMqWTvwQlf .icon-shape p,#mermaid-svg-2vXg2lNMqWTvwQlf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2vXg2lNMqWTvwQlf .icon-shape .label rect,#mermaid-svg-2vXg2lNMqWTvwQlf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2vXg2lNMqWTvwQlf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2vXg2lNMqWTvwQlf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2vXg2lNMqWTvwQlf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 生成私钥
从私钥导出公钥
生成 CSR
包含公钥和域名等信息
CA 验证域名或组织
CA 签发证书
CSR 包含公钥和申请信息,不包含私钥。
自签名证书
自签名证书就是自己给自己签发的证书。
特点:
- 加密通信本身可以正常工作。
- 默认不被浏览器或系统信任。
- 适合本地开发、内网测试、私有 CA 场景。
如果把自建根 CA 安装进信任库,那么它签发的证书就可以被该系统信任。
11. SSH 密钥:登录服务器时发生了什么
SSH 里容易混两套 key:
- 服务器主机密钥:服务器自己生成,通常放在
/etc/ssh/ssh_host_*。客户端用它确认"我连到的是不是这台服务器"。 - 用户登录密钥:用户在客户端生成,例如
~/.ssh/id_ed25519和~/.ssh/id_ed25519.pub。服务器用authorized_keys判断"这个用户能不能登录"。
所以 known_hosts 在客户端,记录服务器主机公钥;authorized_keys 在服务器,记录允许登录的用户公钥。两套密钥方向相反:主机密钥让客户端认服务器,用户密钥让服务器认客户端用户。
SSH 公钥登录不是把私钥发给服务器,而是用用户私钥完成一次签名证明。
服务器 客户端 服务器 客户端 #mermaid-svg-os0IUpN39yVpX68b{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-os0IUpN39yVpX68b .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-os0IUpN39yVpX68b .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-os0IUpN39yVpX68b .error-icon{fill:#552222;}#mermaid-svg-os0IUpN39yVpX68b .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-os0IUpN39yVpX68b .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-os0IUpN39yVpX68b .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-os0IUpN39yVpX68b .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-os0IUpN39yVpX68b .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-os0IUpN39yVpX68b .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-os0IUpN39yVpX68b .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-os0IUpN39yVpX68b .marker{fill:#333333;stroke:#333333;}#mermaid-svg-os0IUpN39yVpX68b .marker.cross{stroke:#333333;}#mermaid-svg-os0IUpN39yVpX68b svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-os0IUpN39yVpX68b p{margin:0;}#mermaid-svg-os0IUpN39yVpX68b .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-os0IUpN39yVpX68b text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-os0IUpN39yVpX68b .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-os0IUpN39yVpX68b .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-os0IUpN39yVpX68b .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-os0IUpN39yVpX68b .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-os0IUpN39yVpX68b #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-os0IUpN39yVpX68b .sequenceNumber{fill:white;}#mermaid-svg-os0IUpN39yVpX68b #sequencenumber{fill:#333;}#mermaid-svg-os0IUpN39yVpX68b #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-os0IUpN39yVpX68b .messageText{fill:#333;stroke:none;}#mermaid-svg-os0IUpN39yVpX68b .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-os0IUpN39yVpX68b .labelText,#mermaid-svg-os0IUpN39yVpX68b .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-os0IUpN39yVpX68b .loopText,#mermaid-svg-os0IUpN39yVpX68b .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-os0IUpN39yVpX68b .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-os0IUpN39yVpX68b .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-os0IUpN39yVpX68b .noteText,#mermaid-svg-os0IUpN39yVpX68b .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-os0IUpN39yVpX68b .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-os0IUpN39yVpX68b .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-os0IUpN39yVpX68b .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-os0IUpN39yVpX68b .actorPopupMenu{position:absolute;}#mermaid-svg-os0IUpN39yVpX68b .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-os0IUpN39yVpX68b .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-os0IUpN39yVpX68b .actor-man circle,#mermaid-svg-os0IUpN39yVpX68b line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-os0IUpN39yVpX68b :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 请求登录 user@host 出示服务器主机公钥 检查 known_hosts,确认服务器身份 在 authorized_keys 中查找用户公钥 用用户私钥对当前会话的认证数据签名 返回签名 用用户公钥验证签名 验证通过,允许登录
这里的"当前会话的认证数据"包含和本次 SSH 连接绑定的信息,例如会话标识、用户名、服务名、公钥算法和公钥内容。它起到类似挑战数据的作用:旧连接里的签名不能直接拿到新连接里重放。
第一次连接时看到的 host key fingerprint 是服务器主机公钥的指纹,不是你的 id_ed25519.pub 指纹。确认后,客户端会把服务器主机公钥写入 known_hosts。
常见文件:
| 文件 | 含义 |
|---|---|
~/.ssh/id_ed25519 |
客户端用户私钥,证明"我是这个用户",必须保密 |
~/.ssh/id_ed25519.pub |
客户端用户公钥,通常放到服务器 authorized_keys 或 Git 平台 |
~/.ssh/authorized_keys |
服务器端用户公钥列表,用来认客户端用户 |
~/.ssh/known_hosts |
客户端记录的服务器主机公钥,用来认服务器 |
~/.ssh/config |
SSH 客户端配置 |
/etc/ssh/ssh_host_* |
服务器主机密钥,通常安装或首次启动 OpenSSH server 时生成 |
推荐生成 Ed25519 SSH key:
bash
ssh-keygen -t ed25519 -C "your_email@example.com"
查看公钥:
bash
cat ~/.ssh/id_ed25519.pub
查看指纹:
bash
ssh-keygen -lf ~/.ssh/id_ed25519.pub
SSH 里有两个认证方向
用户登录和服务器识别是两个方向:
#mermaid-svg-kQLDerny1WmXB89O{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kQLDerny1WmXB89O .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kQLDerny1WmXB89O .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kQLDerny1WmXB89O .error-icon{fill:#552222;}#mermaid-svg-kQLDerny1WmXB89O .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kQLDerny1WmXB89O .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kQLDerny1WmXB89O .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kQLDerny1WmXB89O .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kQLDerny1WmXB89O .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kQLDerny1WmXB89O .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kQLDerny1WmXB89O .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kQLDerny1WmXB89O .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kQLDerny1WmXB89O .marker.cross{stroke:#333333;}#mermaid-svg-kQLDerny1WmXB89O svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kQLDerny1WmXB89O p{margin:0;}#mermaid-svg-kQLDerny1WmXB89O .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kQLDerny1WmXB89O .cluster-label text{fill:#333;}#mermaid-svg-kQLDerny1WmXB89O .cluster-label span{color:#333;}#mermaid-svg-kQLDerny1WmXB89O .cluster-label span p{background-color:transparent;}#mermaid-svg-kQLDerny1WmXB89O .label text,#mermaid-svg-kQLDerny1WmXB89O span{fill:#333;color:#333;}#mermaid-svg-kQLDerny1WmXB89O .node rect,#mermaid-svg-kQLDerny1WmXB89O .node circle,#mermaid-svg-kQLDerny1WmXB89O .node ellipse,#mermaid-svg-kQLDerny1WmXB89O .node polygon,#mermaid-svg-kQLDerny1WmXB89O .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kQLDerny1WmXB89O .rough-node .label text,#mermaid-svg-kQLDerny1WmXB89O .node .label text,#mermaid-svg-kQLDerny1WmXB89O .image-shape .label,#mermaid-svg-kQLDerny1WmXB89O .icon-shape .label{text-anchor:middle;}#mermaid-svg-kQLDerny1WmXB89O .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kQLDerny1WmXB89O .rough-node .label,#mermaid-svg-kQLDerny1WmXB89O .node .label,#mermaid-svg-kQLDerny1WmXB89O .image-shape .label,#mermaid-svg-kQLDerny1WmXB89O .icon-shape .label{text-align:center;}#mermaid-svg-kQLDerny1WmXB89O .node.clickable{cursor:pointer;}#mermaid-svg-kQLDerny1WmXB89O .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kQLDerny1WmXB89O .arrowheadPath{fill:#333333;}#mermaid-svg-kQLDerny1WmXB89O .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kQLDerny1WmXB89O .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kQLDerny1WmXB89O .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kQLDerny1WmXB89O .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kQLDerny1WmXB89O .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kQLDerny1WmXB89O .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kQLDerny1WmXB89O .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kQLDerny1WmXB89O .cluster text{fill:#333;}#mermaid-svg-kQLDerny1WmXB89O .cluster span{color:#333;}#mermaid-svg-kQLDerny1WmXB89O div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kQLDerny1WmXB89O .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kQLDerny1WmXB89O rect.text{fill:none;stroke-width:0;}#mermaid-svg-kQLDerny1WmXB89O .icon-shape,#mermaid-svg-kQLDerny1WmXB89O .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kQLDerny1WmXB89O .icon-shape p,#mermaid-svg-kQLDerny1WmXB89O .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kQLDerny1WmXB89O .icon-shape .label rect,#mermaid-svg-kQLDerny1WmXB89O .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kQLDerny1WmXB89O .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kQLDerny1WmXB89O .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kQLDerny1WmXB89O :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SSH 连接
服务器验证用户身份
客户端验证服务器身份
服务器读取 authorized_keys
用用户公钥验证客户端签名
客户端读取 known_hosts
比对服务器主机公钥
第一次 SSH 到一台新机器时,常见提示是:
text
The authenticity of host ... can't be established.
这表示本机还没有记录过这台服务器的主机公钥。确认后会写入 known_hosts。
如果以后主机公钥变了,SSH 会强烈警告,因为可能是:
- 服务器重装了,主机密钥变了。
- DNS 或 IP 指到了另一台机器。
- 可能遭遇中间人攻击。
12. HTTPS 证书和 SSH key 的区别
| 对比点 | HTTPS/TLS 证书 | SSH key |
|---|---|---|
| 信任来源 | CA 体系,系统/浏览器内置信任根 | 通常是手动信任或管理员配置 |
| 证明对象 | 域名/组织和公钥的绑定 | 用户身份或服务器主机身份 |
| 常见文件格式 | X.509、PEM、DER、PKCS#12 | OpenSSH key、PEM |
| 典型验证 | 浏览器验证证书链和域名 | 服务器验证用户公钥,客户端验证主机公钥 |
| 是否需要 CA | 公网 HTTPS 通常需要 | 普通 SSH 登录通常不需要 |
简单区分:
text
HTTPS:浏览器问 CA,这个域名的公钥可信吗?
SSH:服务器问 authorized_keys,这个用户的公钥允许登录吗?
SSH 客户端还会问 known_hosts,这台服务器是不是我以前见过的那台?
13. 常见文件格式和后缀
| 后缀/格式 | 含义 |
|---|---|
.pem |
Base64 文本封装,常见于证书和私钥 |
.der |
二进制证书/密钥编码 |
.crt / .cer |
证书文件,可能是 PEM 或 DER |
.key |
私钥文件,格式不一定 |
.csr |
证书签名请求 |
.p12 / .pfx |
PKCS#12,常用于打包证书、私钥和证书链 |
.pub |
公钥文件,SSH 常见 |
known_hosts |
SSH 服务器主机公钥记录 |
authorized_keys |
SSH 允许登录的用户公钥列表 |
PEM 长这样:
text
-----BEGIN CERTIFICATE-----
Base64...
-----END CERTIFICATE-----
OpenSSH 私钥可能长这样:
text
-----BEGIN OPENSSH PRIVATE KEY-----
Base64...
-----END OPENSSH PRIVATE KEY-----
注意:PEM、DER、Base64 是编码或封装格式,不等于加密算法。
14. JWT 里的签名算法
JWT 的 alg 也经常让人混乱。
| JWT alg | 类型 | 说明 |
|---|---|---|
| HS256 | HMAC | 使用共享密钥,签发方和验证方都知道 secret |
| RS256 | RSA 签名 | 私钥签发,公钥验证 |
| ES256 | ECDSA P-256 | 私钥签发,公钥验证 |
| EdDSA | Ed25519 等 | 现代签名算法 |
| none | 无签名 | 正常业务系统不应该接受 |
关键区别:
- HS256 是对称的,验证方知道 secret,也就有能力签发 token。
- RS256、ES256、EdDSA 是非对称的,可以只把公钥发给验证方。
微服务里如果只有认证服务负责签发 token,其他服务只验证 token,通常更适合使用非对称签名。
15. 实际使用时怎么选
- 传输加密优先用 TLS 1.3,不要自己设计传输加密协议。
- 文件或字段加密优先用成熟库的 AEAD 接口,例如 AES-GCM 或 ChaCha20-Poly1305。
- nonce/IV 不能重复,密钥不要硬编码进代码仓库。
- 密码存储优先 Argon2id;不要直接存
MD5(password)、SHA1(password)或SHA256(password)。 - 数字签名新系统可优先 Ed25519;需要兼容证书、TLS、JWT 生态时,再按场景选择 RSA-PSS、RS256 或 ES256。
- SSH 新生成用户 key 优先 Ed25519,私钥建议设置 passphrase,不要共享私钥。
- 公网 HTTPS 使用可信 CA 签发的证书,注意 SAN、证书链和自动续期监控。
16. 常见误区清单
- "Base64 加密":错。Base64 是编码。
- "MD5 加密":错。MD5 是哈希,而且不适合安全用途。
- "哈希可以解密":错。哈希是单向摘要。
- "签名会隐藏内容":错。签名证明身份和完整性,不负责保密。
- "HTTPS 用 RSA 加密所有数据":不准确。现代 HTTPS 通常用 ECDHE/X25519 做密钥交换,用 AES-GCM 或 ChaCha20-Poly1305 加密数据。
- "证书就是公钥":不完整。证书包含公钥、主体、有效期、用途,并由 CA 签名。
- "有证书就一定安全":不一定。还要看私钥是否泄露、域名是否匹配、证书链是否可信、TLS 配置是否安全。
- "Ed25519 和 X25519 差不多":名字像,但用途不同。Ed25519 用于签名,X25519 用于密钥交换。
17. 口诀总结
text
加密管保密,哈希管指纹。
HMAC 靠共享密钥,签名靠私钥和公钥。
证书把域名和公钥绑起来,CA 负责背书。
HTTPS 先认证和协商密钥,再用对称加密传数据。
SSH 私钥在本机,公钥放远端。
known_hosts 认服务器,authorized_keys 认用户。
如果只保留最小心智模型:
- 对称加密快,适合加密大量数据。
- 非对称体系慢,但适合身份认证、签名和密钥交换。
- 哈希是指纹,不能解密。
- HMAC 是带共享密钥的完整性认证。
- 数字签名是私钥签、公钥验。
- TLS/HTTPS 组合使用证书、签名、密钥交换、密钥派生和 AEAD。
- CA 证书体系解决"这个公钥到底是谁的"。
- SSH 登录靠私钥签名,不是传输私钥。
参考资料
- RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
- RFC 5280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile
- RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)
- RFC 8709: Ed25519 and Ed448 Public Key Algorithms for the Secure Shell (SSH) Protocol
- RFC 8017: PKCS #1: RSA Cryptography Specifications Version 2.2
- RFC 9106: Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications
- NIST SP 800-63B: Digital Identity Guidelines, Authentication and Lifecycle Management
- OpenBSD ssh-keygen manual