当前位置: 代码网 > it编程>前端脚本>Python > Python项目进行加密打包的实践指南

Python项目进行加密打包的实践指南

2026年01月15日 Python 我要评论
引言在实际开发中,我们有时需要将 python 项目交付给客户或部署到不受控环境中,但又不希望源代码被轻易查看甚至篡改。虽然 python 作为解释型语言天然难以完全隐藏逻辑,但我们仍可通过编译为字节

引言

在实际开发中,我们有时需要将 python 项目交付给客户或部署到不受控环境中,但又不希望源代码被轻易查看甚至篡改。虽然 python 作为解释型语言天然难以完全隐藏逻辑,但我们仍可通过编译为字节码 + 自定义加密 + 运行时解密执行的方式,大幅提升逆向分析的门槛。

本文将基于一个自研的 encryptor 工具类,分享如何实现一个轻量级、可扩展的 python 项目加密打包方案。

整体思路

我们的目标是:

  1. 保留原有项目结构(包括子目录、.py.pyw 文件);
  2. 将每个 python 源文件编译为字节码并加密
  3. 生成一个“运行时”模块,用于在运行时动态解密并执行加密后的字节码;
  4. 输出一个独立的加密项目副本,无需原始源码即可运行。

整个流程如下:

原始项目 (testproject/)
├── main.py
├── utils/
│   └── helper.py
└── ...

↓ encryptor.encryptproject()

加密项目 (testproject-dist/)
├── main.py        ← 内容变为: from __runtime__ import __run__; __run__(b'...', globals())
├── utils/
│   └── helper.py  ← 同上
└── __runtime__/   ← 包含解密和执行逻辑

一、准备工作

由于我们需要在运行时动态解密并执行加密后的字节码,但是又不想暴露解密算法,那么需要将解密函数单独编译为.pyd或者其他(.so/.dll)机器码文件,这里给出示例:

# runtime.py
def __run__(en_code: bytes, globals_: dict):
    import struct
    import marshal

    def decrypt(en_code: bytes) -> bytes:
        en_code, offset_bytes = en_code[:-4], en_code[-4:]  # 去除偏移量
        insert_offset = struct.unpack("<i", offset_bytes)[0]
        key = en_code[insert_offset : insert_offset + 64]  # 提取key
        en_code = en_code[:insert_offset] + en_code[insert_offset + 64 :]  # 去除key
        # 解密
        de_code = bytes([en_code[i] ^ key[i % len(key)] for i in range(len(en_code))])
        return de_code

    code = marshal.loads(decrypt(en_code))
    exec(code, globals_, globals_)

完成编译后,新建runtime文件夹,将pyd文件(如runtime.cp312-win_amd64.pyd)放入,并新建__init.py__文件,输入一行代码:

from .runtime import __run__ 

python解释器会根据目前设备自动选择runtime.cp312-win_amd64.pyd,所以并不需要更改文件名。

二、核心实现解析

1. 密钥生成:动态随机 + sha3-512

def __generatekey(self) -> bytes:
    key = "".join([chr(randint(33, 126)) for _ in range(64)])
    return hashlib.sha3_512(key.encode("utf-8")).digest()
  • 每次加密一个文件时,都会独立生成一个 64 字节的随机密钥
  • 使用 sha3_512 哈希确保密钥分布均匀且不可预测;
  • 注意:密钥不会保存在外部,而是直接嵌入加密数据中(见下文)。

安全提示:此设计便于单文件自包含,但若攻击者能提取密钥,则可解密。适用于防普通用户查看,非高强度安全场景。

2. 加密流程:字节码 + 异或 + 随机插入密钥

code = compile(..., "exec")
bytecode = marshal.dumps(code)
en_code = bytes([bytecode[i] ^ key[i % len(key)] for i in range(len(bytecode))])
insert_offset = randint(0, len(en_code) - 1)
en_code = en_code[:insert_offset] + key + en_code[insert_offset:]
en_code += struct.pack("<i", insert_offset)  # 尾部记录偏移

步骤分解:

  1. 编译源码为 codeobjectcompile()
  2. 序列化为字节码marshal.dumps()(python 内部格式)
  3. 用密钥异或加密(简单但有效,避免明文字节码)
  4. 将密钥随机插入加密数据中间(增加静态分析难度)
  5. 在末尾写入 4 字节偏移量(小端无符号整数),用于运行时定位密钥位置

这种“密钥内嵌 + 偏移记录”的设计,使得每个加密文件都是自包含的,无需额外配置。

3. 输出加密文件:注入运行时调用

加密后的 .py 文件内容变为:

from __runtime__ import __run__
__run__(b'\x12\xaf...', globals())

其中 b'\x12\xaf...' 是加密后的字节数据(包含密钥和偏移)。
当 python 执行该文件时,会调用 __runtime__.__run__ 来解密并执行原始逻辑。

4. 运行时模块(runtime/)

虽然本文未展示 runtime/__init__.py 的内容,但其核心逻辑大致如下:

def __run__(en_code: bytes, globals_: dict):
    import struct
    import marshal

    def decrypt(en_code: bytes) -> bytes:
        en_code, offset_bytes = en_code[:-4], en_code[-4:]  # 去除偏移量
        insert_offset = struct.unpack("<i", offset_bytes)[0]
        key = en_code[insert_offset : insert_offset + 64]  # 提取key
        en_code = en_code[:insert_offset] + en_code[insert_offset + 64 :]  # 去除key
        # 解密
        de_code = bytes([en_code[i] ^ key[i % len(key)] for i in range(len(en_code))])
        return de_code

    code = marshal.loads(decrypt(en_code))
    exec(code, globals_, globals_)

此模块需随加密项目一同分发,但本身不含敏感逻辑,可公开。

三、使用方式

只需一行代码即可加密整个项目:

encryptor = encryptor("testproject")  # 源目录
encryptor.encryptproject()            # 输出到 testproject-dist/

支持递归处理所有 .py.pyw 文件,并自动创建目标目录结构。

四、优缺点分析

优点

  • 简单有效:无需第三方依赖,仅用标准库;
  • 自包含:每个文件独立解密,无全局密钥管理;
  • 保留结构:项目组织不变,兼容原有导入路径;
  • 防小白:普通用户无法直接阅读源码。

局限

  • 非高强度加密:异或加密可被内存 dump 或动态调试破解;
  • 性能开销:每次执行需解密,对启动速度有轻微影响;
  • 不防反编译:一旦字节码被还原,可用 uncompyle6 等工具反编译;
  • 密钥内嵌风险:熟练攻击者可提取密钥批量解密。

若需更高安全性,建议结合:

  • c 扩展封装核心逻辑
  • 商业混淆工具(如 pyarmor)
  • 网络授权验证

五、总结

本文实现的 encryptor 是一个教学级但实用的 python 项目加密方案。它平衡了易用性与基础保护能力,适合用于:

  • 内部工具分发
  • 客户端脚本保护
  • 防止 casual 代码窥探

虽然不能做到“绝对安全”,但在多数场景下已足够提升逆向成本。更重要的是,通过这个过程,我们深入理解了 python 的编译、字节码、marshal 序列化等底层机制。

附:注意事项

  • 确保 runtime/ 目录与加密脚本同级;
  • 不要加密 __main__.py 以外的入口文件时破坏 if __name__ == "__main__" 逻辑;
  • 测试加密后项目是否能正常运行!

以上就是python项目进行加密打包的实践指南的详细内容,更多关于python项目加密打包的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com