Python源码加密方案详解:.pyc、混淆、py2exe与Cython对比

Alice
Alice
发布时间:2026-10-13| 6人浏览过
原创

本文深入解析Python源码保护的四种主流方案:发行.pyc文件、代码混淆、使用py2exe打包及Cython编译。详细对比各方案在实现难度、平台兼容性、破解成本及性能影响方面的优劣,帮助开发者根据实际需求选择最合适的代码保护策略。

Python源码加密概述

本文旨在详细介绍Python代码加密的具体实现方法,通过示例代码进行清晰阐述,为相关学习与工作提供有价值的参考。

笔者于去年11月在PyCon China 2018杭州站分享了Python源码加密技术,重点讲解了通过修改Python解释器来实现代码加解密的技术路径。由于整理成文耗时较长,如今终于完成并分享本文。

本系列内容将首先梳理现有源码加密方案的思路、方法、优点与不足,随后深入探讨如何通过定制Python解释器来实现更高效的源码加解密。

鉴于Python的动态特性和开源属性,其代码难以实现高强度的加密保护。社区中存在两种观点:一种认为应通过法律手段而非加密源码进行商业保护,另一种则坚持寻求技术手段进行加密。为此,业界提出了多种加密或混淆方案以保护源码安全。

常见的源码保护手段主要包括以下几种:

  • 发行.pyc文件
  • 代码混淆
  • 使用py2exe工具
  • 使用Cython工具

接下来将简要介绍上述各方案的具体实施情况。

方案一:发行.pyc文件

1 发行.pyc文件

1.1 思路

Python解释器在执行代码时,会首先生成.pyc文件,随后解释执行该二进制文件。Python解释器也支持直接执行.pyc文件。由于.pyc文件为二进制格式,无法直接查看源码内容,若向客户环境分发时仅包含.pyc文件而非.py文件,即可达到保护Python代码的目的。

1.2 方法

将.py文件编译为.pyc文件操作简便,无需运行所有代码即可提取生成的.pyc文件。

Python标准库提供了compileall模块,可轻松完成编译工作。

执行以下命令可遍历<src>目录下的所有.py文件,并将其编译为.pyc文件:

python -m compileall <src> 随后删除<src>目录下所有.py文件即可打包发布:


$ find <src> -name '*.py' -type f -print -exec rm {} \;

1.3 优点

操作简单便捷,略微提高了源码破解的门槛。

平台兼容性好,.py文件能运行的环境,.pyc文件同样可以运行。

1.4 不足

解释器兼容性较差,.pyc文件仅能在特定版本的解释器上运行。

存在现成的反编译工具,破解成本较低。python-uncompyle6即为一款效果出色的反编译工具。

执行以下命令,即可将.pyc文件反编译为.py文件:


$ uncompyle6 *compiled-python-file-pyc-or-pyo*

方案二:代码混淆技术

2 代码混淆

若代码被混淆至连作者都难以阅读的程度,是否也能达到保护源码的目的?

2.1 思路

混淆的核心在于通过一系列转换,使代码难以被轻易理解。具体操作包括:移除注释和文档字符串,使关键逻辑不易被理解;改变缩进格式,使代码排版混乱;在tokens间插入多余空格,类似改变缩进的效果;重命名函数、类和变量,通过混乱的命名增加阅读障碍;在空白行插入无效代码,以无关代码打乱阅读节奏。

2.2 方法

方法一:使用oxyry进行混淆

http://pyob.oxyry.com/ 是一个在线混淆Python代码的网站,使用便捷。

假设我们有如下涉及类、函数和参数的Python代码:


# coding: utf-8
 
class A(object):
  """
  Description
  """
 
  def __init__(self, x, y, default=None):
    self.z = x + y
    self.default = default
 
  def name(self):
    return 'No Name'
def always():
  return True
num = 1
a = A(num, 999, 100)
a.name()
always()

经过Oxyry混淆后,得到如下代码:


class A (object ):#line:4
  ""#line:7
  def __init__ (O0O0O0OO00OO000O0 ,OO0O0OOOO0000O0OO ,OO0OO00O00OO00OOO ,OO000OOO0O000OOO0 =None ):#line:9
    O0O0O0OO00OO000O0 .z =OO0O0OOOO0000O0OO +OO0OO00O00OO00OOO #line:10
    O0O0O0OO00OO000O0 .default =OO000OOO0O000OOO0 #line:11
  def name (O000O0O0O00O0O0OO ):#line:13
    return 'No Name'#line:14
