对称加密和非对称加密全面详解
1. 密码学基础概念
1.1 加密的目的
-
机密性:防止未授权访问数据
-
完整性:确保数据未被篡改
-
身份验证:确认通信双方身份
-
不可否认性:防止发送方否认发送过消息
1.2 基本术语
-
明文:原始可读数据
-
密文:加密后的数据
-
密钥:用于加密和解密的参数
-
加密算法:将明文转换为密文的数学函数
-
解密算法:将密文转换为明文的数学函数
2. 对称加密
2.1 基本概念
对称加密使用相同的密钥进行加密和解密。
2.2 工作原理示意图
发送方:
明文 "Hello" + 密钥 "secret123"
→ AES加密
→ 密文 "X5gHk2@9"
接收方:
密文 "X5gHk2@9" + 密钥 "secret123"
→ AES解密
→ 明文 "Hello"
2.3 主要特点
-
✅ 加解密使用相同密钥
-
✅ 加密速度快,适合大量数据
-
✅ 算法效率高
-
❌ 密钥分发困难
-
❌ 密钥管理复杂
2.4 常见对称加密算法
分组密码
# AES (Advanced Encryption Standard)
- 密钥长度: 128, 192, 256位
- 分组大小: 128位
- 特点: 目前最安全、最常用的对称加密算法
# DES (Data Encryption Standard) - 已不安全
- 密钥长度: 56位
- 分组大小: 64位
- 现状: 已被破解,不推荐使用
# 3DES (Triple DES)
- 对DES进行三次加密
- 密钥长度: 168位(实际安全强度112位)
- 现状: 逐渐被AES替代
# Blowfish
- 密钥长度: 32-448位
- 分组大小: 64位
- 特点: 快速,免费使用
流密码
2.5 AES 算法详解
AES 加密过程
# 伪代码示例
def aes_encrypt(plaintext, key):
# 1. 密钥扩展
expanded_key = key_expansion(key)
# 2. 初始轮密钥加
state = add_round_key(plaintext, expanded_key[0])
# 3. 主要轮函数(重复10-14次)
for round in range(1, total_rounds):
state = sub_bytes(state) # 字节替换
state = shift_rows(state) # 行移位
state = mix_columns(state) # 列混淆
state = add_round_key(state, expanded_key[round])
# 4. 最终轮(无列混淆)
state = sub_bytes(state)
state = shift_rows(state)
state = add_round_key(state, expanded_key[total_rounds])
return state
AES 密钥长度与轮数
| 密钥长度 | 轮数 | 安全级别 |
|---|---|---|
| 128位 | 10轮 | 标准 |
| 192位 | 12轮 | 较高 |
| 256位 | 14轮 | 最高 |
2.6 对称加密的使用模式
ECB (Electronic Codebook)
CBC (Cipher Block Chaining)
CTR (Counter Mode)
2.7 代码示例
Python 实现 AES
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
def aes_encrypt(plaintext, key):
# 生成随机IV
iv = os.urandom(16)
# 创建加密器
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
# 加密(需要填充到16字节边界)
padded_plaintext = plaintext + b' ' * (16 - len(plaintext) % 16)
ciphertext = encryptor.update(padded_plaintext) + encryptor.finalize()
return iv + ciphertext
def aes_decrypt(ciphertext, key):
# 提取IV
iv = ciphertext[:16]
actual_ciphertext = ciphertext[16:]
# 创建解密器
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
# 解密
plaintext = decryptor.update(actual_ciphertext) + decryptor.finalize()
return plaintext.rstrip()
# 使用示例
key = os.urandom(32) # 256位密钥
plaintext = b"Hello, World!"
ciphertext = aes_encrypt(plaintext, key)
decrypted = aes_decrypt(ciphertext, key)
print(f"解密结果: {decrypted}")
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
def aes_encrypt(plaintext, key):
# 生成随机IV
iv = os.urandom(16)
# 创建加密器
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
# 加密(需要填充到16字节边界)
padded_plaintext = plaintext + b' ' * (16 - len(plaintext) % 16)
ciphertext = encryptor.update(padded_plaintext) + encryptor.finalize()
return iv + ciphertext
def aes_decrypt(ciphertext, key):
# 提取IV
iv = ciphertext[:16]
actual_ciphertext = ciphertext[16:]
# 创建解密器
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
# 解密
plaintext = decryptor.update(actual_ciphertext) + decryptor.finalize()
return plaintext.rstrip()
# 使用示例
key = os.urandom(32) # 256位密钥
plaintext = b"Hello, World!"
ciphertext = aes_encrypt(plaintext, key)
decrypted = aes_decrypt(ciphertext, key)
print(f"解密结果: {decrypted}")
3. 非对称加密
3.1 基本概念
非对称加密使用一对密钥:公钥和私钥。
-
公钥:公开给所有人,用于加密
-
私钥:严格保密,用于解密
3.2 工作原理示意图
3.3 主要特点
-
✅ 解决密钥分发问题
-
✅ 支持数字签名
-
✅ 密钥管理简单
-
❌ 加密速度慢
-
❌ 不适合加密大量数据
3.4 常见非对称加密算法
RSA (Rivest-Shamir-Adleman)
ECC (Elliptic Curve Cryptography)
Diffie-Hellman
3.5 RSA 算法详解
RSA 密钥生成
# 伪代码
def generate_rsa_keys():
# 1. 选择两个大质数 p 和 q
p = generate_large_prime()
q = generate_large_prime()
# 2. 计算 n = p * q
n = p * q
# 3. 计算欧拉函数 φ(n) = (p-1)*(q-1)
phi = (p - 1) * (q - 1)
# 4. 选择公钥指数 e (通常为65537)
e = 65537
# 5. 计算私钥指数 d = e^(-1) mod φ(n)
d = modular_inverse(e, phi)
# 公钥: (e, n), 私钥: (d, n)
return (e, n), (d, n)
RSA 加密解密
def rsa_encrypt(plaintext, public_key):
e, n = public_key
# 加密: ciphertext = plaintext^e mod n
ciphertext = pow(plaintext, e, n)
return ciphertext
def rsa_decrypt(ciphertext, private_key):
d, n = private_key
# 解密: plaintext = ciphertext^d mod n
plaintext = pow(ciphertext, d, n)
return plaintext
3.6 椭圆曲线密码学 (ECC)
ECC 优势
常见椭圆曲线
3.7 代码示例
Python 实现 RSA
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
def rsa_demo():
# 生成RSA密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# 加密
plaintext = b"Hello, RSA!"
ciphertext = public_key.encrypt(
plaintext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 解密
decrypted = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f"原始: {plaintext}")
print(f"解密: {decrypted}")
rsa_demo()
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
def rsa_demo():
# 生成RSA密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
# 加密
plaintext = b"Hello, RSA!"
ciphertext = public_key.encrypt(
plaintext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 解密
decrypted = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(f"原始: {plaintext}")
print(f"解密: {decrypted}")
rsa_demo()
4. 两种加密方式的对比
4.1 全面对比表格
| 特性 | 对称加密 | 非对称加密 |
|---|---|---|
| 密钥数量 | 1个共享密钥 | 1对密钥(公钥+私钥) |
| 加密速度 | 快(10-1000MB/s) | 慢(0.1-1MB/s) |
| 密钥长度 | 128-256位 | 2048-4096位(RSA) |
| 安全性基础 | 密钥保密性 | 数学难题(分解、离散对数) |
| 密钥分发 | 困难,需要安全通道 | 容易,公钥可公开 |
| 适用场景 | 大量数据加密 | 密钥交换、数字签名 |
| 典型算法 | AES, ChaCha20 | RSA, ECC, DSA |
| 资源消耗 | 低 | 高 |
4.2 性能对比数据
5. 实际应用场景
5.1 混合加密系统
在实际应用中,通常结合两种加密方式的优点:
TLS/SSL 握手过程
1. 客户端连接服务器
2. 服务器发送证书(包含公钥)
3. 客户端验证证书
4. 客户端生成随机对称密钥
5. 客户端用服务器公钥加密对称密钥
6. 服务器用私钥解密得到对称密钥
7. 双方使用对称密钥加密通信数据
SSH 密钥交换
5.2 数字签名
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
def digital_signature_demo():
# 生成密钥
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
message = b"Important document"
# 签名
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# 验证签名
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("签名验证成功!")
except Exception as e:
print("签名验证失败!", e)
5.3 实际应用示例
安全文件传输
import os
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
class SecureFileTransfer:
def __init__(self):
# 生成RSA密钥对
self.private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
self.public_key = self.private_key.public_key()
def encrypt_file(self, file_path, recipient_public_key):
# 生成随机对称密钥
symmetric_key = os.urandom(32) # AES-256
iv = os.urandom(16) # 初始化向量
# 使用对称密钥加密文件
with open(file_path, 'rb') as f:
plaintext = f.read()
cipher = Cipher(algorithms.AES(symmetric_key), modes.CBC(iv))
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
# 使用接收方公钥加密对称密钥
encrypted_key = recipient_public_key.encrypt(
symmetric_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return encrypted_key + iv + ciphertext
def decrypt_file(self, encrypted_data, output_path):
# 提取各部分数据
encrypted_key = encrypted_data[:256] # RSA加密的对称密钥
iv = encrypted_data[256:272] # 初始化向量
ciphertext = encrypted_data[272:] # AES加密的文件内容
# 使用私钥解密对称密钥
symmetric_key = self.private_key.decrypt(
encrypted_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 使用对称密钥解密文件
cipher = Cipher(algorithms.AES(symmetric_key), modes.CBC(iv))
decryptor = cipher.decryptor()
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
with open(output_path, 'wb') as f:
f.write(plaintext)
import os
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
class SecureFileTransfer:
def __init__(self):
# 生成RSA密钥对
self.private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
self.public_key = self.private_key.public_key()
def encrypt_file(self, file_path, recipient_public_key):
# 生成随机对称密钥
symmetric_key = os.urandom(32) # AES-256
iv = os.urandom(16) # 初始化向量
# 使用对称密钥加密文件
with open(file_path, 'rb') as f:
plaintext = f.read()
cipher = Cipher(algorithms.AES(symmetric_key), modes.CBC(iv))
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
# 使用接收方公钥加密对称密钥
encrypted_key = recipient_public_key.encrypt(
symmetric_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return encrypted_key + iv + ciphertext
def decrypt_file(self, encrypted_data, output_path):
# 提取各部分数据
encrypted_key = encrypted_data[:256] # RSA加密的对称密钥
iv = encrypted_data[256:272] # 初始化向量
ciphertext = encrypted_data[272:] # AES加密的文件内容
# 使用私钥解密对称密钥
symmetric_key = self.private_key.decrypt(
encrypted_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 使用对称密钥解密文件
cipher = Cipher(algorithms.AES(symmetric_key), modes.CBC(iv))
decryptor = cipher.decryptor()
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
with open(output_path, 'wb') as f:
f.write(plaintext)
6. 安全考虑和最佳实践
6.1 密钥管理
# 对称密钥管理
- 使用密钥派生函数(KDF)从密码生成密钥
- 定期更换密钥
- 安全存储密钥
# 非对称密钥管理
- 使用硬件安全模块(HSM)保护私钥
- 实施证书生命周期管理
- 定期更新密钥对
6.2 算法选择建议
# 对称加密推荐
✅ AES-256 (GCM或CTR模式)
✅ ChaCha20-Poly1305
# 非对称加密推荐
✅ RSA-2048 (最低) 或 RSA-4096
✅ ECC P-256 或 Curve25519
# 避免使用的算法
❌ DES, 3DES, RC4, MD5, SHA1
6.3 性能优化
7. 现代加密发展趋势
7.1 后量子密码学
# 应对量子计算机威胁
- 基于格的加密 (Lattice-based)
- 基于编码的加密 (Code-based)
- 多元多项式加密 (Multivariate)
- 基于哈希的签名 (Hash-based)