Pull to refresh

Как обезопасить исходники своего python-приложения

Reading time 2 min
Views 45K
Рано или поздно все python-разработчики стают перед выбором: отдать заказчику приложение в исходниках или скрыть их. И вот во втором случае у многих (особенно недавно знакомых с этим прелестным языком) начинаются проблемы: поиск по гуглу, как правило, ничего не дает, идей никаких (или все бредовые).

И что же делать в таком случае?

Первой мыслью было отдавать pyc-файлы. Тогда я ещё не вникал в то, что это такое на самом деле. После нескольких часов проведённых в поисках ответов чем это грозит был сделан единственно возможный вывод: вариант не пройдет. Для python < 2.7 «декомпиляторов» полно бесплатных, а 2.7 и выше за сравнительно небольшие деньги обещают выдать в виде исходных кодов. Да ещё и эта тулза, с которой я за считанные мгновения получил свой код один-в-один.

Вариант сборки в бинарник показался достаточно заманчивым. Вот только, как оказалось, все сборщики (ниже я приведу пример cx_Freeze) фактически только и делают что пакуют .pyc в архив, то есть абсолютно не защищают исходные коды.

А потом меня осенило.

Предложим у нас есть проект проект с такой структурой (это всего лиш пример):

TestModule/__init__.py
TestModule/Config.py
ui/__init__.py
ui/mainwindow.py
ui/loginwindow.py
main.py

Тут сразу хотелось бы отметить два момента:
  1. В файле main.py у нас должен быть фактически только вызов главного модуля, если же там что-то большее — желательно оформить это в отдельный модуль
  2. Файлы __init__.py желательно чтоб были вообще пустые.


Делаем несколько простых манипуляций:
  1. $ sudo apt-get install cython
  2. Создаем в корне проекта файл compile.py:
    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext
    
    ext_modules = [
        Extension("TestModule.Config", ["TestModule/Config.py"]),
        Extension("ui.mainwindow", ["ui/mainwindow.py"]),
        Extension("ui.loginwindow", ["ui/loginwindow.py"]),
        ]
    
    setup(
        name = 'Test App',
        cmdclass = {'build_ext': build_ext},
        ext_modules = ext_modules
    )
    

  3. Там же (в корне проекта) выполняем
    $ python compile.py build_ext --inplace
  4. теперь можем удалить все файлы в подкаталогах кроме *.so и __init__.py


После проверки на работоспособность все должно работать точно так же как и прежде.
Вот и все, исходники теперь точно никто не прочитает. Правда отдавать приложение пока рано, заказчик ведь не захочет устанавливать и настраивать питон со всеми использованными вами модулями. Потому собираем все в «пакет»:
  1. $ sudo apt-get install cx-freeze
  2. В корне проекта создаем файл pack.py:
    from cx_Freeze import setup, Executable   
    
    setup(   
        name = "Test App",   
        version = "0.1",   
        description = "test",   
        executables = [Executable("main.py")])  
    
  3. $ python pack.py build
  4. Копируем «свои» папки из папки проекта в build/exe.linux-x86_64-2.7
  5. Пробуем запустить полученный бинарник и, если надо, копируем недостающие библиотеки (в моем случае это был PyQt)


После проверки можно отдавать пакет заказчику.

P.S. Надеюсь кому-то это простое how-to сэкономит столько же времени, сколько могло бы сэкономить мне.
Tags:
Hubs:
+59
Comments 63
Comments Comments 63

Articles