Skip to content

对称加密和非对称加密全面详解

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位
- 特点: 快速,免费使用

流密码

# ChaCha20
- 密钥长度: 256位
- 特点: 移动设备上性能优秀,被Google广泛使用

# RC4 - 已不安全
- 曾经流行,但存在严重漏洞
- 现状: 绝对不要使用

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)

# 常用模式
优点: 每个块依赖于前一个块,安全性好
缺点: 不能并行加密,需要初始化向量(IV)

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}")

3. 非对称加密

3.1 基本概念

非对称加密使用一对密钥:公钥和私钥。

  • 公钥:公开给所有人,用于加密

  • 私钥:严格保密,用于解密

加密:明文 + 公钥 → 加密算法 → 密文
解密:密文 + 私钥 → 解密算法 → 明文

3.2 工作原理示意图

发送方:
明文 "Hello" + 接收方公钥
    → RSA加密
    → 密文 "AbCxYz123"

接收方:
密文 "AbCxYz123" + 接收方私钥
    → RSA解密
    → 明文 "Hello"

3.3 主要特点

  • ✅ 解决密钥分发问题

  • ✅ 支持数字签名

  • ✅ 密钥管理简单

  • ❌ 加密速度慢

  • ❌ 不适合加密大量数据

3.4 常见非对称加密算法

RSA (Rivest-Shamir-Adleman)

# 基于大数分解难题
- 密钥长度: 通常2048位或4096位
- 应用: 数字签名、密钥交换
- 特点: 最广泛使用的非对称算法

ECC (Elliptic Curve Cryptography)

# 基于椭圆曲线离散对数问题
- 密钥长度: 256-521位
- 特点: 更短的密钥,更高的安全性
- 应用: 移动设备、TLS证书

Diffie-Hellman

# 密钥交换协议
- 不用于加密,只用于密钥协商
- 应用: TLS、SSH、VPN

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 优势

# 密钥大小对比(相同安全级别)
RSA 2048位 ≈ ECC 224位
RSA 3072位 ≈ ECC 256位
RSA 7680位 ≈ ECC 384位

常见椭圆曲线

- P-256 (secp256r1): 最常用
- P-384 (secp384r1): 更高安全
- P-521 (secp521r1): 最高安全
- Curve25519: 现代,性能好

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()

4. 两种加密方式的对比

4.1 全面对比表格

特性 对称加密 非对称加密
密钥数量 1个共享密钥 1对密钥(公钥+私钥)
加密速度 快(10-1000MB/s) 慢(0.1-1MB/s)
密钥长度 128-256位 2048-4096位(RSA)
安全性基础 密钥保密性 数学难题(分解、离散对数)
密钥分发 困难,需要安全通道 容易,公钥可公开
适用场景 大量数据加密 密钥交换、数字签名
典型算法 AES, ChaCha20 RSA, ECC, DSA
资源消耗 低 高

4.2 性能对比数据

# 加密速度大致对比(相同安全级别)
AES-256: ~200 MB/s
RSA-2048: ~0.5 MB/s
ECC-256: ~2 MB/s

# 密钥大小对比
AES-256: 256位密钥
RSA-2048: 2048位密钥(但加密强度≈112位)
ECC-256: 256位密钥(加密强度≈128位)

5. 实际应用场景

5.1 混合加密系统

在实际应用中,通常结合两种加密方式的优点:

TLS/SSL 握手过程

1. 客户端连接服务器
2. 服务器发送证书(包含公钥)
3. 客户端验证证书
4. 客户端生成随机对称密钥
5. 客户端用服务器公钥加密对称密钥
6. 服务器用私钥解密得到对称密钥
7. 双方使用对称密钥加密通信数据

SSH 密钥交换

1. 客户端和服务器协商加密参数
2. 使用Diffie-Hellman交换密钥
3. 生成会话对称密钥
4. 使用对称密钥加密后续通信

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)

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 性能优化

# 使用混合加密处理大文件
def encrypt_large_file(file_path, public_key):
    # 生成临时对称密钥
    session_key = os.urandom(32)

    # 使用对称密钥加密文件(快速)
    encrypted_file = aes_encrypt_large_file(file_path, session_key)

    # 使用公钥加密对称密钥(安全)
    encrypted_key = rsa_encrypt(session_key, public_key)

    return encrypted_key + encrypted_file

7. 现代加密发展趋势

7.1 后量子密码学

# 应对量子计算机威胁
- 基于格的加密 (Lattice-based)
- 基于编码的加密 (Code-based)
- 多元多项式加密 (Multivariate)
- 基于哈希的签名 (Hash-based)

7.2 同态加密

# 在加密数据上直接计算
- 允许对密文进行运算
- 结果解密后与对明文运算相同
- 应用于隐私保护数据分析

7.3 零知识证明

# 证明知道秘密而不泄露秘密
- zk-SNARKs
- zk-STARKs
- 应用于区块链和身份验证