对称加密的模式很好理解,但非对称加密算法的上述特点却让我们感觉很神奇,下面就来简单看看,上述这些特点在数学上是怎样实现的吧。在非对称加密算法中 RSA 是使用最广泛的一种,我们就以 RSA 为例,一会儿再介绍怎么用 Python 实现它。
RSA 算法是 1977 年由共同在麻省理工学院工作的罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。RSA 就是他们三人姓氏开头字母拼在一起组成的。
RSA 加密利用了"单向函数"正向求解很简单,反向求解很复杂的特性。思想如下:
这个应该很好理解,然后是 RSA 的工作原理,以下是 ChatGPT 告诉我的,我们不懂也没关系。
- 选择两个大的质数 p 和 q,且通常这两个数的大小相近。
- 计算这两个数的乘积 n = p * q,这个 n 将作为公钥和私钥的一部分。
- 计算 n 的欧拉函数 ϕ(n) = (p - 1) * (q -1)。
- 选择一个整数 e,使得 1 < e ϕ(n) 且 e 与 ϕ(n) 互质,e 通常选取65537,因为它是一个质数,且为形式为 2 的幂次方加 1。
- 计算 e 关于 ϕ(n) 的模逆元 d,即找到 d 使得 e * d = 1 % ϕ(n)。
然后便可得到公钥 (e, n) 和私钥 (d, n),而它们满足如下关系。
其中 M 是明文,C 是密文,明文 M 用公钥加密得到密文 C,密文 C 用私钥解密得到明文 M。当然这个过程反过来也是一样,也可以用私钥进行加密,公钥进行解密,这个过程一般用作签名。RSA 算法的安全性基于 RSA 问题的困难性,也就是基于大整数因子分解的困难性上。这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长 RSA 密钥是 768 个二进制位。
也就是说,长度超过 768 位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024 位的 RSA 密钥基本安全,2048 位的密钥极其安全。
非对称加密的算法比对称加密要复杂且耗时,位数越多越耗时。因此在实际使用中,一般是先用非对称加密过程传递对称加密的密钥,之后再使用对称加密来保证后续的通信,这样安全性与速度就可以达到一个平衡,HTTPS 所使用的就是这种方式。
首先需要安装一个库:pycryptodome,直接 pip 安装即可,这个库里面包含了大量实现好的加密算法。from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii
def generate_keys():
# 生成长度为 2048 的秘钥
key = RSA.generate(2048)
# 生成公钥
private_key = key.export_key()
# 生成私钥
public_key = key.publickey().export_key()
return private_key, public_key
def encrypt_message(public_key, message):
cipher = PKCS1_OAEP.new(RSA.import_key(public_key))
# 使用公钥加密,得到密文(bytes 对象)
encrypted_message = cipher.encrypt(message.encode())
# 一般会转成十六进制进行传输
return binascii.hexlify(encrypted_message).decode()
def decrypt_message(private_key, encrypted_message):
cipher = PKCS1_OAEP.new(RSA.import_key(private_key))
# 解密
decrypted_message = cipher.decrypt(
binascii.unhexlify(encrypted_message)
)
return decrypted_message.decode()
# 生成密钥
private_key, public_key = generate_keys()
message = "高老师总能分享出好东西"
# 使用公钥加密
encrypted = encrypt_message(public_key, message)
print(encrypted)
"""
41bc8709cb82e1f9a13d18f101538c536f760210c11···
"""
print(len(encrypted))
"""
512
"""
# 使用私钥解密
decrypted = decrypt_message(private_key, encrypted)
print(decrypted)
"""
高老师总能分享出好东西
"""