python项目加密(模型加密,文件加密),涵盖了多种方法以及代码实现 您所在的位置:网站首页 web加密解密项目有哪些 python项目加密(模型加密,文件加密),涵盖了多种方法以及代码实现

python项目加密(模型加密,文件加密),涵盖了多种方法以及代码实现

2024-06-17 16:29| 来源: 网络整理| 查看: 265

Python作为动态语言一般是以源码方式进行部署的,这就意味着他人在部署机器上可以直接获取项目代码,可能给作者带来不必要的损失和风险,这就需要对代码进行加密或混淆。常规的几类加密(混淆)方式如下:

编译为pyc文件将项目代码打包成python包将python文件变异成二进制文件

总体来说1和2的方式还是存在一定的风险,本文将采用第三种方式,且提供五种该类型的加密方式,分别为、Cython、cryptography、RSA、pyAesCrypt和encryptpy。

一、Cython

该方法是通过Cython将python文件编译成.c(C语言)文件,再生成.so(share object)文件,这种方式是不可逆的,所以能够起到混淆代码,起到一定程度的加密效果。 通过命令查看目录结构

$ tree -a .

目录结构如下:

. ├── setup.py └── example ├── __init__.py ├── main.py ├── README.md ├── xxx.py └── utils.py 1 directory, 6 files

运行命令

python setup.py build_ext

setup.py文件如下,这段代码可通用,直接运行即可自动生成

# -*- coding: utf-8 -*- import os import shutil import fnmatch from distutils.core import setup from Cython.Build import cythonize def get_delete_files(project_root): """这个函数会遍历指定项目根目录下的所有文件,并返回一个包含所有Python文件的列表。 这个函数会排除名为'main.py'的文件,因为它是主程序文件。""" matches = [] for root, dirnames, filenames in os.walk(project_root): for filename in fnmatch.filter(filenames, '*.py'): if filename != 'main.py': # 排除main.py文件 matches.append(os.path.join(root, filename)) for filename in fnmatch.filter(filenames, '*.c'): matches.append(os.path.join(root, filename)) return matches def get_py_files(project_root): """这个函数会遍历指定项目根目录下的所有文件,并返回一个包含所有Python文件的列表。 这个函数会排除名为'main.py'的文件,因为它是主程序文件。""" matches = [] for root, dirnames, filenames in os.walk(project_root): for filename in fnmatch.filter(filenames, '*.py'): if filename != 'main.py': # 排除main.py文件 matches.append(os.path.join(root, filename)) return matches def tool(root, paths): """ 该函数是执行整个任务的主要函数。它以项目的根目录和Python文件的路径列表作为输入。 :param root: :param paths: :return: """ filePath3 = os.path.dirname(dis_root) + '/build/' if not os.path.exists(filePath3): os.mkdir(filePath3) # 1、文件加密 setup(name='encrypt', ext_modules=cythonize(paths)) print("加密完成") # 2、将加密的文件移至对应目录下 files_1 = os.listdir(filePath3) for files_1_temp in files_1: if "lib" in files_1_temp: files_1 = files_1_temp # print(files_1) print('filePath3: ', filePath3) print('files_1: ', files_1) for files_2 in os.listdir(filePath3 + files_1): so_file = filePath3 + files_1+"/" + files_2 print(so_file) # 文件移动或拷贝 shutil.move(so_file, root) # 3、删除原文件和生成的附属文件夹 files2 = get_delete_files(dis_root) for file in files2: if os.path.exists(file): os.remove(file) print('移除后test 目录下有文件:%s' % file) else: print("要删除的文件不存在!") # 删除附属文件夹 try: shutil.rmtree(filePath3) except Exception as ex: print("错误信息:"+str(ex)) # 提示:错误信息,目录不是空的 print("删除完成") dis_root = '/mnt/xxx/example' Paths = get_py_files(dis_root) tool(dis_root, Paths) 二、加密库 cryptography

环境安装

pip install cryptography

下面以加密一个onnx文件为例。 先进行加密,可根据配置密钥个数,保障加密强度。然后对文件内容进行加密,当然这个密钥后面在对文件进行解密的时候会派上用场,因此密钥一定要保存完好,代码如下:

