别怕,咱们的聊天消息,没人能偷看

别怕,咱们的聊天消息,没人能偷看
别怕,咱们的聊天消息,没人能偷看html

摄影:产品经理
炸鱼剩下的油,我跟产品经理吃了一周
因为众所周知的缘由,国内的各大邮箱、聊天 App 都会监控你接收和发送的信息。若是你须要传递一些绝密内容,显然你须要对你的内容进行加密。算法

可是加密的密码你怎么告诉别人呢?打电话说吗?若是是一对一的沟通,这种方式确实没有问题。安全

但若是如今是单向联系,多我的给你发信息。你想让全部联系你的人,都把信息加密之后才能发给你,而且只有你能解密怎么办?若是只使用一个密码,那么 A 发给你的消息可能会被 B 偷看。难道你须要和每一个人都设置一个各自的专用密码?微信

为了解决这个问题,咱们就可使用非对称加密。非对称加密的加密密钥与解密密钥是分开的。加密密钥能够公开,全部人都能看到。全部人都能使用同一个加密密钥加密信息发送给你。但只有你本身手上的解密密钥能把这个密文解开。ide

RSA 算法就是一种非对称加密算法。工具

这种算法很是可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还没法破解(至少没人公开宣布)。所以能够认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。——《RSA算法原理(一)》[1]”

RSA 算法中的加密密钥,咱们称为公钥(Public Key),解密密钥,称为私钥(Private Key)。你只须要保管好私钥便可。公钥能够放在博客上,想给你发信息的人, 只须要用公钥加密信息再发给你便可。ui

在 Python 中咱们如何使用 RSA 算法进行加密解密呢?能够安装一个第三方库,叫作rsa:编码

pip install rsa

安装完成之后,咱们试着交密一段中文:今晚8点老地方碰头.加密

第一步,建立公钥和私钥3d

import rsa

public_key, private_key = rsa.newkeys(1024)

咱们如今打印一下这两个密钥,以下图所示:
别怕,咱们的聊天消息,没人能偷看

其中的数字1024表示生成1024位的密钥。你也能够写2048或者4096……,只要是 且 n>4便可。位数越多越安全,可是加密解密速度越慢。

生成的密钥是 Python 对象,不方便发送给别人。因此咱们能够把它们转换为pem格式:

public_key_str = public_key.save_pkcs1()
private_key_str = private_key.save_pkcs1()

以下图所示:
别怕,咱们的聊天消息,没人能偷看

如今,咱们获得了两个字符串。这是 pem 格式的公钥和私钥,公钥以BEGIN RSA PUBLIC KEY开头,较短;私钥以BEGIN RSA PRIVATE KEY开头,较长。

其中,私钥你本身保管好不要泄露。公钥你能够用 QQ 微信邮箱短信等等任意通讯工具发送给别人。

密钥只须要生成一次,之后就不须要执行上面的代码了。

有了公钥和私钥之后,咱们就能够开始发送信息了。

注意如下代码都是使用 pem 格式的公钥和私钥。

首先咱们使用公钥加密信息。

public_key_str = '''
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAIWmLWCvb3kSJ7+ys9JZ/rqqgIcYwf9bcEl9/BQd4XnsSHHoyAyG+bPI
1YRGaAnmKLGeEcgrJE1sQIqIMdeHLHVTWUNh4Wr8o+1fyTrlpK0fCNmLb3qRabsg
wRxoSEflXAchBLlHWQoHkaMjcfR7zTFe5I/ogx5gtSX0TQCSmLANAgMBAAE=
-----END RSA PUBLIC KEY-----
'''
msg = '今晚8点老地方碰头'
public_key = rsa.PublicKey.load_pkcs1(public_key_str.encode())
encryptd_msg = rsa.encrypt(msg.encode(), public_key)

加密之后,咱们得到是一个 bytes 型的数据,以下图所示:
别怕,咱们的聊天消息,没人能偷看

注意,这里的这个 bytes 型数据是不能.decode()成字符串的。那么应该如何把它发送给别人呢?

这个时候,就能够在它的外层套一层 base64编码,让他变成字符串:

import base64

encryptd_msg_str = base64.b64encode(encryptd_msg).decode()

以下图所示:
别怕,咱们的聊天消息,没人能偷看

如今,你能够把密文

RzwfgCFUhLKYiXM7frOcBL7VyLIh1M7pJ8Gpaz9j7HksjYqsw8DzreFziBNi/S0GGciIfWsvr5pUvYFA7wacOjHqluZ7KVx1oEOdg/x6wyeb1UdQ9cR6PzMlgpidpzUknhsGIAmxjtt6EUL+tJVUbzfXHgs5wETxFZQtRHLcKag=”

经过任何一个公开渠道发送给别人了。这就是密文。

