当前位置: 首页 > 后端技术 > Python

保护你的Python代码:现有的加密方案

时间:2023-03-25 20:07:14 Python

由于Python的动态性和开源特性,很难很好地加密Python代码。社区内有声音认为,这样的限制是事实,商业保护的目的应该通过法律手段来实现,而不是对源代码进行加密;而一些声音则希望有一种方法可以加密。于是乎,人们想出了各种加密或混淆方案来达到保护源代码的目的。常见的源码保护方式有以下几种:发布.pyc文件代码混淆使用py2exe使用Cython下面简单说一下这些解决方案。1发布.pyc文件1.1思路我们都知道,Python解释器在执行代码时,会先生成一个.pyc文件,然后解释执行.pyc文件的内容。当然,Python解释器也可以直接执行.pyc文件。.pyc文件是二进制文件,不能直接看到源代码的内容。如果将代码作为.pyc文件而不是.py文件发布到客户环境,是否可以保护Python代码?1.2方法将.py文件编译成.pyc文件非常简单。您不需要运行所有代码,然后转到生成的.pyc文件。事实上,在Python标准库中有一个名为compileall的库可以使编译变得容易。执行以下命令遍历目录下的所有.py文件,编译成.pyc文件:python-mcompileall然后删除目录下的所有.py文件打包发布:$find-name'*.py'-typef-print-execrm{}\;1.3优点简单方便,提高源码破解门槛,平台兼容性好,其中.py可以run,.pyc可以在哪运行1.4InsufficientInterpreter兼容性差,.pyc只能在特定版本的解释器上运行有现成的反编译工具,破解成本低python-uncompyle6就是这样的反编译工具,效果是杰出的。执行如下命令将.pyc文件反编译成.py文件:$uncompyle6*compiled-python-file-pyc-or-pyo*2代码混淆如果代码混淆到一定程度,连作者都看不下去了在它身上,是不是也能达到保护源代码的目的呢?2.1思路既然我们的目的是为了混淆,也就是通过一系列的转换让代码变得不那么容易理解,那么我们可以这样着手:-去掉注释和文档。没有这些说明,要理解一些关键逻辑就没那么容易了。-更改缩进。完美的缩进只会让人看起来舒服。如果压痕长或短,看起来一定会令人不安。-在令牌中间添加一定的空间。这与更改缩进具有相同的效果。-重命名函数、类、变量。命名直接影响可读性,乱七八糟的名字会成为阅读理解的一大障碍。-在空白行插入无效代码。这就是蒙眼法,用不相关的代码打乱阅读节奏。2.2方法方法一:使用oxyry进行混淆http://pyob.oxyry.com/是一个在线Python代码混淆网站,可以用来方便混淆。假设我们有这么一段Python代码,涉及类、函数、参数等:#coding:utf-8classA(object):"""Description"""def__init__(self,x,y,default=None):self.z=x+yself.default=defaultdefname(self):return'NoName'defalways():returnTruenum=1a=A(num,999,100)a.name()always()passesOxyry的混淆,得到如下代码:classA(object):#line:4""#line:7def__init__(O0O0O0OO00OO000O0,OO0O0OOOO0000O0OO,OO0OO00O00OO00OOO,OO000OOO0O000OOO0=None):#line:9O0O0O0OO00OO000O0.z=OO0O0OOOO0000O0OO+OO0OO00O00OO00OOO#line:10O0O0O0OO00OO000O0.default=OO000OOO0O000OOO0#line:11defname(O000O0O0O00O0O0OO):#line:13return'NoName'#line:14defalways():#line:17returnTrue#line:18num=1#行:line:21a=A(num,999,100)#line:22a.name()#line:23always()混淆代码主要调整在注释、参数名和空格,带来一点阅读障碍。方法二:使用pyobfuscate库进行混淆pyobfuscate是一个老牌的Python代码混淆库,但是“老生常谈”。上面同一段Python代码,pyobfuscate混淆后的效果如下:#coding:utf-8if64-64:i11iiiiiiif65-65:O0/iiii1I11I1II1%Ooooooooo-i1IIIiclasso0OO00(object):if78-78:i11i。oOoo0OoifO0o10-10:IIiI1I11i11如果54-54:i11iIi1-oOo0O0Ooo如果2-2:o0*i1*ii1IiI1i%OOooOOo/I11i/Ii1Idef__init__(self,x,y,default=None):self.y=x+自我。default=defaultif48-48:iII11i%IiII+I1Ii111/ooOoO0o*Ii1Idefname(self):return'NoName'if46-46:ooOoO0o*I11i-OooooooooOOif30-30:o0-O0%o0-OooooooooOO*O0*OooooooooOOdefOo0o():如果60-60则返回True:i1+I1Ii111-I11i/i1IIi如果40-40:oOooOoO0Oo0O/O0%ooOoO0o+O0*i1IIiI1Ii11I1Ii1i=1Ooo=o0OO00(I1Ii11I11I1I1Ii1i=1Ooo=o0OO00(I1Ii11I,19i19i)oo()Oo0o()#dd678faae9ac167bc83abf78e5cb2f3f0688d3a3与方法一相比,方法二的效果看起来更好。除了重命名类和函数、添加一些空格以及最值得注意的是插入几段不相关的代码之外,它变得更加难以阅读。2.3优点简单方便,源码破解门槛提高了一点。兼容性好。只要源代码逻辑能够兼容,混淆后的代码也可以使用。代码结构没有变化,字节码也可以得到,破解难度不大。3使用py2exe3.1思路py2exe是Windows平台上将Python脚本转换成可执行文件的工具。其原理是将源代码编译成一个.pyc文件,连同必要的依赖文件,一起打包成一个可执行文件。如果py2exe打包好的二进制文件最终发布出来,那不就达到了保护源代码的目的了吗?3.2使用py2exe打包的步骤比较简单。1)编写入口文件。本例中命名为hello.py:print'HelloWorld'2)写入setup.py:fromdistutils.coreimportsetupimportpy2exesetup(console=['hello.py'])3)生成可执行文件pythonsetup.py的py2exe生成的可执行文件位于disthello.exe。3.3优点可以直接打包成exe,方便分发执行。破解门槛高于.pyc。.pyc文件,然后反编译源码4使用Cython4.1的思路虽然Cython的主要目的是提高性能,但是基于它的原理:将.py/.pyx编译成.c文件,然后再编译.c文件被编译为.so(Unix)或.pyd(Windows),这具有难以破解的额外好处。4.2使用Cython开发方法的步骤并不复杂。1)写入文件hello.pyx或hello.py:defhello():print('hello')2)写入setup.py:fromdistutils.coreimportsetupfromCython.Buildimportcythonizesetup(name='HelloWorldapp',ext_modules=cythonize('hello.pyx'))3)编译成.c,再编译成.so或.pyd:pythonsetup.pybuild_ext--inplaceexecutepython-c"fromhelloimporthello;hello()”可以直接引用生成的二进制文件中的hello()函数。4.3优点生成的二进制.so或.pyd文件不易破解,带来性能提升。4.4不足兼容性略差。对于不同版本的操作系统,可能需要重新编译。虽然支持大部分Python代码,但如果发现部分代码不支持,改进成本高文源网,仅供学习,如有侵权,联系删除。我的公众号【Python圈】里收集了优质的技术文章和经验总结。为了方便大家,我也整理了一套学习资料,免费提供给热爱Python的同学们!还有学习交流群,多交流问题才能进步更快~