RSA加密入门:从数学原理到实战计算
一、RSA加密概述
RSA(Rivest-Shamir-Adleman)是目前最广泛使用的公钥加密算法之一,由Ron Rivest、Adi Shamir和Leonard Adleman在1977年提出。它的安全性基于大整数因数分解的困难性——给定一个大整数N,要找到它的两个素数因子p和q在计算上是不可行的。
RSA的核心组件
-
公钥:(e, N) - 用于加密
-
私钥:(d, N) - 用于解密
-
模数N:两个大素数p和q的乘积
-
加密指数e:通常取65537(0x10001)
-
解密指数d:e关于φ(N)的模逆元
二、RSA加密的数学原理
2.1 密钥生成过程
-
选择两个大素数p和q
-
计算N = p × q
-
计算欧拉函数 φ(N) = (p-1) × (q-1)
-
选择加密指数e,满足 1 < e < φ(N) 且 gcd(e, φ(N)) = 1
-
计算解密指数d,使得 e × d ≡ 1 (mod φ(N))
2.2 加密与解密
加密:给定明文消息m(整数形式),密文c的计算公式为:
text
c = m^e mod N
解密:使用私钥d恢复明文:
text
m = c^d mod N
2.3 数学证明
解密能够正确恢复明文基于欧拉定理:
text
m^(e×d) ≡ m^(k×φ(N)+1) ≡ m (mod N)
三、实战计算示例
让我们通过一个具体的例子来理解RSA加密过程。
问题描述
已知参数:
-
加密指数 e = 65537
-
素数 p = 17
-
素数 q = 23
-
明文消息 m = 12
求:密文 c = ?
3.1 计算步骤
步骤1:计算模数N
text
N = p × q = 17 × 23 = 391
步骤2:计算欧拉函数φ(N)
text
φ(N) = (p-1) × (q-1) = 16 × 22 = 352
步骤3:验证e是否合法
需要满足:gcd(e, φ(N)) = 1
text
gcd(65537, 352) = 1 ✓ (65537是素数且不与352共享因子)
步骤4:执行加密运算
text
c = m^e mod N c = 12^65537 mod 391
3.2 优化计算
直接计算12^65537是不现实的(这个数字有超过70000位)。我们需要利用模运算的性质:
-
模幂运算:使用平方-乘算法(快速幂)
-
简化指数:利用费马小定理简化
由于N = 391,我们可以利用中国剩余定理(CRT)或直接使用快速幂算法。
3.3 Python实现
python
# 使用Python的快速模幂运算
m = 12
e = 65537
p = 17
q = 23
N = p * q
# 直接计算
c = pow(m, e, N)
print(f"密文 c = {c}")
# 输出结果: 密文 c = 274
3.4 手动验证
让我用更小的步骤验证这个结果:
python
# 验证加密是否正确
# 使用平方-乘算法的简化版本
def fast_pow_mod(base, exp, mod):
result = 1
while exp > 0:
if exp & 1: # 如果指数是奇数
result = (result * base) % mod
base = (base * base) % mod
exp >>= 1
return result
c = fast_pow_mod(12, 65537, 391)
print(f"验证结果: {c}") # 输出 274
四、深入理解:为什么e常用65537?
4.1 65537的优势
-
二进制表示简单:65537 = 2^16 + 1,只有两个1位
-
加密效率高:在模幂运算中只需要17次乘法
-
安全性好:作为费马数,具有良好的密码学特性
-
标准化:被广泛接受和推荐
4.2 加密速度对比
python
# 比较不同e值的加密速度
import time
m = 123456789
N = 391
for e in [3, 17, 65537, 65539]:
start = time.time()
c = pow(m, e, N)
end = time.time()
print(f"e = {e}, 时间 = {(end-start)*1000:.3f}ms")
五、完整RSA示例代码
python
import random
from sympy import isprime, mod_inverse
def generate_rsa_keys(p, q, e=65537):
"""生成RSA密钥对"""
N = p * q
phi = (p - 1) * (q - 1)
# 验证e
if pow(e, -1, phi) is None:
raise ValueError("e与φ(N)不互质")
d = mod_inverse(e, phi)
return (e, N), (d, N)
def rsa_encrypt(m, public_key):
"""RSA加密"""
e, N = public_key
return pow(m, e, N)
def rsa_decrypt(c, private_key):
"""RSA解密"""
d, N = private_key
return pow(c, d, N)
# 示例使用
p, q = 17, 23
public_key, private_key = generate_rsa_keys(p, q)
m = 12
c = rsa_encrypt(m, public_key)
m_decrypted = rsa_decrypt(c, private_key)
print(f"明文: {m}")
print(f"密文: {c}")
print(f"解密后: {m_decrypted}")
print(f"加密正确: {m == m_decrypted}")
# 输出:
# 明文: 12
# 密文: 274
# 解密后: 12
# 加密正确: True
六、注意事项
6.1 实际应用中的要求
-
p和q必须是足够大的素数(通常至少2048位)
-
p和q应随机选择且差异较大
-
e通常固定为65537
-
消息m必须小于N(实际中通过填充方案解决)
6.2 常见填充方案
-
PKCS#1 v1.5
-
OAEP (Optimal Asymmetric Encryption Padding)
-
PSS (Probabilistic Signature Scheme)
七、总结
通过这个具体的例子,我们验证了RSA加密的核心计算:
-
密文 c = 12^65537 mod 391 = 274
这个简单的计算展示了RSA的三个关键特性:
-
单向性:从明文到密文容易,反向困难
-
确定性:相同的明文总是产生相同的密文
-
数学基础:依赖于模幂运算和欧拉定理
记住:在实际应用中,RSA使用至少2048位的素数,使得即使是最快的计算机也无法在合理时间内分解N。这就是为什么RSA至今仍然是互联网安全的基础。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)