拥有私钥的人,拿到密文之后如何解密呢?也很简单:

import rsa
import base64

encryptd_msg_str = '''
RzwfgCFUhLKYiXM7frOcBL7VyLIh1M7pJ8Gpaz9j7HksjYqsw8DzreFziBNi/S0GGciIfWsvr5pUvYFA7wacOjHqluZ7KVx1oEOdg/x6wyeb1UdQ9cR6PzMlgpidpzUknhsGIAmxjtt6EUL+tJVUbzfXHgs5wETxFZQtRHLcKag=
'''

private_key_str = '''
-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQCFpi1gr295Eie/srPSWf66qoCHGMH/W3BJffwUHeF57Ehx6MgM
hvmzyNWERmgJ5iixnhHIKyRNbECKiDHXhyx1U1lDYeFq/KPtX8k65aStHwjZi296
kWm7IMEcaEhH5VwHIQS5R1kKB5GjI3H0e80xXuSP6IMeYLUl9E0AkpiwDQIDAQAB
AoGAYNu2N0PtfcjylbNlLyWZvp6i10XSEsap8hkj/1BIgJwFRMh3cty/StRaKar8
62+qPk9Yg8EAZjv16nAZjRcVQ031/F57FGR3JdZ43fuT/no0gV+mEIc72ypNuhUl
M9iccyhEq0xX4eixex3nUALBcPY17ElhvaD8cDZoW2QGFAECRQCHR4RHmgOzoyuM
Wnov7/WetV8Eqxy1/XQOkvSTWEv6Gyc1vlc/xsRGLwXiUt0BFoOnMRCOAQJwjxSn
EbbRzey3YdzX4QI9APzqPCqiEZ4eNnh8F7eOmQYSRurx2b5eyEg3zrVgJHCNOE1i
8uidT4mLBx4nfIwV8/ttw7TjzvhQtnBtrQJEaAzyCcDEqB8RF9tfsA95dKE8fHLA
mppf8fXGeK6pga3w8r18jmlr/i+c7v+dTYDrsmVivla4casbz4UogSdKs6JqIwEC
PGkUdO0Nqx4z1VPX0w7Lq15vZ5Gj7GEBBlui/Do1eM5ejj7w1pW5DlvKLKnlpASb
9mPHZiGY6NwYxMQPfQJEGg5vG+TN7G4PxbCzeInxxIScpmDE8TBPixrIy9qM/cjb
Excc1vCiR8+Kbhr/RhYveaGuKIKaXrVBhzQJZDYd8298mmA=
-----END RSA PRIVATE KEY-----
'''

private_key = rsa.PrivateKey.load_pkcs1(private_key_str.encode())
encryptd_msg = base64.b64decode(encryptd_msg_str.encode())
msg = rsa.decrypt(encryptd_msg, private_key).decode()
print(msg)

运行效果以下图所示:

别怕,咱们的聊天消息,没人能偷看
RSA 加密对被加密的内容(明文)是有长度限制的。由于最终的密文中会有11 bytes 的内容用来存放加密相关的元信息,因此对于1024位的密钥来讲,能加密的明文长度为 bytes。

若是计算一个字符串的字节长度呢?可使用以下代码:

msg = '今晚8点老地方碰头'
print(len(msg.encode()))

运行效果以下图所示:
别怕,咱们的聊天消息,没人能偷看

说明这8个汉字加1个数字长度为25bytes(由于在 Python 里面,一个汉字占3bytes,数字和字母占1bytes,)

若是要发送一段很长的字符串,就须要把字符串先转成 bytes 型数据,再按照117 bytes 一组拆分红不少组,对每一组分别加密。解密的时候,以密钥位数/8bytes一组先切分密文,再逐一解密,最后拼出明文的 bytes 型数据之后再.decode()转成字符串。

咱们先来实现加密的代码:

def encrypt(msg, public_key):
    msg_bytes = msg.encode()
    encryptd_msg = b''
    chunk_size = len(msg_bytes) // 117 + 1
    for chunk_index in range(chunk_size + 1):
        chunk = msg_bytes[chunk_index * 117: (chunk_index + 1) * 117]
        encryptd_msg += rsa.encrypt(chunk, public_key)
    encryptd_msg_str = base64.b64encode(encryptd_msg).decode()
    return encryptd_msg_str

在这段代码中,咱们是先把明文转成 bytes 型的数据后,再进行切片。这里有可能会把一个中文对应的三个 bytes 从中切开。不过这影响不大。以117bytes 为一个明文块进行加密。把加密后生成的 bytes 型数据拼接成长字符串,再总体使用 Base64进行编码。最后把编码生成的密文发送给别人便可。以下图所示:
别怕,咱们的聊天消息,没人能偷看

