16.05M
Category: softwaresoftware

Защита кода на Python или как скрывать нескрываемое?

1.

Защита кода
на Python
или как скрывать
нескрываемое?

2.

О чем доклад?
Повесть о развитии проекта
и о том, как мы дошли до жизни такой
Рассказ о боли защиты кода
Итоги, к которым мы пришли

3.

О себе
Руководитель отдела
Техлид
Backend: Python, Go
Иногда DevOps…

4.

Чем мы занимаемся?
Видеонаблюдение
Удаленная телеметрия
Умный дом
СКУД

5.

Чем мы занимаемся?

6.

Наша слава в интернете

7.

Коротко о проекте
Ядро
Python / Django
Service 1
Python
Service 2
Go

8.

Что такое УД?
Клиенты
ЮЛ
Клиенты

9.

Коробочное решение
Ядро
Python / Django
Service 1
Python
Service 2
Go

10.

Зачем?

11.

Зачем?
Законодательство

12.

Зачем?
Законодательство
Географическая
удаленность

13.

Зачем?
Законодательство
Географическая
удаленность
Так спокойнее

14.

Вопросы по перезду
Отрицание
Гнев
Торг
Депрессия
Как разворачивать?
Какие ресурсы нужны?
Защита кода

15.

От чего защищаться?

16.

От чего защищаться?
Защита
от модификации

17.

От чего защищаться?
Защита
от модификации
Защита
от тиражирования

18.

С этим вопросом…

19.

Критерии оценки методов

20.

Критерии оценки методов
Безопасность

21.

Критерии оценки методов
Безопасность
Простота
настройки

22.

Критерии оценки методов
Безопасность
Простота
настройки
Поддержка

23.

Нефункциональные требования

24.

Нефункциональные требования
Сохранить
преимущества языка

25.

Нефункциональные требования
Сохранить
преимущества языка
Как можно меньше
изменений в проекте

26.

Какие есть решения?

27.

Решение №1 - смирись

28.

Решение №1 - смирись
Python про другое!
Предназначен
делиться знаниями,
а не скрывать их

29.

Решение №1 - смирись
— А почему его зовут Неуловимым Джо, Билли?
— Потому что его никто ещё не поймал, Гарри.
— А почему его никто ещё не поймал, Билли?
— Потому что он никому не нужен, Гарри.

30.

Решение №1 – выводы
Ничего не нужно делать
Метод работает до первого мошенника
Безопасность
Простота настройки
Поддержка
1/10
10/10
10/10

31.

Решение №2 - перепиши

32.

Выводы
Код скрыт под компиляцией
Долго и дорого
Теряем преимущества Python
(простота синтаксиса, время онбординга, скорость разработки)
Безопасность
Простота настройки
Поддержка
9/10
2/10
7/10

33.

Решение №2.1 – перепиши на Cython
Cython – язык программирования,
упрощающий написание модулей
С/C++ кода для Python
http://docs.cython.org
/en/latest/src/tutorial
/pure.html
Особенности Cython:
- Работа со строками
- Оператор IS

34.

Решение №2.1 – выводы
Код скрыт под компиляцией
Можно передавать python-файлы без изменения
Для лучшей защиты кода требует разметки
Нюансы самого языка
Безопасность
Простота настройки
Поддержка
8/10
2/10
6/10

35.

Решение №2.2 – JIT-компилятор
https://numba.pydata.org/
from numba import jit
@jit
def f(x, y):
return x + y

36.

Решение №2.2 – выводы
Код скрыт под компиляцией
Обязательно требует разметки
Новый стек для команды
Безопасность
Простота настройки
Поддержка
8/10
2/10
4/10

37.

Решения №2 - выводы
Код становится более защищенным
Много месяцев разработки в 3 проектах
Безопасность
Простота настройки
Поддержка
9/10
2/10
8/10

38.

Решение №3 – отдавай pyc-файлы
Byte
Code
Run
Code

39.

Решение №3 – отдавай pyc-файлы
Обратимость байткода
def foo():
"""Тестовая функция"""
print("Hello, Ufadevconf!")
if __name__ == "__main__":
foo()
python -m compileall main.py

40.

Решение №3 – отдавай pyc-файлы
Обратимость байткода

41.

Решение №3 – отдавай pyc-файлы
Обратимость байткода
https://pypi.org/project/uncompyle6/

42.

Решение №3 – отдавай pyc-файлы
Обратимость байткода

43.

Решение №3 – выводы
Подходит, если нужно хоть как-то скрыть код
быстро и без переписывания
Нативен для Python
Безопасность
Простота настройки
Поддержка
0/10
9/10
9/10

44.

Решение №4 – обфускация кода
https://github.com/dashingsoft/pyarmor

45.

