1 背景
在一些使用python的商業項目上,開發人員不想被用戶看到源代碼時,就需要對python代碼進行加密。
這裏提供一種代碼加密的思路。
2 代碼加密
衆所周知,python是一種開源的編程語言,在開源的語言上做加密,加密效果肯定不如編譯性語言的加密效果好,其逆向工程的難度會比編譯性語言的逆向工程簡單,按照這個思路,既然編譯性語言c/c++的逆向工程難,那麼爲何不先把python編譯成c/c++代碼,然後再加密呢?根據經驗這樣是可行的,且這樣加密的代碼比那些編譯成pyd文件或者打包成exe的方法就安全得多(pyd和exe的逆向工程有專門的包可以實現)。這就是這篇文章介紹的加密方法。
思路是先將py轉換爲c代碼,然後編譯c爲so文件。
python安裝第三方庫:
pycrypto
Cython
pip install pycrypto Cython
加密腳本“setup.py”的代碼如下
# python代碼:(在原項目中編寫setup.py文件)
from distutils.core import setup
from Cython.Build import cythonize
import os
'''
該文件的執行需要的在Terminal中輸入 python setup.py build_ext --inplace
使用Cpython 編譯python文件,關鍵函數編譯成pyd文件(相當於dll)
'''
# 針對多文件情況設置,單文件就只寫一個就行
key_funs = ["test.py"]
setup(
name="XX app",
ext_modules=cythonize(key_funs),
)
'''
1、將編譯後的pyd文件的命名更改成與原py文件一致
2、刪除編譯後得到的c文件和原py文件
'''
files = os.listdir(os.getcwd())
print(files)
for fi in files:
if fi.__contains__(".pyd"):
re_name = fi.split(".")[0] + ".pyd"
print(re_name)
print(fi, re_name)
os.rename(fi, re_name)
elif fi.__contains__(".c") or fi in key_funs:
os.remove(fi)
print(fi)
# 運行方式 在原目錄的命令行下執行
# python setup.py build_ext --inplace
3 舉例說明
爲了更好的說明,這裏舉個簡單的例子。
另外準備兩個py文件,test.py
和 main.py
,其中test.py
是需要加密的代碼,main.py
是調用加密代碼的腳本,不需要加密。
test.py
的內容如下
import datetime
class Today():
def get_time(self):
print(datetime.datetime.now())
def say(self):
print('hello world')
main.py的內容如下
from test import Today
t = Today()
t.get_time()
t.say()
加密之前,測試一下運行效果,在終端執行python main.py
,輸出
2020-05-24 16:02:38.419308
hello world
使用setup.py對test.py進行加密
方法:將需要加密的代碼放到列表key_funs裏面,然後在終端運行
python setup.py build_ext --inplace
運行完加密腳本setup.py後,會將test.py刪掉(請備份到其他地方!),得到test.so文件和文件夾build/,這個文件夾可以刪掉。至此代碼加密完成。
測試
再次在終端執行python main.py,輸出
2020-05-24 16:09:34.416438
hello world
成功!!!
(注意,不能直接在IDE執行main.py,會出現錯誤ImportError: cannot import name ‘Today’)