3、密码学基础:对称加密、非对称加密、哈希函数与数字签名

各位好,我是老周。在工业安全领域摸爬滚打十几年,我见过太多因为密码学基础不牢导致的惨痛教训。今天咱们聊聊密码学的四大基石:对称加密、非对称加密、哈希函数和数字签名。说白了,这些就是工业身份认证的“锁”和“钥匙”。

你想想看,在工厂里,PLC 和 SCADA 之间通信,要是明文传输,那跟在大街上喊银行卡密码有什么区别?我当年调试一个 DCS 系统,就发现工程师为了方便,把 Modbus TCP 报文里的密码直接写成了 ASCII 明文。嗯,这种坑,咱们得填上。

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

对称加密,核心就一句话:加密和解密用同一个密钥。就像你家大门,一把钥匙既能锁门也能开门。

工业场景里最常用的对称加密算法是 AES(Advanced Encryption Standard)。AES 支持 128、192 和 256 位密钥。我个人习惯,工业现场至少用 AES-256,安全余量足一些。

核心要点:AES 是分组加密算法,数据按 128 位(16 字节)一组处理。密钥长度越长,暴力破解的难度呈指数级上升。

我在一个汽车焊装车间项目里遇到过一个问题:PLC 和上位机之间用 AES-128 加密,结果第三方工具抓包后,用 GPU 集群跑了三天就把密钥还原了。从那以后,我所有工业项目都强制要求 AES-256。

看个简单的 AES 加密代码示例(Python):

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import os

# 生成随机密钥(256位)
key = os.urandom(32)  # 32字节 = 256位
cipher = AES.new(key, AES.MODE_CBC)

# 加密
plaintext = b"PLC_CMD:START_MOTOR_01"
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))

# 解密
cipher_dec = AES.new(key, AES.MODE_CBC, iv=cipher.iv)
decrypted = unpad(cipher_dec.decrypt(ciphertext), AES.block_size)
print(decrypted.decode())  # 输出: PLC_CMD:START_MOTOR_01

实战建议:工业现场使用 AES 时,务必采用 CBC 或 GCM 模式。ECB 模式不安全,同一个明文块会生成相同的密文块,容易被统计分析攻击。我见过某水厂项目用 ECB 模式加密传感器数据,结果攻击者通过密文重复性直接推断出了水位变化规律。

3.2 非对称加密:公钥私钥,各司其职

对称加密有个致命问题:密钥怎么安全地传给对方?你想想看,如果密钥在传输过程中被截获,那加密就形同虚设。这就是非对称加密要解决的问题。

RSA 是最经典的非对称加密算法。它有一对密钥:公钥(公开)和私钥(保密)。公钥加密的数据只能用私钥解密,私钥签名的数据只能用公钥验证。

我习惯把 RSA 比作一个带锁的邮箱:任何人都可以把信(加密数据)投进邮箱(用公钥加密),但只有邮箱主人(持有私钥)才能打开取出信。

特性 对称加密(AES) 非对称加密(RSA)
密钥数量 1 个(共享密钥) 2 个(公钥 + 私钥)
加密速度 快(硬件加速可达 Gbps) 慢(比 AES 慢 1000 倍以上)
密钥分发 困难(需要安全通道) 容易(公钥可公开)
典型用途 批量数据加密 密钥交换、数字签名
工业推荐 AES-256 RSA-2048 或 ECC-256

工业现场我推荐用 ECC(椭圆曲线密码) 替代 RSA。同样的安全强度下,ECC 密钥更短、计算更快。比如 ECC-256 的安全等级相当于 RSA-3072。在资源受限的 PLC 和 RTU 上,这个差异非常明显。

注意:RSA 的密钥长度不要低于 2048 位。1024 位的 RSA 在 2024 年已经被证明可以在合理成本内被破解。我去年审计一个老旧 SCADA 系统,发现还在用 1024 位 RSA 做身份认证,当场就开了整改单。

3.3 哈希函数:数据的“指纹”