Решение №4 – выводы
Быстро
Trial-версия имеет ограничение в 32768 байт
Безопасность
Простота настройки
Поддержка
8/10
5/10
6/10

46.

Решение №5 – готовое решение

47.

Решение №6 – Pyinstaller
https://pyinstaller.org/en/stable/
pip install -U pyinstaller
pyinstaller your_program.py

48.

Решение №7 – свой импортер
PEP 302 – New Import Hooks
PEP 451 - A ModuleSpec Type for the Import System

49.

Решение №7 – свой импортер
Finder и Loader
PEP 302
До версии 3.4
- finder.find_module(fullname, path=None)
- loader.load_module(fullname)
PEP 451
С версии 3.4
-
finder.find_spec(name, path, target)
loader.exec_module(module)
loader.create_module(spec)

50.

Решение №7 – свой импортер
import foo
Делаем все возможное
sys.modules
sys.meta_path
sys.path_importer_cache
Нашли?
sys.path_hooks
Да
ImportError

51.

Решение №7 – свой импортер
SOURCE_SUFFIXES = ['.py']
BYTECODE_SUFFIXES = ['.pyc']
def _get_supported_file_loaders():
extensions = ExtensionFileLoader, _imp.extension_suffixes()
source = SourceFileLoader, SOURCE_SUFFIXES
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
return [extensions, source, bytecode]

52.

Решение №7 – свой импортер
Свой
Loader
class MyLoader(SourceLoader):
def get_data(self, filename):
with open(filename) as f:
a = f.read().encode('utf-8')
if a == b"":
return a
data = base64.b64decode(a)
return data

53.

Решение №7 – свой импортер
Инъекция в Python
loader_details = MyLoader, [".pyenc"]
def install():
sys.path_hooks.insert(0, MyFinder.path_hook(loader_details))
sys.path_importer_cache.clear()
invalidate_caches()

54.

Решение №7 – свой импортер
Пример
https://github.com/UsmanovTimur/encoding_django

55.

Решение №7 – выводы
Можно внести свою логику
Сложный в понимании и реализации
Некоторые python-библиотеки перестают работать
Безопасность
Простота настройки
Поддержка
7/10
1/10
1/10

56.

Могло быть так

57.

Решение №8 – транспиляция
Транспиляция – перевод исходного
кода программы с одного языка
программирования на другой.
Nuitka – транспайлер, который
транслирует код Python в исполняемые
файлы или исходный код C/C++

58.

Решение №8 – транспиляция
Варианты сборки
1) Собрать исполняемый файл
python -m nuitka --follow-imports program.py
Подходит для сервисов в себе
Долго собирается и много весит

59.

Решение №8 – транспиляция
Варианты сборки
2) Собрать исполняемый модуль
python -m nuitka --module some_module.py
Гибкий вариант
Есть шанс наплодить много файлов

60.

Решение №8 – транспиляция
Простой способ применения
for f in $(find . -name "*.py" |grep -v __init__.py)
do
echo $f
nuitka3 --module --output-dir=$(dirname $f)
--no-pyi-file $f
rm $f
done
--remove-output

61.

Решение №8 – транспиляция
Еще вариация
for f in $(cat encrypt_files.txt)
do
echo $f
nuitka3 --module --output-dir=$(dirname $f) $f
rm $f
done

62.

Решение №8 – транспиляция
Варианты сборки
3) Собрать исполняемый пакет
python -m nuitka --module package --include-package=package
В Django могут возникнуть проблемы с
импортами миграций
Их можно закрыть как модуль

63.

Решение №8 – транспиляция
Сборка пакета
nuitka3 --module core --include-package=core --removeoutput --no-pyi-file --follow-import-to=core

64.

Решение №8 – выводы
Если у вас компактный микросервис - супер
Если у вас монолит на 5k только python-файлов –
закрыть все не сможете
Итоговые бинарники работают “бесшовно”
Нужно шаманить с настройкой
Безопасность
Простота настройки
Поддержка
9/10
4-8/10
8/10

65.

Решение №9 – несофтовые способы
1) Шифрование ВМ
2) Железный сервер с эксклюзивным доступом
- Посчитать экономику
- Вопрос масштабирования и замены оборудования
1) Размещение в облаке той страны где клиент
- За пределами РФ – боль!
1) Добавьте ценность вашему продукту(обновления
багфиксы и т.д.)

66.

Выводы по решениям
Перепиши
Безопасность
Простота
настройки
Поддержка
PYC
Pyarmor
Pyinstaller
Importer
Nuitka
9
0
8
3
7
9
2
9
5
3
1
8
7
9
6
3
1
8

67.

Nuitka – нравиться!
Простота
Скорость внедрения
Гибкость настройки
Не нужно переучивать
разработчиков. Вся магия CI

68.

Конец
Спасибо за внимание!
English     Русский Rules