3、非对称加密基础:RSA算法原理、密钥对生成、公钥加密与私钥解密流程

好,咱们进入正题。非对称加密,说白了就是两把钥匙——一把公开,一把私藏。在医疗体温计的场景里,这玩意儿太重要了。你想想看,体温数据要是被篡改,医生误诊了怎么办?RSA就是解决这个问题的老牌选手。

3.1 RSA算法原理——数学没那么可怕

RSA的核心,其实就一个数学事实:大数分解很难。两个大质数乘起来很容易,但给你一个超大合数,想拆回两个质数?嗯,超级计算机也得算到猴年马月。

我当年第一次接触RSA时,也觉得数学公式头疼。后来我换了个角度理解——它就像一把锁:公钥是锁头,谁都能拿来锁数据;私钥是钥匙,只有你能打开。锁头扔满大街都不怕,钥匙自己藏好就行。

具体到数学层面,RSA依赖这几个东西:

  • 欧拉函数 φ(n):计算小于n且与n互质的正整数个数。对于两个质数p和q,φ(n) = (p-1)(q-1)
  • 模反元素:找到一个数d,使得 e*d ≡ 1 (mod φ(n))。这个d就是私钥的核心
  • 模幂运算:加密是 c = m^e mod n,解密是 m = c^d mod n

说白了,加密就是把你体温数据m,用公钥(e, n)做一次模幂运算,变成密文c。解密就是拿着私钥(d, n),把c再变回m。整个过程,外人没有私钥d,根本算不回去。

核心要点:RSA的安全性建立在「大整数分解困难」这个假设上。一旦量子计算机成熟,这个假设就站不住了。不过目前,2048位的RSA还是够用的。

3.2 密钥对生成——我踩过的坑

生成RSA密钥对,流程其实挺固定的。我习惯用OpenSSL来干这事,命令行几秒钟搞定。但要注意——随机数质量

我曾经在一个嵌入式项目里吃过亏。设备刚上电时,熵池还没收集够随机种子,生成的密钥对居然有规律可循。嗯,那批设备差点要召回重做。后来我强制要求:生成密钥前,必须等待熵池充足,或者用硬件随机数发生器。

标准生成流程是这样的:

  1. 选两个大质数p和q,长度至少1024位,最好2048位。它们不能太接近,否则容易被猜出来
  2. 计算 n = p × q,n的长度就是密钥长度
  3. 计算 φ(n) = (p-1)(q-1)
  4. 选一个公钥指数e,常用65537(0x10001)。为什么选它?因为它是质数,且二进制只有两个1,计算效率高
  5. 计算私钥d,满足 e×d ≡ 1 (mod φ(n))。这一步用扩展欧几里得算法
  6. 销毁p和q,只保留(n, e)作为公钥,(n, d)作为私钥

我的建议:别自己手写RSA生成逻辑。用OpenSSL、Bouncy Castle这类成熟库。自己实现?我试过,踩坑概率极高——性能问题、侧信道攻击、随机数漏洞...专业的事交给专业库。

用OpenSSL生成2048位密钥对,就这几行:

# 生成私钥
openssl genrsa -out private_key.pem 2048

# 从私钥提取公钥
openssl rsa -in private_key.pem -pubout -out public_key.pem

# 查看私钥内容(别在生产环境干这事)
openssl rsa -in private_key.pem -text -noout

生成的私钥文件里,其实包含了n、e、d、p、q、dp、dq、qinv等参数。公钥文件只包含n和e。你想想看,私钥里信息这么多,一旦泄露,整个加密体系就崩了。

3.3 公钥加密与私钥解密流程

好,密钥对有了,怎么用?在医疗体温计的场景里,流程大概是这样的:

步骤 发送方(体温计) 接收方(服务器/医生)
1 获取服务器的公钥 提前生成密钥对,公开公钥
2 用公钥加密体温数据
3 发送密文到服务器 接收密文
4 用私钥解密,得到原始体温

这里有个关键点——RSA不能加密大数据。2048位的RSA,一次最多加密245字节(2048/8 - 11,11字节是填充开销)。体温数据虽然小,但如果你要加密整个数据包,就得用混合加密:RSA加密对称密钥,对称密钥加密数据。

我参与的一个体温计项目,最初设计就是直接用RSA加密每次体温读数。结果发现:加密一次要几十毫秒,设备电池扛不住。后来改成:设备生成一个临时AES密钥,用RSA加密这个密钥,然后用AES加密体温数据。嗯,效率提升了一个数量级。

注意:RSA加密必须使用填充方案。常见的PKCS#1 v1.5填充和OAEP填充。OAEP更安全,我建议优先选它。没有填充的RSA(教科书式RSA)是脆弱的——同样的明文会得到同样的密文,攻击者可以暴力枚举。

代码示例(Python,用cryptography库):

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives import serialization

# 生成密钥对(实际项目中,服务器提前生成,体温计只存公钥)
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)
public_key = private_key.public_key()

# 公钥加密(体温计端)
temperature_data = b"36.5"  # 体温数据
ciphertext = public_key.encrypt(
    temperature_data,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# 私钥解密(服务器端)
plaintext = private_key.decrypt(
    ciphertext,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)
print(plaintext.decode())  # 输出: 36.5

你看,代码本身不复杂。但实际部署时,要考虑的事情多了去了:

  • 公钥分发:体温计怎么安全地拿到服务器公钥?预置在固件里?还是通过证书验证?
  • 密钥更新:私钥泄露了怎么办?得有吊销和更新机制
  • 性能优化:嵌入式设备的算力有限,RSA运算可能成为瓶颈
  • 侧信道防护:攻击者可能通过功耗分析、时间分析来破解密钥

总结一下:RSA是非对称加密的基石。公钥加密、私钥解密,这个流程保证了只有持有私钥的服务器能读取体温数据。但要注意:RSA不适合加密大量数据,实际应用中多用混合加密方案。密钥管理是整个体系的命门——公钥可以公开,私钥必须锁死。

下一章,我会讲如何用RSA结合AES,构建一个完整的医疗体温计加密传输方案。到时候咱们再细聊混合加密的那些坑和技巧。