非对称加密(RSA算法)原理
RSA并不是构造了一个无漏洞、无法破解的算法,而是让解密在计算上变得不可承受。
RSA的引入
很多加密场景里,密钥是加密、解密和安全性的关键,安全地传输密钥则成为了一个关键问题,
RSA算法就可以将公钥公开的发出去,而不影响私钥拥有者可以安全地解密,这一套机制就是RSA。
除了基础的加解密功能,RSA还有一个很常用的用途是那就是身份认证和验签,不过这里不讲这些。
RSA的使用流程
RSA算法的核心思想是利用一对密钥(公钥和私钥)进行加密和解密操作。公钥可以公开分发给任何人,用于加密信息,而私钥则必须保密,用于解密信息。这种加密方式保证了只有私钥的持有者才能解密出原始信息,从而确保了信息传输的安全性。

算法流程
背景知识:
- 欧拉定理

构造密钥
RSA的密钥生成涉及以下步骤:

计算过程
一、第一步:选择两个质数 p 和 q
RSA 首先随机选择两个质数。
p = 11
q = 17
为什么必须是质数?
因为 RSA 后面要利用质数的数学性质。
然后计算:
n = p × q
所以:
n = 11 × 17
= 187
现在得到:
p = 11
q = 17
n = 187
其中:
p和q必须保密,n最终会放进公钥。
二、第二步:计算欧拉函数 φ(n)
因为:
n = p × q
而且 p、q 都是质数,所以:
φ(n) = (p - 1)(q - 1)
代入:
φ(187)
= (11 - 1)(17 - 1)
= 10 × 16
= 160
所以:
φ(n) = 160
现在我们有:
p = 11
q = 17
n = 187
φ(n) = 160
三、第三步:选择 e
接下来选择一个数字作为:
e
要求:
1 < e < φ(n)
并且:
e 和 φ(n) 互质
我们的:
φ(n) = 160
我们选择:
e = 7
检查:
160 的因数:
1、2、4、5、8、10、16、20、32、40、80、160
7不在里面。
所以:
最大公约数(7,160) = 1
满足要求。
于是:
e = 7
四、第四步:计算 d
这是 RSA 最关键的一步。
我们需要找到一个:
d
使得:
e × d ≡ 1 (mod φ(n))
现在把我们的数字代进去:
7 × d ≡ 1 (mod 160)
翻译成普通数学:
7 × d 除以160,余数必须是1。
我们可以直接试:
7 × 1 = 7
7 × 2 = 14
7 × 3 = 21
...
继续找。
7 × 23 = 161
而:
161 ÷ 160 = 1 余 1
所以:
d = 23
成功。
因此现在:
e = 7
d = 23
并且:
7 × 23 = 161
161 mod 160 = 1
五、密钥生成完成
现在把整个过程整理起来:
输入:
p = 11
q = 17
↓
n = p × q
↓
n = 187
↓
φ(n) = (p-1)(q-1)
↓
φ(n) = 160
↓
选择 e
e = 7
↓
寻找 d
7 × d mod 160 = 1
↓
d = 23
最终:
公钥
(e, n)
= (7, 187)
私钥
(d, n)
= (23, 187)
六、现在开始加密
假设我们要加密:
明文 M = 10
RSA加密公式:
C = M^e mod n
代入:
C = 10^7 mod 187
也就是:
C = 10 × 10 × 10 × 10 × 10 × 10 × 10
然后除以187取余数
计算:
10^7
= 10,000,000
然后:
10,000,000 ÷ 187
得到余数:
C = 175
所以:
明文:
10
↓
使用公钥 (7,187)
↓
密文:
175
七、现在解密
收到密文:
175
我们使用私钥:
(d,n)
=
(23,187)
解密公式:
M = C^d mod n
代入:
M = 175^23 mod 187
这个数字非常大:
175^23
手算非常麻烦。
但是我们可以利用取模的规律简化计算。
注意:
175 ≡ -12 (mod 187)
因为:
175 - 187 = -12
所以:
175^23 mod 187
=
(-12)^23 mod 187
继续利用平方:
12² = 144
然后:
12^4 mod187
等等。
最终计算得到:
175^23 mod187 = 10
于是:
密文:
175
↓
使用私钥 (23,187)
↓
明文:
10
恢复成功。
八、你可以把整个 RSA 当成一个程序
如果用伪代码表示:
# ========================
# 1. 生成密钥
# ========================
p = 11
q = 17
n = p * q
phi = (p - 1) * (q - 1)
e = 7
d = find_d(e, phi)
# 此时:
# n = 187
# phi = 160
# e = 7
# d = 23
public_key = (e, n)
private_key = (d, n)
其中:
find_d(7,160)
实际上就是寻找:
7 × d % 160 == 1
最终:
d = 23
九、加密伪代码
function encrypt(message, public_key):
e = public_key.e
n = public_key.n
ciphertext = message^e % n
return ciphertext
使用:
message = 10
public_key = (7,187)
于是:
ciphertext
= 10^7 % 187
= 175
十、解密伪代码
function decrypt(ciphertext, private_key):
d = private_key.d
n = private_key.n
message = ciphertext^d % n
return message
使用:
ciphertext = 175
private_key = (23,187)
于是:
message
= 175^23 % 187
= 10
成功恢复。
十一、最重要的是理解这张图
你现在可以把 RSA 想象成:
密钥生成
│
┌─────────┴─────────┐
↓ ↓
p = 11 q = 17
│ │
└─────────┬─────────┘
↓
n = 11 × 17
↓
n = 187
│
↓
φ(n) = 160
│
↓
e = 7
│
↓
d = 23
│
┌────────┴────────┐
↓ ↓
公钥 私钥
(7,187) (23,187)
│ │
↓ │
加密 │
│ │
10 → 175 │
↓
解密
│
175 → 10
十二、你现在真正需要理解的只有三个数学关系
理解 RSA,需要把这三个关系吃透:
① p、q 生成 n
p = 11
q = 17
n = p × q
= 187
② p、q 生成 φ(n)
φ(n)
= (p-1)(q-1)
= 10 × 16
= 160
③ e、d 必须满足
e × d mod φ(n) = 1
我们的例子:
7 × 23 mod 160
= 161 mod 160
= 1
然后才有:
加密:
M^7 mod 187
解密:
C^23 mod 187
最终:
10
↓
加密
↓
175
↓
解密
↓
10
练习:如果你自己用 p=5、q=11,从头算出 n、φ(n)、e、d,然后去走一遍加密,解密流程?
陷门函数与困难问题、困难计算
TODO
为什么抗彩虹表攻击?
彩虹表攻击是指,拿着获取到的hash值通过查询彩虹表找出其原始值的攻击方式。
如果先计算好一些大数的质数表,能否破解?
TODO
公钥和私钥用反的安全风险
只是从使用来说,他们可以相互反着来用,都能达成加密、解密效果。
但是,实际上私钥包含了更多信息,比如公钥的信息,如果把私钥公开出去,把私钥当成公钥来使用,
则会照成密钥泄露的安全风险。
一些安全性考虑
安全性考虑
-
密钥长度:为了保持RSA算法的安全性,必须选择足够大的密钥长度。在现代标准中,通常推荐使用至少2048位的密钥长度,以抵抗已知的攻击方法。
-
随机数生成:在密钥生成过程中使用的随机数必须具有良好的随机性,以避免潜在的安全。
-
参数选择:选择合适的质数p和q以及加密指数e对于算法的安全性至关重要。通常建议使用安全的参数生成方法来避免常见的陷阱和弱点。
-
已知与防御:尽管RSA算法被广泛认为是安全的,但仍存在潜在的风险。例如,侧信道可以通过观察加密或解密操作的物理特征(如时间、功耗等)来推测密钥信息。为了防范这些,可以采取相应的防御措施,如使用掩码技术来隐藏关键操作的特征。
-
算法实现与更新:在实际应用中,需要注意RSA算法的正确实现和及时更新。错误的实现或使用过时的算法库可能导致安全漏洞。因此,建议使用经过充分测试和验证的加密算法库,并定期更新以应对新出现的安全威胁。
浙公网安备 33010602011771号