密码学深度指南 — SecOps 工程师实战手册

面向网络安全从业者的密码学技术参考:原理、应用、攻击与防御、学习路线


目录

  1. 密码学核心概念

  2. 主流算法深入解析

  3. 实际应用场景

  4. 常见攻击与漏洞

  5. 学习路线与资源


1. 密码学核心概念

1.1 对称加密 vs 非对称加密

对称加密:加密和解密使用同一个密钥。

非对称加密:加密和解密使用一对密钥(公钥 + 私钥)。

核心区别在于密钥分发问题:对称加密需要双方事先共享密钥,非对称加密解决了这个难题。

对比维度 对称加密 非对称加密
速度 快 (GB/s 级别) 慢 (比对称慢 100-1000 倍)
密钥长度 AES-128 即可 RSA-3072 / ECC-256
密钥分发 ❌ 需要安全通道 ✅ 公钥可公开
典型算法 AES, ChaCha20, 3DES RSA, ECC (ECDSA, ECDH), Ed25519
用途 大量数据加密 密钥交换、数字签名

💡 实际工作场景 : TLS 握手用 ECDH(非对称)协商出一个对称密钥,之后所有数据传输用 AES-GCM(对称)。这就是混合加密体系------用非对称解决密钥分发,用对称保证传输效率。

1.2 哈希 vs MAC vs 数字签名

三者的核心区别:

  • 哈希 (Hash) : 保证完整性,无密钥,任何人都能验证

  • MAC (Message Authentication Code) : 保证完整性 + 认证,共享密钥,双方可互相验证

  • 数字签名 : 保证完整性 + 认证 + 不可抵赖,非对称密钥,私钥签名,公钥验证

特性 哈希 HMAC 数字签名
完整性
身份认证
不可抵赖
密钥 共享对称密钥 非对称密钥对
性能 极快
典型场景 文件校验、密码哈希 API 签名、TLS 完整性 代码签名、证书、JWT

1.3 分组密码工作模式

块密码(如 AES)一次处理固定长度的数据块(AES 为 128 位/16 字节)。工作模式决定了如何处理多个块

AES 工作模式对比图

工作模式选择建议:

场景 推荐模式 原因
一般加密需求 AES-GCM 认证加密,现代标准
高性能流式加密 ChaCha20-Poly1305 无硬件 AES 加速时比 AES-GCM 快
加密数据库字段 AES-SIV 确定性加密,相同明文产生相同密文
遗留系统兼容 AES-CBC + HMAC 旧系统不支持 GCM 时的退选
绝不使用 AES-ECB 完全不安全

💡 应急响应场景: 发现勒索软件使用 AES-ECB 加密文件?这可能是一个线索------专业勒索软件通常用 RSA+ECB 加密密钥 + AES-CBC/GCM 加密文件。用 ECB 的可能是业余作品。


2. 主流算法深入解析

2.1 AES --- 高级加密标准

直觉理解:AES 在做什么?

AES 不是"数学上很难",而是"通过大量简单操作的组合产生极高复杂度"。把 AES-128 想象成一台搅面机

复制代码
原始面团(明文) ──► [10 轮搅面] ──► 完全混合的面团(密文)
密钥长度选择
算法 密钥长度 安全级别 轮数 适用场景
AES-128 128 bit 128 bit 10 默认选择,量子计算机前安全
AES-192 192 bit 192 bit 12 合规要求 (Suite B)
AES-256 256 bit 256 bit 14 绝密数据、后量子过渡期

💡 实战建议: 99% 的场景 AES-128-GCM 足够。AES-256 只比 AES-128 慢约 40%,但安全余量更大。如果你在做政府/军事项目,用 AES-256。否则,AES-128 足够用到量子计算机实用化之前。

为什么 GCM 是现代标准?

