2、对称加密基础:AES算法原理、密钥长度选择(128/256)、ECB与CBC模式对比
好,咱们进入正题。对称加密,说白了就是加密和解密用同一把钥匙。你想想看,医疗体温计采集的数据,从传感器到云端,中间要经过蓝牙、Wi-Fi,万一被截获了怎么办?这时候就需要一把锁,把数据锁起来。AES就是目前最通用的那把锁。
2.1 AES算法原理:它到底是怎么工作的?
AES,全称是Advanced Encryption Standard,高级加密标准。它不是那种复杂的数学怪兽,而是一套精心设计的“替换-置换”网络。我刚开始接触时也觉得头大,但拆开来看,其实就四个核心操作:
- SubBytes(字节代换):用一个固定的S盒,把每个字节替换成另一个字节。这步是非线性的,目的是混淆数据。
- ShiftRows(行移位):把状态矩阵的每一行向左循环移位。第一行不动,第二行移1位,第三行移2位,第四行移3位。目的是扩散。
- MixColumns(列混合):把每一列的四个字节,通过矩阵乘法混合在一起。这一步进一步扩散。
- AddRoundKey(轮密钥加):把当前状态和本轮的子密钥进行异或操作。这是唯一用到密钥的步骤。
这四步反复执行多轮。具体轮数取决于密钥长度:10轮(128位)、12轮(192位)、14轮(256位)。
核心要点:AES不是一次性加密整个数据块,而是把数据分成16字节(128位)一块,一块一块地处理。这就是“分组密码”的含义。
我在项目中遇到过一个问题:有人觉得AES太慢,想用更简单的算法。嗯,千万别这么干。AES在硬件上(比如体温计的MCU)有专门的指令集加速,速度其实非常快。你想想看,一个体温计芯片,跑AES-128加密一个16字节的数据块,通常只需要几十微秒。这点延迟,对体温采集来说完全可以忽略。
2.2 密钥长度选择:128位还是256位?
这是大家最纠结的问题。AES支持三种密钥长度:128、192、256位。我个人的建议是:医疗数据场景,优先选AES-256。
为什么?
- AES-128:安全强度足够,破解需要2^128次尝试。目前没有任何公开方法能有效破解。但量子计算机出现后,Grover算法可以把强度降到2^64次尝试。虽然短期内不可能,但医疗数据通常需要保存几十年(比如病历),你得考虑未来。
- AES-256:安全强度是2^256次尝试。量子计算机也只能降到2^128次。说白了,就是“后量子时代”也够用。
- 性能差异:AES-256比AES-128多4轮运算(14轮 vs 10轮),速度慢大约40%。但在体温计这种低频数据采集场景下,完全不是问题。你一天测几次体温?每次加密几个字节?那点性能差异根本感觉不到。
避坑指南:我曾经见过一个项目,为了省电选了AES-128,结果客户要求数据保存20年。后来合规审查时被要求升级到AES-256,整个固件都得重写。所以,一开始就选256,省得后面折腾。
我建议的密钥长度选择原则:
- 普通消费类产品(比如智能手环):AES-128够用
- 医疗数据(体温、心率等):AES-256起步
- 涉及诊断、处方等敏感信息:必须AES-256
2.3 ECB与CBC模式对比:别踩这个坑
AES本身只定义了如何加密一个16字节的数据块。但实际数据往往不止16字节,所以需要一种“工作模式”来把多个块串起来。ECB和CBC是最常见的两种。
ECB模式(电子密码本模式)
ECB最简单:每个16字节块独立加密,互不影响。你想想看,这有什么问题?
问题大了。同样的明文块,加密后得到同样的密文块。如果数据有规律(比如体温数据大多是36.5°C左右),那么密文也会呈现规律性。攻击者不需要解密,光看密文模式就能猜出数据的大致分布。
经典案例:我见过一个体温计项目,用ECB模式加密。结果密文里每隔几个字节就出现重复模式。稍微懂点密码学的人一看就知道:这数据肯定有规律。虽然他不知道具体数值,但知道“这些数据是重复的”本身就是信息泄露。
所以,ECB模式绝对不能用于医疗数据。它只适合加密随机数据(比如密钥本身)。
CBC模式(密码分组链接模式)
CBC模式解决了ECB的问题。它的做法是:每个明文块先和前一个密文块异或,然后再加密。这样,同样的明文块,因为前一个密文块不同,加密结果也不同。
CBC需要一个初始向量(IV)。IV是随机生成的,每次加密都不同。即使加密同样的数据,只要IV不同,密文就完全不同。
我个人的习惯是:所有医疗数据加密,一律用CBC模式。虽然它比ECB慢一点点(因为不能并行加密),但安全性提升是质的飞跃。
| 特性 | ECB模式 | CBC模式 |
|---|---|---|
| 安全性 | 低(明文模式泄露) | 高(相同明文不同密文) |
| 并行加密 | 支持 | 不支持 |
| 错误传播 | 仅影响当前块 | 影响当前块及后续块 |
| 是否需要IV | 不需要 | 需要(随机生成) |
| 适用场景 | 随机数据加密 | 通用数据加密(推荐) |
小技巧:CBC模式的IV不需要保密,但必须随机且每次不同。我通常的做法是:把IV直接放在密文前面一起传输。解密时先取出前16字节作为IV,再解密后面的密文。这样既简单又安全。
2.4 代码示例:用Python实现AES-CBC加密
下面是一个简单的示例,演示如何在Python中使用AES-256-CBC加密体温数据。注意,实际项目中密钥和IV要安全存储,不能硬编码。
from Crypto.Cipher import AES
import os
# 密钥:32字节(256位)
key = os.urandom(32)
# 初始向量:16字节
iv = os.urandom(16)
# 待加密数据(体温数据,假设为36.5°C)
plaintext = b"36.5"
# 填充数据到16字节倍数(PKCS7填充)
def pad(data):
padding_len = 16 - (len(data) % 16)
return data + bytes([padding_len] * padding_len)
# 加密
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(pad(plaintext))
# 实际传输时:iv + ciphertext 一起发送
print("IV:", iv.hex())
print("密文:", ciphertext.hex())
嗯,这里要注意:实际体温数据可能是浮点数,需要先序列化成字节。我习惯用struct.pack或者直接转成字符串再编码。另外,密钥管理是另一个大话题,后面章节会详细讲。
2.5 总结与避坑
- 选AES-256:医疗数据至少保存10年以上,别省那点性能。
- 用CBC模式:ECB模式在医疗场景下就是定时炸弹。
- IV必须随机:每次加密生成新的IV,不要复用。
- 密钥不能硬编码:密钥要存储在安全区域(如MCU的OTP或安全芯片)。
我曾经踩过的坑:有一次,我把密钥写死在固件里,结果固件被反编译,密钥直接暴露。从那以后,我所有项目的密钥都通过安全通道分发,或者使用硬件安全模块(HSM)存储。记住:密钥泄露,加密就形同虚设。
好了,对称加密的基础就讲到这里。下一章我们会讲非对称加密和数字签名,那是另一套玩法。你想想看,体温计的数据到了云端,怎么确认它没有被篡改?那就是非对称加密的用武之地了。