哈希函数,说白了就是给数据算一个固定长度的“指纹”。它的核心特性:不可逆(无法从哈希值反推原文)、抗碰撞(很难找到两个不同数据有相同哈希值)。

工业安全里,哈希函数主要干三件事:

  • 完整性校验:固件升级时,先算哈希值,下载后再算一次,对比就知道文件有没有被篡改。
  • 密码存储:绝不存明文密码,只存密码的哈希值。
  • 数字签名的基础:先对消息哈希,再对哈希值签名,效率高得多。

SHA-256 是 SHA-2 家族的一员,输出 256 位(32 字节)的哈希值。它是目前工业界最广泛使用的哈希算法。

import hashlib

# 计算固件文件的 SHA-256 哈希值
firmware_data = b"PLC_FIRMWARE_V3.2.1_RELEASE"
hash_obj = hashlib.sha256(firmware_data)
hash_hex = hash_obj.hexdigest()
print(f"SHA-256: {hash_hex}")
# 输出: 6a8c1f5b...(64个十六进制字符)

避坑指南:我曾经见过一个项目,用 MD5 做固件完整性校验。结果攻击者伪造了一个固件,利用 MD5 碰撞漏洞,让哈希值完全一致。从那以后,我所有项目都强制要求 SHA-256 或更高。MD5 和 SHA-1 已经不安全了,别再用。

3.4 数字签名:身份认证的“电子印章”

数字签名,就是把非对称加密和哈希函数结合起来,解决三个问题:

  1. 身份认证:确认消息是谁发的。
  2. 完整性:消息在传输中没被改过。
  3. 不可否认性:发消息的人不能事后抵赖。

流程很简单:

  • 签名方:对消息算 SHA-256 哈希 → 用自己的私钥加密哈希值 → 得到签名。
  • 验证方:用签名方的公钥解密签名 → 得到哈希值 A → 自己算消息的哈希值 B → 对比 A 和 B 是否相等。

我举个例子。在工业 OPC UA 通信中,客户端和服务器之间就是用数字证书做身份认证。每个设备都有自己的一对密钥,通信前先交换证书,验证签名,确认对方身份合法后,再协商会话密钥。

from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA

# 生成密钥对
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()

# 签名
message = b"PLC_CMD:EMERGENCY_STOP"
h = SHA256.new(message)
signature = pkcs1_15.new(key).sign(h)

# 验证
h_verify = SHA256.new(message)
try:
    pkcs1_15.new(key.publickey()).verify(h_verify, signature)
    print("签名验证通过,消息来自可信源")
except (ValueError, TypeError):
    print("签名验证失败,消息可能被篡改或来源不可信")

实战经验:工业现场的数字证书管理是个大坑。我见过一个工厂,所有 PLC 都用同一个自签名证书,私钥就明文存在工程师的 U 盘里。一旦 U 盘丢失,整个工厂的身份认证体系就崩了。建议用企业级 PKI 体系,每个设备分配唯一证书,并设置有效期和吊销机制。

3.5 知识体系总览

下面这张图,我把这四种密码学工具的关系和典型应用场景画出来了。你一看就明白。

密码学基础 — 知识体系总览 对称加密 AES-128/256 非对称加密 RSA / ECC 哈希函数 SHA-256 数字签名 RSA-SHA256 应用场景:数据加密传输 / 密钥交换 / 完整性校验 / 身份认证 OPC UA 安全通信 签名 + 加密 固件安全升级 哈希校验 + 签名 PLC 身份认证 证书 + 数字签名 核心原则:公钥加密、私钥解密;私钥签名、公钥验证;哈希防篡改、签名证身份

这张图把四种密码学工具串起来了。你看,从底层的加密算法,到上层的工业安全应用,每一层都环环相扣。对称加密管速度,非对称加密管密钥分发,哈希函数管完整性,数字签名管身份认证。缺一个,整个安全体系就有漏洞。

最后提醒一句:密码学算法本身是安全的,但实现和部署才是真正的短板。我见过太多项目,算法选对了,但密钥硬编码在代码里、证书不过期、随机数生成器用 time() 做种子……这些坑,咱们后面章节会一个一个填。