GCM = CTR 模式加密 + GMAC 认证。关键优势:

  • 一次操作同时完成加密和认证(不需要先加密再 HMAC)

  • 并行化:CTR 和 GHASH 都可以并行

  • 额外认证数据 (AAD):可以认证不加密的头部信息(如协议版本号)

  • TLS 1.3 强制要求的 AEAD 模式之一

复制代码
# Python cryptography 库 — AES-GCM 正确用法
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
​
# 生成密钥(16 字节 = AES-128, 32 字节 = AES-256)
key = AESGCM.generate_key(bit_length=256)  # 32 bytes
aesgcm = AESGCM(key)
​
# 生成 nonce(必须每次不同!96 位推荐)
nonce = os.urandom(12)
​
# 加密(AAD 是不加密但要认证的数据)
aad = b"version=1.0,type=confidential"
plaintext = b"这是一段机密信息"
ciphertext = aesgcm.encrypt(nonce, plaintext, aad)
​
# 解密(nonce 和 aad 必须与加密时相同)
decrypted = aesgcm.decrypt(nonce, ciphertext, aad)
​
# ⚠ 如果密文被篡改,decrypt() 会抛出 InvalidTag 异常
常见错误用法
复制代码
# ❌ 错误 1: 硬编码 IV/Nonce
key = b"0123456789abcdef" * 2  # 硬编码密钥
iv = b"\x00" * 16                # 固定 IV = 灾难!
​
# ❌ 错误 2: ECB 模式(默认就是 ECB!)
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms
cipher = Cipher(algorithms.AES(key), mode=None)  # 无 mode = ECB!
​
# ❌ 错误 3: 重用 Nonce(GCM 模式下 = 密钥泄露)
nonce = os.urandom(12)
c1 = aesgcm.encrypt(nonce, msg1, None)
c2 = aesgcm.encrypt(nonce, msg2, None)  # Nonce 重用!攻击者可恢复明文!
​
# ✅ 正确做法
nonce = os.urandom(12)  # 每次加密生成新的 nonce
ciphertext = aesgcm.encrypt(nonce, plaintext, aad)
# 存储格式: nonce(12) + ciphertext + tag(16)

2.2 RSA --- 非对称加密基石

密钥生成过程(直觉理解)
复制代码
1. 随机选两个大质数 p 和 q(各 1024 位 → RSA-2048)
2. 计算 n = p × q  (n 是公钥的一部分,2048 位)
3. 计算 φ(n) = (p-1) × (q-1)
4. 选择 e = 65537(常用,质数且二进制只有两个 1,计算快)
5. 计算 d = e⁻¹ mod φ(n)  (d 是私钥)
​
公钥 = (n, e)
私钥 = (n, d)
​
加密: c = m^e mod n
解密: m = c^d mod n

安全性基础 :从 n 反推 p 和 q 是整数分解问题,目前没有已知的多项式时间算法。但 Shor 算法在量子计算机上可以高效分解,所以 RSA 在后量子时代不安全。

为什么 RSA-2048 是底线?
密钥长度 安全级别 分解难度 (GNFS) 建议
RSA-1024 ~80 bit 已可分解(2020 年分解 795 位) ❌ 已不安全
RSA-2048 ~112 bit 当前算力需要数百万年 ✅ 最低要求
RSA-3072 ~128 bit 远超出当前算力 ✅ 推荐
RSA-4096 ~140 bit 极其困难 过度保护,性能差

💡 合规检查: PCI-DSS 要求 RSA ≥ 2048。NIST SP 800-131A 建议 2023 年后使用 RSA-3072 或 ECC。

OAEP 填充 vs PKCS#1 v1.5
复制代码
from cryptography.hazmat.primitives.asymmetric import rsa, padding, hashes
from cryptography.hazmat.primitives import serialization
​
# 生成 RSA-2048 密钥对
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)
public_key = private_key.public_key()
​
# ❌ PKCS#1 v1.5 — 已被 Bleichenbacher 攻击利用
# 不推荐使用,但很多遗留系统仍在使用
​
# ✅ OAEP — 推荐
from cryptography.hazmat.primitives.asymmetric import padding
​
message = b"机密数据"
ciphertext = public_key.encrypt(
    message,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)
