TLS加密算法深度解析
TLS 加密算法深度解析
从数学原理到工程实现,探索现代密码学在 TLS 中的应用
加密算法体系
对称加密算法
AES (Advanced Encryption Standard):
密钥长度:128/192/256 位
分组长度:128 位
轮数:10/12/14 轮
工作模式对比:
| 模式 | 特点 | 安全性 | 性能 | 适用场景 |
|---|---|---|---|---|
| CBC | 需要 IV,串行 | 中等 | 慢 | 已淘汰 |
| GCM | 认证加密,并行 | 高 | 快 | TLS 1.2+ |
| CCM | 认证加密,串行 | 高 | 中等 | 受限环境 |
| ChaCha20-Poly1305 | 流密码+认证 | 高 | 快 | 移动设备 |
非对称加密算法
RSA:
# RSA 密钥生成
def generate_rsa_key(bits=2048):
# 1. 选择两个大质数 p, q
p = generate_prime(bits // 2)
q = generate_prime(bits // 2)
# 2. 计算模数 n = p * q
n = p * q
# 3. 计算欧拉函数 φ(n) = (p-1)(q-1)
phi_n = (p - 1) * (q - 1)
# 4. 选择公钥指数 e (通常是 65537)
e = 65537
# 5. 计算私钥指数 d = e^(-1) mod φ(n)
d = mod_inverse(e, phi_n)
return {
'public_key': (n, e),
'private_key': (n, d)
}
椭圆曲线密码学 (ECC):
# 椭圆曲线点运算
class EllipticCurve:
def __init__(self, a, b, p):
self.a = a # 曲线参数
self.b = b # 曲线参数
self.p = p # 有限域模数
def point_add(self, P, Q):
"""椭圆曲线点加法"""
if P is None:
return Q
if Q is None:
return P
x1, y1 = P
x2, y2 = Q
if x1 == x2:
if y1 == y2:
# 点倍乘
s = (3 * x1 * x1 + self.a) * mod_inverse(2 * y1, self.p) % self.p
else:
# 相反点,结果为无穷远点
return None
else:
# 普通点加法
s = (y2 - y1) * mod_inverse(x2 - x1, self.p) % self.p
x3 = (s * s - x1 - x2) % self.p
y3 = (s * (x1 - x3) - y1) % self.p
return (x3, y3)
def scalar_multiply(self, k, P):
"""标量乘法 kP"""
if k == 0:
return None
result = None
addend = P
while k:
if k & 1:
result = self.point_add(result, addend)
addend = self.point_add(addend, addend)
k >>= 1
return result
哈希算法
SHA-2 家族:
SHA-224: 224 位输出
SHA-256: 256 位输出 (TLS 常用)
SHA-384: 384 位输出
SHA-512: 512 位输出
SHA-3 (Keccak):
- 不同于 SHA-2 的 Merkle-Damgård 结构
- 使用海绵函数构造
- 抗长度扩展攻击
密钥交换算法
ECDHE (椭圆曲线 Diffie-Hellman)
数学原理:
1. 双方约定椭圆曲线 E 和基点 G
2. Alice 生成私钥 a,计算公钥 A = aG
3. Bob 生成私钥 b,计算公钥 B = bG
4. Alice 计算共享密钥 K = aB = a(bG) = abG
5. Bob 计算共享密钥 K = bA = b(aG) = abG
安全性基础:
- 椭圆曲线离散对数问题 (ECDLP)
- 给定 P, Q,求 k 使得 Q = kP 在计算上不可行
常用曲线:
P-256 (secp256r1): y² = x³ - 3x + b (mod p)
P-384 (secp384r1): 更高安全强度
Ed25519: 扭曲爱德华曲线,性能优异
DHE (有限域 Diffie-Hellman)
数学原理:
1. 选择大质数 p 和生成元 g
2. Alice 生成私钥 a,计算公钥 A = g^a mod p
3. Bob 生成私钥 b,计算公钥 B = g^b mod p
4. 共享密钥 K = g^(ab) mod p
安全参数:
- 2048 位模数提供 112 位安全强度
- 3072 位模数提供 128 位安全强度
数字签名算法
ECDSA (椭圆曲线数字签名)
签名过程:
def ecdsa_sign(message, private_key, curve):
# 1. 计算消息哈希
h = sha256(message)
# 2. 生成随机数 k
k = random.randint(1, curve.order - 1)
# 3. 计算 r = (kG).x mod n
point = curve.scalar_multiply(k, curve.generator)
r = point[0] % curve.order
# 4. 计算 s = k^(-1)(h + r * private_key) mod n
k_inv = mod_inverse(k, curve.order)
s = (k_inv * (h + r * private_key)) % curve.order
return (r, s)
验证过程:
def ecdsa_verify(message, signature, public_key, curve):
r, s = signature
h = sha256(message)
# 计算 w = s^(-1) mod n
w = mod_inverse(s, curve.order)
# 计算 u1 = hw mod n, u2 = rw mod n
u1 = (h * w) % curve.order
u2 = (r * w) % curve.order
# 计算 (x, y) = u1*G + u2*public_key
point1 = curve.scalar_multiply(u1, curve.generator)
point2 = curve.scalar_multiply(u2, public_key)
point = curve.point_add(point1, point2)
# 验证 x ≡ r (mod n)
return point[0] % curve.order == r
EdDSA (爱德华曲线数字签名)
Ed25519 优势:
def ed25519_sign(message, private_key):
# 1. 确定性随机数生成
r = hash(private_key_suffix + message)
# 2. 计算 R = rG
R = scalar_multiply(r, generator)
# 3. 计算挑战值
h = hash(R + public_key + message)
# 4. 计算签名
s = (r + h * private_key) % order
return (R, s)
特点:
- 确定性签名(相同输入产生相同签名)
- 抗侧信道攻击
- 更快的签名和验证速度
认证加密 (AEAD)
AES-GCM
工作原理:
GCM = CTR 模式加密 + GHASH 认证
实现细节:
def aes_gcm_encrypt(plaintext, key, iv, aad=b''):
# 1. 生成认证密钥 H
H = aes_encrypt(b'\x00' * 16, key)
# 2. CTR 模式加密
ciphertext = aes_ctr_encrypt(plaintext, key, iv)
# 3. GHASH 计算认证标签
auth_data = aad + b'\x00' * padding_length(aad)
auth_data += ciphertext + b'\x00' * padding_length(ciphertext)
auth_data += struct.pack('>QQ', len(aad) * 8, len(ciphertext) * 8)
tag = ghash(auth_data, H)
return ciphertext, tag
ChaCha20-Poly1305
ChaCha20 流密码:
def chacha20_encrypt(plaintext, key, nonce, counter=0):
keystream = b''
for i in range((len(plaintext) + 63) // 64):
block = chacha20_block(key, nonce, counter + i)
keystream += block
return bytes(a ^ b for a, b in zip(plaintext, keystream))
Poly1305 认证:
def poly1305_mac(message, key):
r = int.from_bytes(key[:16], 'little') & 0x0ffffffc0ffffffc0ffffffc0fffffff
s = int.from_bytes(key[16:32], 'little')
accumulator = 0
for i in range(0, len(message), 16):
block = message[i:i+16] + b'\x01'
n = int.from_bytes(block, 'little')
accumulator = ((accumulator + n) * r) % (2**130 - 5)
return ((accumulator + s) % 2**128).to_bytes(16, 'little')
密钥派生
TLS 1.2 PRF
伪随机函数:
def tls12_prf(secret, label, seed, length):
"""TLS 1.2 伪随机函数"""
def p_hash(secret, seed, length):
result = b''
a = seed
while len(result) < length:
a = hmac_sha256(secret, a)
result += hmac_sha256(secret, a + seed)
return result[:length]
return p_hash(secret, label + seed, length)
# 主密钥派生
master_secret = tls12_prf(
pre_master_secret,
b"master secret",
client_random + server_random,
48
)
# 会话密钥派生
key_block = tls12_prf(
master_secret,
b"key expansion",
server_random + client_random,
key_block_length
)
TLS 1.3 HKDF
基于 HMAC 的密钥派生:
def hkdf_extract(salt, ikm):
"""HKDF 提取阶段"""
if not salt:
salt = b'\x00' * hash_length
return hmac(salt, ikm)
def hkdf_expand(prk, info, length):
"""HKDF 扩展阶段"""
t = b''
okm = b''
counter = 1
while len(okm) < length:
t = hmac(prk, t + info + bytes([counter]))
okm += t
counter += 1
return okm[:length]
# TLS 1.3 密钥派生
early_secret = hkdf_extract(b'', psk or b'\x00' * hash_length)
handshake_secret = hkdf_extract(derive_secret(early_secret, "derived"), ecdhe_shared_secret)
master_secret = hkdf_extract(derive_secret(handshake_secret, "derived"), b'\x00' * hash_length)
性能优化
硬件加速
AES-NI 指令集:
// Intel AES-NI 示例
__m128i aes_encrypt_block(__m128i plaintext, __m128i* round_keys) {
__m128i state = _mm_xor_si128(plaintext, round_keys[0]);
for (int i = 1; i < 10; i++) {
state = _mm_aesenc_si128(state, round_keys[i]);
}
return _mm_aesenclast_si128(state, round_keys[10]);
}
椭圆曲线优化:
- 蒙哥马利阶梯算法
- 窗口方法
- 预计算表
算法选择建议
高性能场景:
密钥交换: X25519 (ECDHE)
签名: Ed25519
对称加密: ChaCha20-Poly1305 (移动端)
AES-256-GCM (服务器端)
哈希: SHA-256
兼容性优先:
密钥交换: P-256 (ECDHE)
签名: ECDSA P-256
对称加密: AES-128-GCM
哈希: SHA-256
安全考量
侧信道攻击防护
常数时间实现:
def constant_time_compare(a, b):
"""常数时间字符串比较"""
if len(a) != len(b):
return False
result = 0
for x, y in zip(a, b):
result |= x ^ y
return result == 0
def constant_time_select(condition, a, b):
"""常数时间条件选择"""
mask = -(condition & 1) # 0 或 0xFFFFFFFF
return (a & mask) | (b & ~mask)
随机数生成
密码学安全随机数:
import os
import hashlib
def secure_random(length):
"""生成密码学安全的随机数"""
return os.urandom(length)
def deterministic_random(seed, length):
"""确定性随机数生成(用于测试)"""
output = b''
counter = 0
while len(output) < length:
hash_input = seed + counter.to_bytes(4, 'big')
output += hashlib.sha256(hash_input).digest()
counter += 1
return output[:length]
后量子密码学
NIST 标准化算法
CRYSTALS-Kyber (密钥封装):
- 基于格密码学
- 安全级别:Kyber512/768/1024
- 抗量子攻击
CRYSTALS-Dilithium (数字签名):
- 基于格密码学
- 安全级别:Dilithium2/3/5
- 签名长度较大
混合部署策略
class HybridKeyExchange:
def __init__(self):
self.classical = ECDHE_P256()
self.post_quantum = Kyber768()
def generate_keys(self):
# 生成两套密钥对
classical_keys = self.classical.generate_keypair()
pq_keys = self.post_quantum.generate_keypair()
return {
'classical': classical_keys,
'post_quantum': pq_keys
}
def derive_shared_secret(self, my_keys, peer_public_keys):
# 计算两个共享密钥
classical_secret = self.classical.compute_shared_secret(
my_keys['classical']['private'],
peer_public_keys['classical']
)
pq_secret = self.post_quantum.decapsulate(
my_keys['post_quantum']['private'],
peer_public_keys['post_quantum']
)
# 组合两个密钥
combined_secret = hkdf_extract(
classical_secret,
pq_secret
)
return combined_secret
总结
现代 TLS 加密算法的选择原则:
- 对称加密:优先 AEAD 模式(AES-GCM、ChaCha20-Poly1305)
- 非对称加密:ECDHE + ECDSA/EdDSA,逐步淘汰 RSA
- 哈希算法:SHA-256 为主,SHA-3 备选
- 性能优化:利用硬件加速,选择高效曲线
- 未来准备:关注后量子算法,准备混合部署
理解这些算法的数学原理和工程实现,有助于做出正确的安全配置选择。