咱们在这里生成的密文为:

K2Tb9tDQPXBiuCBuWxOR9zBTbDSN2WaF+n+P2RUA9CHdIKvIHvqfMZ60xTsJ7UqZlB4ykzu/ccsTEmp8vqiVaJSSwg5TgDYLdPmk5/6leZaBW4BqyJ2g0PcyCcUvhjxc7P4AIC6MKYZ+74qTgm+Pf8qnY/riOeEZUuxoq0KaFZQOpvGpwnAgpCad8a6MJ7TbyZpepkZr+GbFDdbmegrA6HN9zCIw30c4g0RCiD01PwerUtbK9YXr/aO8hrFEim8bWDos3bpNrQtk8ST4fM9OczXKEoTSuv+f+Ue2s1YFJ00tAyD4GF8QeZ5mUc2ydNyovkvEfhwhy1eOcI/HQQZn2DPxLb3gB4tgE/Hoo4Xblj8ZWpeMe5BrAdT4Dk1qduOJ/A3RnfvhEbojwx30pEU+JipW4AqCPxK26Q+WsYyqVCBM29vWWgxttthxBidpM0GYII1OIfZvWG8GAAMPvotTwrdGOF/Nk355qLlwiHJhsjz0uN0p9PjyUY+xHobDrmuggBHejM69PwelnG5ubxjhBoqKtbBttU4IWfDZq+d3LZdhwZMp2PsXkSzu+IIgpAn0+F/5bZkRAv8XTAv1YFnYLwJI9vyXfMIyoo4wcqDpNmJrMoaW0hvpJ8jMPna0lI9/Up2JO8GRhq+C+pgeM37OUE70UGrqw1R25yO8Y60of69HqfdFgLalhD7egJ42gRt9Lman7dsokWrpySp6Tq7jFJ/h/OL2Kma8Tqeodd1B0/bINNBkK2hb5EIq7cu6xEd5LevieYllEw0LNK03aWERMfkIuOSabzDfn1kedZnK4PlZ+DiXaoe8uUlAlfZsWNBNV94C3+Ji/a1jYk+ZEUZMxA==”

接下来咱们来编写解密程序:

def decrypt(encryptd_msg_str, private_key):
    encryptd_msg = base64.b64decode(encryptd_msg_str.encode())
    chunk_size = len(encryptd_msg) // 128
    msg_bytes = b''
    for chunk_index in range(chunk_size):
        chunk = encryptd_msg[chunk_index * 128: (chunk_index + 1) * 128]
        msg_bytes += rsa.decrypt(chunk, private_key)
    return msg_bytes.decode()

在解密程序中,咱们先把 Base64编码的字符串解码为 bytes 型的数据,而后以128bytes 为一组进行拆分。分别对每一组进行解密。再把每次解密生成的 bytes 型数据拼接。最后把拼接完成的数据使用.decode()转换为字符串。

特别要注意,对每一块密文,在解密完成之后不能直接.decode()。由于它末尾可能只有半个中文,直接转字符串会致使报错,必须先拼接完解密后的全部 bytes 数据,再转成字符串。更多关于 bytes 型数据切片的问题,请参阅我之前的公众号:一日一技:Python 的 bytes 型数据的迭代特征一文。

解密程序运行效果以下图所示:
别怕,咱们的聊天消息,没人能偷看

你们注意,若是你的密钥是2048位的,那么加密时一个明文会以245bytes 一组先切分再加密;解密时,密文会以256bytes 一组先切分再解密。

最后,你们若是有任何不但愿被众所周知的组织看到的信息想发送给我,可使用下面这个公钥对信息进行加密,而后把密文发送给我:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEApQSWvu/C5NH3aEGMqFTeiJrXbOM2Qi+uXc+FiApEWDYdyEMPQWKH
exJiFoyAa+JJ8OfmkTIVktkx0VqEcvfjfKxrGPk9JuQ6WL4/UUYs8/F+2ArDnMyR
lWcqaf1658QjrWYbFHxQ0eEOZ6RcRKME3p431mDMqeDpQtqlDyeMKGp7hSv5gnpd
Qjlyl1Jgoa4lAzyPv66IM1PD207qjLFCTY0udiWSFDiUlvgXcBHDypUqWGOUUSLE
vVXIE+KYNbR2g23iRa1IJGSCEz1xllt7QpygCwwd+vVGD8zaCHOEE7Fex0K/ybhi
Nvdt19qgxE8aIwGt0ln71DNpn+yZsq4fIwIDAQAB
-----END RSA PUBLIC KEY-----

参考资料

[1]
《RSA算法原理(一)》: https://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

别怕,咱们的聊天消息,没人能偷看

kingname攒钱给产品经理买房。

相关文章
相关标签/搜索