​
plaintext = private_key.decrypt(
    ciphertext,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

为什么 OAEP 更安全?

PKCS#1 v1.5 的填充格式是 0x00 || 0x02 || 随机非零字节 || 0x00 || 明文。Bleichenbacher 攻击利用服务器对填充错误的不同响应(padding oracle)逐步恢复明文。

OAEP 使用随机数 + 哈希函数的 Feistel 网络结构,即使攻击者知道填充格式错误,也无法获得任何有用信息。

2.3 ECC --- 椭圆曲线密码学

直觉理解

RSA 的安全性基于大整数分解 ,ECC 的安全性基于椭圆曲线离散对数问题 (ECDLP)

复制代码
椭圆曲线方程: y² = x³ + ax + b  (mod p)
​
在曲线上选一个基点 G,选一个私钥 d,
公钥 Q = d × G  (曲线上的点乘)
​
已知 Q 和 G 求 d → 极难 (ECDLP)
已知 d 和 G 求 Q → 容易 (点乘)

核心优势:更短的密钥 = 同等安全

安全级别 RSA 密钥 ECC 密钥 比例
128 bit 3072 位 256 位 12:1
256 bit 15360 位 512 位 30:1

更短的密钥 = 更快的运算 + 更少的带宽 + 更小的存储。这就是为什么 TLS 1.3、SSH、加密货币都选择了 ECC。

常用曲线
曲线 用途 安全性 备注
P-256 (secp256r1) TLS、JWT 128 bit NIST 标准,广泛支持
P-384 政府/军事 192 bit NIST Suite B
Curve25519 SSH、TLS 1.3 128 bit Bernstein 设计,推荐首选
Ed25519 SSH 密钥、签名 128 bit 基于 Curve25519,签名比 ECDSA 更快更安全

💡 实战建议 : 新系统一律选 Curve25519/Ed25519。它比 NIST 曲线更快、更安全(没有潜在后门嫌疑)、实现更简单。OpenSSH 8.2+ 默认使用 Ed25519。

2.4 SHA-2 / SHA-3 与 HMAC

为什么 SHA-1 已死?

2017 年 Google 的 SHAttered 攻击首次实现了 SHA-1 的实际碰撞。此后碰撞成本已降至约 $45,000。

复制代码
SHA-1 碰撞意味着:
  攻击者可以构造两个不同的文件,它们有相同的 SHA-1 哈希值
​
实际影响:
  - Git 用 SHA-1 做对象校验 → 已迁移到 SHA-256
  - X.509 证书签名 → 已禁用 SHA-1
  - 代码签名 → 已禁用 SHA-1

现在的选择

算法 输出长度 安全性 用途
SHA-256 256 bit 128 bit 通用哈希、TLS、比特币
SHA-384 384 bit 192 bit 高安全需求
SHA-512 512 bit 256 bit 通用哈希(64 位 CPU 上比 SHA-256 快)
SHA3-256 256 bit 128 bit SHA-2 的替代方案(不同构造)
BLAKE3 可变 128 bit 极快,适合高性能场景
HMAC 正确用法
复制代码
import hmac
import hashlib
​
# 生成 HMAC
key = os.urandom(32)  # 推荐 ≥ 32 字节
message = b"request_data"
tag = hmac.new(key, message, hashlib.sha256).hexdigest()
​
# 验证 HMAC — 必须用 compare_digest(恒定时间比较)
received_tag = "..."  # 从请求中获取
expected_tag = hmac.new(key, message, hashlib.sha256).hexdigest()
if not hmac.compare_digest(received_tag, expected_tag):
    raise ValueError("HMAC 验证失败!")

2.5 现代算法对比

ChaCha20-Poly1305 vs AES-GCM
对比 AES-GCM ChaCha20-Poly1305
硬件加速 需要 AES-NI 指令集 纯软件,无需特殊指令
无 AES-NI 时 快 3-4 倍
有 AES-NI 时 相当
Nonce 长度 96 位 96 位
安全余量 良好 更好(Poly1305 更安全)
TLS 1.3 支持
推荐场景 有 AES-NI 的服务器 移动设备、无 AES-NI 的 CPU

💡 实战: Google 的 TLS 默认首选 ChaCha20-Poly1305(因为大量移动设备无 AES-NI)。Intel 服务器上 AES-GCM 略快。两者安全性相当,都推荐。

密码哈希函数 --- 密码存储专用
复制代码
┌─────────────────────────────────────────────────────┐
│         密码哈希算法选择指南                         │
├─────────────────┬───────────┬───────────────────────┤
│     算法        │  推荐度   │  说明                  │
├─────────────────┼───────────┼───────────────────────┤
│ Argon2id        │ 🏆 首选   │ 抗 GPU/ASIC,内存硬   │
│ bcrypt          │ ✅ 推荐   │ 广泛支持,经过验证    │
│ scrypt          │ ⚠️ 可用   │ 内存硬,但不如 Argon2 │
│ PBKDF2          │ ⚠️ 最低   │ NIST 推荐,但无内存硬 │
│ MD5/SHA1        │ ❌ 禁用   │ 太块,GPU 每秒亿次     │
│ SHA256          │ ❌ 禁用   │ 同上                   │
└─────────────────┴───────────┴───────────────────────┘
复制代码
# Python — Argon2 密码哈希(推荐)
import argon2

ph = argon2.PasswordHasher(
    time_cost=3,      # 迭代次数
    memory_cost=65536, # 64 MB 内存
    parallelism=4,     # 并行线程
    hash_len=32,       # 输出长度
    salt_len=16        # salt 长度
)

# 存储密码
hashed = ph.hash("user_password_123")
# 输出: $argon2id$v=19$m=65536,t=3,p=4$...

# 验证密码
ph.verify(hashed, "user_password_123")  # 返回 True
ph.verify(hashed, "wrong_password")     # 抛出 VerifyMismatchError

💡 应急响应场景 : 发现数据库存储的密码是 MD5(password)SHA1(password)?这是严重安全事件!攻击者可以用 GPU 集群每秒尝试数亿个密码。应立即要求所有用户重置密码,并迁移到 Argon2 或 bcrypt。


3. 实际应用场景

3.1 TLS 1.3 握手流程

TLS 1.3 vs TLS 1.2 的关键改进:

TLS 1.2 TLS 1.3
2-RTT 握手 1-RTT 握手(快一倍)
支持 RC4, 3DES, CBC 只允许 AEAD(GCM, ChaCha20)
RSA 密钥传输 只允许 (EC)DHE(完美前向保密)
静态 RSA 签名 RSA-PSS / ECDSA

💡 网络取证场景 : 用 Wireshark 分析 TLS 流量时,TLS 1.3 的握手比 1.2 简洁得多。如果看到 Client Hello 后直接就是加密的 Server Hello(没有 Certificate/Server Key Exchange),那就是 TLS 1.3。

3.2 密码存储 --- 安全实践

3.3 JWT 签名 --- HS256 vs RS256 vs ES256

复制代码
JWT 结构: Header.Payload.Signature

Header:  {"alg":"RS256","typ":"JWT"}
Payload: {"sub":"user123","role":"admin","exp":1723000000}
Signature: RSASHA256(Base64(Header.Payload), private_key)
算法 密钥类型 性能 适用场景
HS256 对称密钥 (共享 secret) 最快 单体应用,单一服务
RS256 RSA 私钥签名,公钥验证 多服务,公钥可分发
ES256 ECDSA P-256 中等 移动应用,密钥小
⚠️ alg=none 攻击
复制代码
# 攻击者可以修改 JWT 头部:
# {"alg":"none","typ":"JWT"}
# 然后删除签名部分:
# header.payload.

# 如果服务端没有验证 alg 字段,会接受无签名的 JWT!

# 正确做法:
import jwt

# ❌ 错误 — 不验证签名
payload = jwt.decode(token, options={"verify_signature": False})

# ✅ 正确 — 强制验证
payload = jwt.decode(
    token,
    public_key,
    algorithms=["RS256"]  # 必须指定允许的算法!
)

3.4 磁盘加密 --- 密钥层次结构

3.5 区块链密码学


4. 常见攻击与漏洞

4.1 Padding Oracle Attack

现实案例: POODLE 攻击 (CVE-2014-3566) 就是 Padding Oracle 的变种,影响 SSL 3.0。攻击者通过降级攻击迫使服务端使用 SSL 3.0 的 CBC 模式,然后利用 Padding Oracle 逐字节解密 Cookie。

4.2 长度扩展攻击

复制代码
问题: H(K || m) 不是安全的 MAC!

原因: Merkle-Damgård 结构 (MD5, SHA-1, SHA-2) 的输出就是内部状态。
      已知 H(K || m) 和 |K||m|,可以计算 H(K || m || padding || m')
      而不需要知道 K!

攻击演示:
  已知: HMAC = SHA256(secret || "user=guest")
  攻击者可以计算: SHA256(secret || "user=guest" || padding || "&role=admin")
  而不需要知道 secret!

防御: 使用 HMAC 而不是 H(K||m)
  HMAC 的两层结构 (ipad/opad) 天然防止长度扩展攻击

4.3 Nonce 重用 --- 灾难性错误

GCM 模式 Nonce 重用
复制代码
# ❌ 灾难性错误:GCM Nonce 重用
nonce = os.urandom(12)
c1 = aesgcm.encrypt(nonce, message1, aad)
c2 = aesgcm.encrypt(nonce, message2, aad)  # 相同的 nonce!

# 后果:
# 1. 攻击者可以计算: c1 ⊕ c2 = m1 ⊕ m2
# 2. 如果知道 m1 的部分内容,可以恢复 m2
# 3. 更严重:攻击者可以伪造认证标签 (GHASH 密钥泄露)
# 4. 整个密钥的安全性被破坏!
One-Time Pad 重用
复制代码
经典案例: 苏联 Venona 计划 (1940s)
  苏联情报机构使用一次性密码本加密消息
  但由于生产量不足,部分密码本被重复使用
  美国 NSA 通过比对两条用相同密钥加密的消息
  恢复了大量苏联情报通信的明文

原理:
  c1 = m1 ⊕ k
  c2 = m2 ⊕ k
  c1 ⊕ c2 = m1 ⊕ m2

  如果 m1 和 m2 是自然语言,m1 ⊕ m2 有可识别的模式
  通过统计分析可以恢复 m1 和 m2

4.4 Timing Attack --- 恒定时间比较

复制代码
# ❌ 不安全 — 非恒定时间比较
def verify_signature(received_sig, expected_sig):
    if len(received_sig) != len(expected_sig):
        return False
    for i in range(len(received_sig)):
        if received_sig[i] != expected_sig[i]:
            return False  # 在不匹配的位置提前返回!
    return True

# 攻击者可以通过测量响应时间,逐字节确定签名
# 第 1 字节匹配: +10ns
# 第 2 字节匹配: +10ns
# ...
# 暴力复杂度从 256^n 降到 256×n

# ✅ 安全 — 恒定时间比较
import hmac
def verify_signature_safe(received_sig, expected_sig):
    return hmac.compare_digest(received_sig, expected_sig)

# hmac.compare_digest() 会比较所有字节,无论在哪里不匹配
# 返回时间只与输入长度有关,与内容无关

💡 代码审计场景 : 在 JWT 验证、API 密钥验证、密码比较等场景中,搜索 == 比较敏感值。如果找到,替换为 hmac.compare_digest() 或语言等效的恒定时间比较函数。

4.5 侧信道攻击 --- 直觉理解

复制代码
┌─────────────────────────────────────────────────────┐
│                 侧信道攻击类型                        │
├─────────────────┬───────────────────────────────────┤
│   攻击类型       │           说明                    │
├─────────────────┼───────────────────────────────────┤
│ Timing Attack   │ 通过操作耗时推断密钥信息            │
│                 │ 例: RSA 解密时间依赖私钥 d 的比特   │
│                 │ 防御: 恒定时间实现                  │
├─────────────────┼───────────────────────────────────┤
│ Cache Timing    │ 通过 CPU 缓存命中/未命中推断访问模式│
│                 │ 例: AES 查表操作的缓存侧信道        │
│                 │ 防御: 使用 AES-NI 指令 (不查表)     │
├─────────────────┼───────────────────────────────────┤
│ Power Analysis  │ 通过功耗变化推断密钥                │
│                 │ 例: 智能卡/嵌入式设备的 SPA/DPA     │
│                 │ 防御: 功耗均衡、随机延迟            │
├─────────────────┼───────────────────────────────────┤
│ EM Radiation    │ 通过电磁辐射推断操作                │
│                 │ 例: TEMPEST 攻击                    │
│                 │ 防御: 屏蔽室、法拉第笼              │
├─────────────────┼───────────────────────────────────┤
│ Fault Injection │ 通过电压/时钟故障诱导计算错误       │
│                 │ 例: RSA-CRT 故障攻击恢复私钥        │
│                 │ 防御: 错误检测、冗余计算            │
└─────────────────┴───────────────────────────────────┘
ROCA 漏洞 (CVE-2017-15361)
复制代码
Infineon TPM 芯片的 RSA 密钥生成缺陷:
  p 和 q 的生成使用了有偏的随机数生成器
  导致 p ≡ a (mod M) 对于某个小 M

影响:
  - 30,000+ 设备受影响 (智能卡、TPM、安全启动密钥)
  - 攻击者可以在几小时内分解受影响的 RSA 密钥
  - 不需要量子计算机!

检测:
  - 工具: roca-detect (GitHub)
  - 检查你的 RSA 密钥是否被影响:
    $ python3 roca-detect.py your_key.pem

防御:
  - 更新 TPM 固件
  - 重新生成 RSA 密钥对
  - 迁移到 ECC (Ed25519)

5. 学习路线与资源

5.1 学习路径

5.2 推荐资源

书籍
书籍 难度 特点
《Serious Cryptography》(Aumasson) ⭐⭐ 最佳入门,实战导向,代码示例丰富
《Understanding Cryptography》( Paar/Pezl) ⭐⭐⭐ 教科书级别,数学推导详细
《Applied Cryptography》(Schneier) ⭐⭐⭐ 经典,部分内容过时但思想永恒
《Real-World Cryptography》(Wong) ⭐⭐ 现代实践,TLS/Signal/加密货币密码学
在线课程
课程 平台 特点
CryptoHack cryptohack.org 最佳实战平台,交互式,Python 代码题
Cryptopals cryptopals.com 经典挑战,64 题,从基础到高级
Cryptography I Coursera (Stanford, Boneh) 理论扎实,数学推导
pwn.college crypto pwn.college CTF 风格,实践性强
工具
工具 用途 链接
CyberChef 可视化加密/编码/解码 https://gchq.github.io/CyberChef/
hashcat 密码破解学习 https://hashcat.net/hashcat/
openssl 命令行加密/证书操作 系统自带
Wireshark TLS 握手分析 https://wireshark.org
cryptography (Python) 编程实现 pip install cryptography

5.3 实战练习 --- 安全文件加密工具

复制代码
"""
实战项目:安全的文件加密工具
功能: 使用 Argon2 从密码派生密钥,AES-256-GCM 加密文件
"""

import os
import struct
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.argon2 import Argon2id

# 文件加密格式:
# [salt(16)] [nonce(12)] [ciphertext + tag]

def derive_key(password: str, salt: bytes) -> bytes:
    """从密码派生 256 位密钥"""
    kdf = Argon2id(
        salt=salt,
        length=32,           # 256 位密钥
        iterations=3,
        lanes=4,
        memory_cost=65536,   # 64 MB
    )
    return kdf.derive(password.encode())

def encrypt_file(input_path: str, output_path: str, password: str):
    """加密文件"""
    salt = os.urandom(16)
    key = derive_key(password, salt)
    aesgcm = AESGCM(key)
    nonce = os.urandom(12)

    with open(input_path, "rb") as f:
        plaintext = f.read()

    aad = os.path.basename(input_path).encode()  # 文件名作为 AAD
    ciphertext = aesgcm.encrypt(nonce, plaintext, aad)

    with open(output_path, "wb") as f:
        f.write(salt + nonce + ciphertext)

    print(f"✅ 已加密: {input_path} → {output_path}")
    print(f"   原始大小: {len(plaintext)} 字节")
    print(f"   加密大小: {len(salt) + len(nonce) + len(ciphertext)} 字节")

def decrypt_file(input_path: str, output_path: str, password: str):
    """解密文件"""
    with open(input_path, "rb") as f:
        data = f.read()

    salt = data[:16]
    nonce = data[16:28]
    ciphertext = data[28:]

    key = derive_key(password, salt)
    aesgcm = AESGCM(key)

    try:
        aad = os.path.basename(output_path).encode()
        plaintext = aesgcm.decrypt(nonce, ciphertext, aad)
    except Exception:
        print("❌ 解密失败:密码错误或文件已损坏")
        return

    with open(output_path, "wb") as f:
        f.write(plaintext)

    print(f"✅ 已解密: {input_path} → {output_path}")

# 使用示例
if __name__ == "__main__":
    encrypt_file("secret.docx", "secret.docx.enc", "my_secure_password")
    decrypt_file("secret.docx.enc", "secret_decrypted.docx", "my_secure_password")

5.4 OpenSSL 命令行速查

复制代码
# 生成 RSA-2048 私钥
openssl genrsa -out private.pem 2048

# 生成 RSA-4096 私钥
openssl genrsa -out private4096.pem 4096

# 生成 ECC 私钥 (P-256)
openssl ecparam -genkey -name prime256v1 -noout -out ec_key.pem

# 生成 Ed25519 私钥
openssl genpkey -algorithm ED25519 -out ed25519_key.pem

# 提取公钥
openssl rsa -in private.pem -pubout -out public.pem

# AES-256-GCM 加密 (OpenSSL 命令行不直接支持 GCM,用 CBC 演示)
openssl enc -aes-256-cbc -salt -in secret.txt -out secret.txt.enc

# AES-256-CBC 解密
openssl enc -aes-256-cbc -d -in secret.txt.enc -out secret.txt

# 计算 SHA-256 哈希
openssl dgst -sha256 file.txt

# 计算 HMAC-SHA256
openssl dgst -sha256 -hmac "my_secret_key" file.txt

# RSA 签名
openssl dgst -sha256 -sign private.pem -out signature.bin file.txt

# RSA 验签
openssl dgst -sha256 -verify public.pem -signature signature.bin file.txt

# 查看证书信息
openssl x509 -in cert.pem -text -noout

# TLS 连接测试
openssl s_client -connect example.com:443 -servername example.com

# 检查 TLS 版本和密码套件
openssl s_client -connect example.com:443 -tls1_3

# 查看证书的 RSA 密钥长度
openssl x509 -in cert.pem -text -noout | grep "Public-Key"

5.5 Wireshark TLS 分析

复制代码
# 设置 TLS 密钥日志文件(让 Wireshark 解密 TLS 流量)
export SSLKEYLOGFILE="$HOME/tls-keys.log"

# 然后启动浏览器(Chrome/Edge 会写入密钥到该文件)
# 在 Wireshark 中: Edit → Preferences → Protocols → TLS → (Pre)-Master-Secret log filename
# 选择 $HOME/tls-keys.log

# 过滤 TLS 流量
tls

# 查看 TLS 握手
tls.handshake

# 查看具体的 Client Hello
tls.handshake.type == 1

# 查看 Server Hello
tls.handshake.type == 2

# 查看证书
tls.handshake.certificate

# 查看密码套件协商
tls.handshake.ciphersuite

5.6 面试常问密码学问题

  1. 解释对称加密和非对称加密的区别,以及 TLS 中如何结合使用?

  2. 为什么不能用 MD5 存储密码?应该用什么?

  3. 什么是 Perfect Forward Secrecy (PFS)?TLS 1.3 为什么强制要求?

  4. AES-GCM 中 Nonce 重用有什么后果?

  5. 解释 HMAC 的构造,为什么不能直接用 H(K||m)?

  6. RSA-2048 和 ECC-256 哪个更安全?为什么?

  7. 什么是 Padding Oracle Attack?如何防御?

  8. 解释 TLS 1.3 握手流程,与 1.2 有什么不同?

  9. 什么是 AEAD?举例说明。

  10. 如果你的系统发现密码用 SHA1 存储,你如何处理?


附录:密码学决策树

复制代码
你需要做什么?
│
├─ 加密数据
│  ├─ 大量数据? → AES-256-GCM 或 ChaCha20-Poly1305
│  ├─ 小数据/密钥加密? → RSA-OAEP 或 ECIES
│  └─ 需要确定性加密? → AES-SIV
│
├─ 验证数据完整性
│  ├─ 不需要密钥? → SHA-256
│  ├─ 需要认证? → HMAC-SHA256
│  └─ 需要不可抵赖? → ECDSA / Ed25519
│
├─ 存储密码
│  └─ Argon2id (首选) 或 bcrypt
│
├─ 密钥交换
│  └─ X25519 (首选) 或 ECDH P-256
│
├─ 密钥派生
│  ├─ 从密码派生? → Argon2id 或 PBKDF2
│  └─ 从主密钥派生子密钥? → HKDF-SHA256
│
└─ 随机数生成
   └─ os.urandom() / /dev/urandom (不要自己实现!)

本文档为 SecOps 工程师密码学参考手册,涵盖原理、应用、攻击与防御。密码学在安全运营中无处不在------从日志中的 TLS 握手分析到恶意软件加密通信解密,从密码存储合规检查到 API 签名验证。掌握这些知识,你将能在实际工作中做出更明智的安全决策。

相关推荐
美团技术团队44 分钟前
Agent评测漫谈 —— 由浅入深讲解Agent评测
人工智能
前端 贾公子1 小时前
Tavily Search:一个专为 AI Agent 打造的专属搜索引擎 API
人工智能
淼澄研学1 小时前
PyTorch核心实操:从张量计算到混合精度训练的5个关键步骤
人工智能·pytorch·python
用户298698530141 小时前
Word 转 PDF 的 3 种自动化实现:从桌面操作到后端服务集成
java·人工智能·后端
梦想三三1 小时前
Qwen Function Calling实战:重构电商客服AI Agent
人工智能·python·langchain·大模型·rag
蜜桃味女焊匠人1 小时前
焊接机器人对比人工焊接,工厂该怎么选?
人工智能·经验分享·其他·机器人
0566461 小时前
agent学习Day23——文件上传与 Embedding 语义检索
python·学习·embedding
leisoo80971 小时前
筹码分布数据分析实战:用Python构建主力建仓成本分析系统
python·数据挖掘·数据分析
2601_955759411 小时前
企业 Claude API 权限治理常见问题解答
人工智能