做过开发的都会接触到加密算法和 hash 算法,这两者是有区别的,加密算法分为对称加密和非对称加密,目的是、对数据进行加密/解密,而 hash 则是单向算法,无法还原原始数据。
RSA 加密/解密
目前简单的非对称加密是 RSA,还有其他的如椭圆等,各位可以自行研究
首先需要 crypto 的 lib
$ pip install pycryptodome
# or
$ poetry add pycryptodome
复制代码
generate_key.py: 生成公钥和密钥
from Crypto.PublicKey import RSA
key = RSA.generate(2048)
private_key = key.export_key()
file_out = open("private.pem", "wb")
file_out.write(private_key)
file_out.close()
public_key = key.publickey().export_key()
file_out = open("receiver.pem", "wb")
file_out.write(public_key)
file_out.close()
复制代码
加密和解密(文件版)
官方代码:
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES, PKCS1_OAEP
data = "I met aliens in UFO. Here is the map.".encode("utf-8")
file_out = open("encrypted_data.bin", "wb")
recipient_key = RSA.import_key(open("receiver.pem").read())
session_key = get_random_bytes(16)
# Encrypt the session key with the public RSA key
cipher_rsa = PKCS1_OAEP.new(recipient_key)
enc_session_key = cipher_rsa.encrypt(session_key)
# Encrypt the data with the AES session key
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
[ file_out.write(x) for x in (enc_session_key, cipher_aes.nonce, tag, ciphertext) ]
file_out.close()
复制代码
加密和解密(Data 版)
由于 pycryptodome 的加密都是基于 bytes,所以 str 需要与 bytes 的转换, 代码如下:
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Cipher import PKCS1_OAEP # AES,
from Crypto.Util.Padding import pad, unpad
# RSA public key
recipient_key = RSA.import_key(open("receiver.pem").read())
data = '123456'
# 通过decode转换bytes,另一种方法是bytes(data, 'utf-8'), 但是存在损耗
session_key = data.encode('utf-8')
# Encrypt the session key with the public RSA key
cipher_rsa = PKCS1_OAEP.new(recipient_key)
enc_session_key = cipher_rsa.encrypt(pad(session_key, 16))
# 将bytes转str,用于保存与varchar数据字段
enc_session_key = enc_session_key.decode('raw_unicode_escape')
private_key = RSA.import_key(open("private.pem").read())
# Decrypt the session key with the private RSA key
cipher_rsa = PKCS1_OAEP.new(private_key)
# 将str转bytes
session_key = unpad(cipher_rsa.decrypt(enc_session_key.encode('raw_unicode_escape')), 16)
decrypted = session_key.decode('utf-8')
user.passwd = decrypted
复制代码
SHA1 计算文件校验码
关于计算文件的校验码,从速度上来说 crc32 > sha1 > md5,从安全性角度 sha1 > md5 > crc32, 所以在使用中自己取舍, 但是目前许多大厂转向 sha256,主要是安全性比 sha1 更高,但是速度就下降了许多。其选择的原因也是他们的数据已经接近或远远超过ZB
了。
添加
$ pip install hashlib
# or
$ poetry add hashlib
复制代码
我这里直接引用我写在 Flask 下的代码, 值的注意的是 Flask 的文件是 FileStorage 类型,不是 File-like object,需要 stream 读取,如果读取后需要再读取记得用 stream.seek(0),修改偏移量,否则文件读取 size 为 0
from flask import request, jsonify
import hashlib
BUF_SIZE = 65536
def post_file():
file = request.files.get('file')
# 计算文件的checksum值
sha1 = hashlib.sha1()
checksum = ""
try:
# with open(file.filename, 'rb') as f:
while True:
data = file.stream.read(BUF_SIZE)
if not data:
break
sha1.update(data)
# 获取结果
checksum=sha1.hexdigest()
except IOError:
return jsonify({'message': '演算checksum失败!!!'}), 403
复制代码
参考:
评论