当交付工程项目时,一般希望核心代码和数据不被公开,此时需要进行加密处理,并保证代码能够正确运行。
下面介绍一个我最近写的一个跨平台release版本发布工具,实现了txt文件、excel文件加密,并将python代码编译成so文件(Linux平台)。其中txt, excel文件加密使用了AES加密算法,在这些数据加密后代码要做一定的更改,即加密的数据在需要使用时解码,使用完再将数据加密放回去。众所周知,Python代码是很难做到完全保密的,本文使用cython,gcc将Python代码转换成C代码,然后编译成so文件,实现了相对较高的安全性,至少增加了反编译的成本。
以下是数据加解密的代码,包括AES加密、解密txt, excel文件,以及加密整个嵌套文件夹下的txt、excel文件等功能,注释比较清楚,请看代码:
"""
文件加解密工具
"""
import os
import csv
import xlrd
import xlwt
import hashlib
import base64
import random
import string
from Crypto.Cipher import AES
class Encryptor():
def __init__(self):
self.mode = AES.MODE_CBC
def encrypt(self, key, text):
"""
加密函数,如果text不是16的倍数(加密文本text必须为16的倍数),那就补足为16的倍数
:param text:
:return:
"""
sha384 = hashlib.sha384()
sha384.update(key.encode('utf-8'))
res = sha384.digest()
key = res[0:32]
iv = res[32:48]
cryptor = AES.new(key, self.mode, iv)
length = 16
count = len(text)
add = length - (count % length)
text = text + ('\0' * add).encode('utf-8')
self.ciphertext = cryptor.encrypt(text)
return base64.encodestring(self.ciphertext)
def write_encrypt_text(self, key, file_name):
"""
将一个文件加密并写回原文件
:param key: 加密密钥
:param file_name: 需要加密的文件名
"""
file_name = file_name.rstrip("\n").rstrip(" ")
file_object = open(file_name, 'r', encoding='utf-8')
encrypt_str = file_object.read()
file_object.close()
encrypt_str = encrypt_str.rstrip("\n").rstrip(" ")
e = self.encrypt(key, encrypt_str.encode('utf-8'))
file_object = open(file_name, 'w', encoding='utf-8')
file_object.write(e.decode('utf-8'))
file_object.close()
# pass
def make_key(self):
"""
随机产生一个32位密钥
:return:
"""
return ''.join(random.sample(string.ascii_letters + string.digits, 32))
def make_key_list(self, key_num):
"""
产生key_num个数量的32位随机密钥
:param key_num:
:return:
"""
return [''.join(random.sample(string.ascii_letters + string.digits, 32)) for i in range(key_num)]
def encrypt_files_in_folder(self, folder_name):
"""
加密一个文件夹下的所有文件
:param folder_name
:return: 文件名、密钥字典
"""
file_names = get_file_names(folder_name)
key_list = self.make_key_list(len(file_names))
file_key_dict = {}
for i, file_name in enumerate(file_names):
file_key_dict[file_name] = key_list[i]
self.write_encrypt_text(key_list[i], folder_name + '/' + file_name)
return file_key_dict
def encrypt_files_in_folder_with_dict(self, key_dict, folder_name):
"""
利用传入的key_dict解密一个文件夹下的文件
:param key_dict:
:param folder_name:
:return:
"""
file_names = get_file_names(folder_name)
for i, file_name in enumerate(file_names):
self.write_encrypt_text(key_dict.get(file_name), folder_name + '/' + file_name)
# pass