def always ():#line:17
  return True #line:18
num =1 #line:21
a =A (num ,999 ,100 )#line:22
a .name ()#line:23
always ()

混淆后的代码主要在注释、参数名称和空格方面进行了调整,在一定程度上增加了阅读障碍。

方法二:使用pyobfuscate库进行混淆

pyobfuscate是一个历史悠久的Python代码混淆库,但依然“老当益壮”。

对前述同一段Python代码,经pyobfuscate混淆后效果如下:


# coding: utf-8
if 64 - 64: i11iIiiIii
if 65 - 65: O0 / iIii1I11I1II1 % OoooooooOO - i1IIi
class o0OO00 ( object ) :
 if 78 - 78: i11i . oOooOoO0Oo0O
 if 10 - 10: IIiI1I11i11
 if 54 - 54: i11iIi1 - oOo0O0Ooo
 if 2 - 2: o0 * i1 * ii1IiI1i % OOooOOo / I11i / Ii1I
 def __init__ ( self , x , y , default = None ) :
 self . z = x + y
 self . default = default
 if 48 - 48: iII111i % IiII + I1Ii111 / ooOoO0o * Ii1I
 def name ( self ) :
 return 'No Name'
 if 46 - 46: ooOoO0o * I11i - OoooooooOO
 if 30 - 30: o0 - O0 % o0 - OoooooooOO * O0 * OoooooooOO
def Oo0o ( ) :
 return True
 if 60 - 60: i1 + I1Ii111 - I11i / i1IIi
 if 40 - 40: oOooOoO0Oo0O / O0 % ooOoO0o + O0 * i1IIi
I1Ii11I1Ii1i = 1
Ooo = o0OO00 ( I1Ii11I1Ii1i , 999 , 100 )
Ooo . name ( )
Oo0o ( ) # dd678faae9ac167bc83abf78e5cb2f3f0688d3a3

Oo0o ( ) # dd678faae9ac167bc83abf78e5cb2f3f0688d3a3 相比于方法一,方法二的效果更为显著。除了对类和函数进行重命名、插入空格外,最明显的是插入了若干段无关代码,使得代码更难阅读。

2.3 优点

操作简单便捷,略微提高了源码破解的门槛。

兼容性好,只要源码逻辑兼容,混淆后的代码同样兼容。

2.4 不足

仅能对单个文件进行混淆,无法实现多个相互关联的源码文件的联动混淆。

代码结构未发生变化,仍可获取字节码,破解难度不大。

方案三:使用py2exe打包

3 使用py2exe

3.1 思路

py2exe是一款将Python脚本转换为Windows平台可执行文件的工具。其原理是将源码编译为.pyc文件,并打包必要的依赖文件,最终生成一个可执行文件。

若最终分发由py2exe打包出的二进制文件,是否即可达到保护源码的目的?

3.2 方法

使用py2exe进行打包的步骤相对简便。

1)编写入口文件。本示例中命名为hello.py:


print 'Hello World'

2)编写setup.py:


from distutils.core import setup
import py2exe
setup(console=['hello.py'])

3)生成可执行文件


python setup.py py2exe

生成的可执行文件位于dist\hello.exe。

3.3 优点

可直接打包成exe文件,便于分发和执行。

破解门槛比.pyc文件更高一些。

3.4 不足

兼容性较差,仅能在Windows系统上运行。

生成的可执行文件内部布局明确且公开,可找到源码对应的.pyc文件,进而反编译出源码。

方案四:使用Cython编译

4 使用Cython

4.1 思路

尽管Cython的主要目的是提升性能,但其原理是将.py/.pyx编译为.c文件,再将.c文件编译为.so(Unix)或.pyd(Windows),这一过程带来的额外好处是代码难以被破解。

4.2 方法

使用Cython进行开发的步骤也不复杂。

1)编写文件hello.pyx或hello.py:


def hello():
  print('hello')

2)编写setup.py:


from distutils.core import setup
from Cython.Build import cythonize
setup(name='Hello World app',
   ext_modules=cythonize('hello.pyx'))

3)编译为.c,再进一步编译为.so或.pyd:


python setup.py build_ext --inplace

执行python -c "from hello import hello;hello()" 即可直接引用生成的二进制文件中的hello()函数。

4.3 优点

生成的二进制.so或.pyd文件难以破解。

同时带来了性能提升。

4.4 不足

兼容性稍差,针对不同版本的操作系统可能需要重新编译。

虽然支持大多数Python代码,但若发现部分代码不支持,完善成本较高。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。