加密技术基础回顾:对称加密与非对称加密

这章咱们不讲新东西,而是把地基夯一夯。说句实话,我见过不少同学一上来就冲信封加密,结果对称和非对称的概念都没整明白,后面越学越乱。好,我们从头捋一遍。

加密这件事,说白了就是把明文变成别人看不懂的密文。反过来,能解密的人再变回明文。那密钥是什么呢?你想想看,密钥就是开锁的钥匙——有了它,才能解开密文。

对称加密:一把钥匙开一把锁

对称加密是最直白的方案。加密和解密用同一把密钥。就像你家里的大门钥匙,你用它锁门,也用同一把开门。

个人习惯:我在项目中做小数据量加密时,首选对称加密——速度快,代码简单。

常用算法

  • AES — 当今最主流的对称算法。我个人习惯用 AES-256-GCM,自带认证,不怕篡改。
  • ChaCha20 — 移动端或 IoT 设备上常用,软件实现效率更高。
  • 3DES / DES — 别用了,太老,它俩已经过时。我曾经在一个遗留系统里看到还在用 DES,果断要求升级。

优势与劣势

优势劣势
加解密速度快,适合大块数据密钥分发困难——怎么把密钥安全地给对方?
算法成熟,硬件加速好每对通信方需要独立密钥,N 方通信就需要 N-1 个密钥
密钥长度相对短(256位就够)密钥泄露后,整个通信被破解

我经常跟团队说:对称加密解决的是「加密」问题,但不解决「密钥交换」问题。你想想,如果两个人想用对称加密通话,必须先偷偷见一面把密钥换好——这不现实。

我曾经踩过一个坑:在项目早期,我用对称加密存储用户敏感数据,密钥硬编码在代码里。后来代码仓库泄露,所有用户数据全废。嗯,千万别硬编码密钥。

非对称加密:公钥锁,私钥开

非对称加密就聪明多了。它用一对密钥:公钥和私钥。公钥公开给所有人,私钥自己藏好。你用公钥加密的数据,只有对应的私钥能解开;反过来,用私钥签名,公钥可以验签。

这解决了啥问题?——你不需要事先交换密钥。我只需要把你的公钥拿来,加密后传给你,只有你能用私钥解开。中间人就算拿到公钥和密文,也没法解密。

常用算法

  • RSA — 最经典的非对称算法。我在项目中遇到的 HTTPS 证书基本都是 RSA。
  • ECC / ECDH / ECDSA — 椭圆曲线,密钥更短,性能更好。我个人建议新项目优先考虑 ECC。
  • DSA / ElGamal — 现在用得少了,除非是某些老旧协议。

优势与劣势

优势劣势
无需预先交换密钥,公钥公开没问题加解密速度比对称加密慢几个数量级
支持数字签名,实现不可否认性密文长度比明文长(RSA 加密块有大小限制)
适合密钥分发和身份认证密钥长度长(RSA 推荐 2048 位以上)
实际经验:我做过一个文件同步工具,一开始傻乎乎用 RSA 直接加密大文件——慢到没法用。后来改成用混合加密(后面会讲),才解决问题。

对称 vs 非对称:一张表看懂

对比维度对称加密非对称加密
密钥数量1 个2 个(公钥+私钥)
加解密速度快(硬件加速可到 Gbps)慢(通常 Kbps 级别)
密钥分发难度难易(公钥公开)
常用算法AES、ChaCha20RSA、ECC、ECDH
主要用途数据加密密钥交换、签名
典型密钥长度128-256 位2048-4096 位(RSA)

混合加密?已经有人在这么做了

你肯定猜到了——对称加密快但无法安全交换密钥,非对称加密安全交换密钥但慢。怎么办?把两者结合。
混合加密:用非对称加密传输一个「会话密钥」,然后用这个对称密钥加密实际数据。这正是 HTTPS、PGP 和——你猜对了——信封加密的核心思路。

我记得刚开始学密码学那会儿,觉得混合加密是天才设计。后来自己做项目才明白,这背后全是工程妥协的结果。没有完美的加密方案,只有最适合场景的组合。

避坑指南:千万不要自己实现混合加密协议!我曾经手写过一套密钥交换逻辑,结果因为随机数生成器没种好种子,密钥空间直接缩水——差点捅大篓子。用业界标准吧,比如 TLS 或 Noise 协议。

知识体系总览

下面这张图把对称加密、非对称加密和混合加密的关系理清了。你看完后应该对整个密码学分类有个直观印象。

加密技术分类总览 加密技术 对称加密 AES ChaCha20 非对称加密 RSA ECC 混合加密 非对称交换会话密钥 对称加密大数据 要点总结 • 对称加密:快,适合大数据,但密钥分发困难 • 非对称加密:慢,适合小数据/密钥交换,公钥公开

一个小代码示例:感受一下两种加密

我用 Python 的 cryptography 库演示一下最基本的用法。不多解释,你看完就有体感了。

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
import os

# 对称加密:AES-GCM
key = os.urandom(32)          # 256位密钥
nonce = os.urandom(12)        # GCM 推荐 96位
cipher = Cipher(algorithms.AES(key), modes.GCM(nonce))
encryptor = cipher.encryptor()
ciphertext = encryptor.update(b"Hello Envelope Encryption!") + encryptor.finalize()
print(f"AES密文: {ciphertext.hex()[:32]}...")

# 非对称加密:RSA-OAEP
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
ciphertext_rsa = public_key.encrypt(
    b"short message",
    padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
)
plaintext_rsa = private_key.decrypt(
    ciphertext_rsa,
    padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
)
print(f"RSA解密正确: {plaintext_rsa == b'short message'}")
一个小提醒:上面的 RSA 示例只能加密 190 字节以内的小数据。为什么?因为 2048 位的 RSA 加密块最多能容纳那么多。这就是为什么非对称加密不适合加密大文件。