import os import base64 import argparse from cryptography.fernet import Fernet, MultiFernet def Parser(): parser = argparse.ArgumentParser(description='文件加密') parser.add_argument('--model_file', '-mf', type=str, default=None, help='需要加密文件的绝对地路径') parser.add_argument('--new_model_file', '-nmf', type=str, default=None, help='文件保存的绝对地路径') parser.add_argument('--key_num', '-kn', type=int, default=8, help='密钥数量') return parser.parse_args() def generate_key(message='') -> bytes: x = os.urandom(32 - len(message)) + message.encode() return base64.urlsafe_b64encode(x) def add_secret(model_file=None, new_model_file=None, multi_key: int = 1): if new_model_file is None: ext = os.path.splitext(model_file)[-1] new_model_file = model_file.replace(ext, '.dll') # # 生成密钥 ks = [] keys = [] if multi_key > 0: for i in range(multi_key): keyi = generate_key() keys.append(keyi) print(f'key{i + 1}: ', keyi) ki = Fernet(keyi) ks.append(ki) if len(ks) == 1: f = ks[0] else: f = MultiFernet(ks) else: raise ValueError('The "multi_key" must be greater than 0.') # 保存license file = 'license.dll' with open(file, 'wb') as fw: for j in keys: fw.write(j + b'\n') print('liscence file write in ', file) with open(new_model_file, 'wb') as ew: # 二进制读取模型文件 content = open(model_file, 'rb').read() # 根据密钥解密文件 encrypted_content = f.encrypt(content) # print(encrypted_content) # 保存到新文件 ew.write(encrypted_content) def desecrect(new_model_file: str = None, keys_file: str = None): """ :param new_model_file: :param keys: :return: """ with open(keys_file, 'rb') as f: x = f.read() keys = x.strip(b'\n').split(b'\n') print(keys) ks = [] for keyi in keys: ki = Fernet(keyi) ks.append(ki) if len(ks) > 1: f = MultiFernet(ks) else: f = ks[0] onnx_file = open(new_model_file, 'rb').read() onnx_file = f.decrypt(onnx_file) if onnx_file is not None: print('解密成功') with open(desecrect_model_file, 'wb') as ew: ew.write(onnx_file) def test(): dll_file = 'xxx.dll' key1 = 'license.dll' desecrect(dll_file, key1) def main(): args = Parser() if args.model_file is None: model_file = 'xxx.onnx' else: model_file = args.model_file message = args.message if args.message is not None else '' add_secret(message, model_file, args.new_model_file, args.key_num) if __name__ == '__main__': main() # test() 三、加密库 RSA

使用RSA加密算法实现数据的加密解密 环境安装

pip install rsa import os import rsa def encrypt_file(file_path, public_key_file): """使用RSA算法加密文件 参数: file_path: 需要加密的文件路径 public_key_file: 公钥文件路径 返回值: 无 """ # 读取文件内容 with open(file_path, "rb") as file: file_content = file.read() # 读取公钥 with open(public_key_file, "rb") as key_file: public_key = rsa.PublicKey.load_pkcs1(key_file.read()) # 加密文件内容 encrypted_content = rsa.encrypt(file_content, public_key) # 将加密后的内容写入文件 with open(file_path, "wb") as file: file.write(encrypted_content) def decrypt_file(file_path, private_key_file, password): """使用RSA算法解密文件 参数: file_path: 需要解密的文件路径 private_key_file: 私钥文件路径 password: 私钥文件密码 返回值: 无 """ # 读取文件内容 with open(file_path, "rb") as file: encrypted_content = file.read() # 读取私钥 with open(private_key_file, "rb") as key_file: private_key = rsa.PrivateKey.load_pkcs1(key_file.read(), password) # 解密文件内容 file_content = rsa.decrypt(encrypted_content, private_key) # 将解密后的内容写入文件 with open(file_path, "wb") as file: file.write(file_content) 四、加密库 pyAesCrypt

个人觉得这个代码库实现最为简单,只是密钥需要我们自己指定的 环境安装

pip install pyAesCrypt import pyAesCrypt def Encryption(input_file_path, output_file_path, key): pyAesCrypt.encryptFile(input_file_path, output_file_path, key) print("File has been decrypted") def Decryption(input_file_path, output_file_path, key): pyAesCrypt.decryptFile(input_file_path, output_file_path, key) print("File has been decrypted") 五、加密库 encryptpy

encryptpy使用Cython将Python代码编译为二进制以达到加密的目的,并且支持通过git-diff来获取两次提交间的差异文件,方便地进行编译 环境安装

pip install encryptpy

Basic Usage

Usage: encryptpy [OPTIONS] COMMAND [ARGS]... Encrypt your Python code Options: --config TEXT The config file, ignore if given is invalid [default: .encryptpy.cfg] --help Show this message and exit. Commands: clean Simply clean `build` and `__pycache__` directory in DIRS git-diff Compile files between two COMMITS, see `git-diff`: `--name-only` init Copy src to build-dir and do compile, usually used for the... run Compile given Python code files

子命令用法可以使用encryptpy --help来查看。

例子

例如,有一个名为package_a的项目文件目录:

$ tree -a . . ├── .encryptpy.cfg └── package_a ├── __init__.py ├── main.py ├── README.md ├── setup.py └── utils.py 1 directory, 6 files

其中 .encryptpy.cfg内容如下:

[encryptpy] ; Files will be compiled paths = package_a ; Files will be ignored when compiling, support Regex ignores = setup.py ; For command `init`, files will be ignored when copying, Glob-style copy_ignores = *.pyc *.md ; The build directory build_dir = build ; For commands `run` and `git-diff`, whether the source .py will be removed clean_py = 0 1. 项目第一次使用,使用init $ encryptpy init .

查看build目录:

$ tree -a build build ├── .encryptpy.cfg └── package_a ├── __init__.cpython-38-x86_64-linux-gnu.so ├── main.cpython-38-x86_64-linux-gnu.so ├── setup.py └── utils.cpython-38-x86_64-linux-gnu.so 1 directory, 5 files 使用run $ encryptpy run package_a/main.py

将package_a/main.py被重新编译为package_amain.cpython-38-x86_64-linux-gnu.so

使用git-diff $ encryptpy git-diff 0.1 0.2

标记(或提交或分支)0.1 和 0.2 之间更改的文件将被编译。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有