python
October 17

Защита реквизитов с Python

"Конфиденциальность — это не только право, это основа свободы." В эпоху цифровых технологий, когда данные становятся всё более ценным ресурсом, защита личной информации приобретает критическое значение. В этой статье я расскажу, как работать с конфиденциальными реквизитами в Python проекте.

load_dotenv


Первый способ - использовать функцию load_dotenv из модуля dotenv. Она позволяет считать строки вида ключ=значение из файла и загрузить их в переменные окружения с именем ключа. Обычно таким образом задаются конфиденциальные данные, как пароли, ключи API, которые не следует хранить в коде и тем более заливать в репозиторий.

Отмечу, что этот способ подойдет, если злоумышленник не имеет доступ к локальным файлам, так как пароль хранится в открытом виде. Продемонстрируем работу на практике. Сначала установим модуль python-dotenv и создадим файл:

!pip install python-dotenv -q

!mkdir pers
!printf ''' USER="user"\n\
PSWD="1pswd1" ''' > pers/.env

!cat .env

Теперь вызовем load_dotenv с указанием пути к файлу:

from dotenv import load_dotenv

load_dotenv('pers/.env')

После этого переменные из файла доступны через окружение:

import os
os.environ['USER'], os.environ['PSWD']

Если все равно страшно хранить реквизиты в открытом файле, можно немного усложнить и, например, хранить часть пароля в файле, а часть добавлять из кода (но это все равно не безопасное решение). В функции ниже прописано такое поведение - при отсутствии создается файл с реквизитами (лучше, чтобы каждый раз при старте сессии, после удалять), при этом первый и последний символы, пароля не хранятся в файле, а добавляются в коде:

from getpass import getpass

def get_creds():

    if not os.path.exists('pers/.env'):
        cred = getpass()
        with open('pers/.env', 'wt') as f_wr:
            f_wr.write(f'PSWD={cred[1:-1]}')

    load_dotenv('pers/.env')
    PSWD = '1'+os.environ['PSWD']+'1'

    return PSWD return PSWD

Удалим файл, старое значением переменной окружения и вызовем функцию:

!rm pers/.env
del os.environ['PSWD']
USER = 'user'
PSWD = get_creds()
PSWD

Пароль правильный и он не хранится в файле полностью:

!cat pers/.env

Если вы делаете проект, который будет запускать лицо с другими реквизитами (например, заказчик), удобно функцию get_creds не показывать, а объявить в отдельно модуле, который не попадет в репозиторий. При этом в отдельном общедоступном py файле прописать переменные USER = 'user', PSWD = get_creds(). Во время передачи проекта указать, что следует задать в переменной PSWD пароль для запуска или для большей безопасности прописать там getpass.

keyring


Когда существует опасность доступа злоумышленника к вашим файлам, надежным способом хранения реквизитов является их шифрование. Как вариант, можно воспользоваться модулем keyring. Сначала установим необходимые библиотеки:

pip install keyring keyrings.alt pycryptodome -q
import keyring
from keyrings.alt.file import EncryptedKeyring

Зададим тип хранилища:

keyring.set_keyring(EncryptedKeyring())

Для записи или обновления пароля можно использовать функцию set_password модуля keyring. Первый параметр - имя сервиса (ключа), к которому привязан пароль:

keyring.set_password('main', 'user', '1pswd1')

Для получения пароля необходимо указать имя сервиса и логин, а функция при первом ее вызове потребует ввод пароля хранилища, который задавался в set_password:

keyring.get_password('main', 'user')

Для получения пути к файлу с зашифрованным паролем можно вызвать атрибут file_path класса EncryptedKeyring:

EncryptedKeyring().file_path
!cat /root/.local/share/python_keyring/crypted_pass.cfg

Также есть и другие способы получения пути к файлу с реквизитами, которые в зависимости от системы могут сработать или нет:

  1. keyring.get_keyring() в ячейке
  2. keyring diagnose в терминале