Как зашифровать файл Python
Обновлено: 21.11.2024
Soroco рада написать свой первый пост в блоге о том, как мы модифицировали язык Python, чтобы сделать развертывание кода Python более безопасным в рабочей среде.
Несмотря на то, что Python – это мощный и продуктивный язык для построения систем, его развертывание в производственной среде создает большую поверхность для атаки, которая позволяет злоумышленнику изменять или реконструировать потенциально конфиденциальную бизнес-логику.
В Soroco мы всегда ставим защиту бизнес-логики наших клиентов на первое место. Эта защита должна обеспечиваться как от злоумышленников, так и от естественных источников, таких как битовая гниль на диске или ошибки передачи по сети. Ниже мы описываем, как мы шифруем и добавляем HMAC к каждому файлу Python, который мы отправляем для этих целей.
Мы также говорили об этом на PyCon Delhi:
Общие методы и проблемы для Python
Распространенными методами защиты кода в рабочей среде являются двоичная подпись, обфускация или шифрование. Но эти методы обычно предполагают, что мы защищаем либо один файл (EXE), либо небольшой набор файлов (EXE и DLL).
Когда мы работаем с программами Python, не нужно подписывать ни одного двоичного файла. В отличие от скомпилированных языков, таких как C, Rust или Go, у вас нет ни одного исполняемого файла для защиты в полевых условиях.
С Python ваша поверхность атаки намного шире. Таким образом, мы не можем просто подписать двоичный файл, обфускация на самом деле ничего не защищает, и обычно есть много файлов, которые требуют шифрования. Не говоря уже о том, что интерпретатор Python не может загружать подписанные или зашифрованные файлы.
Да, для Python существуют статические компиляторы, такие как Cython, но их языковые функции всегда отстают от эталонной реализации Python. Нам нужно было решение, которое будет работать с эталонной реализацией Python, чтобы использовать преимущества новейших функций.
Таким образом, наши требования были тройными:
- Работа с эталонной реализацией Python,
- Обеспечить надежную защиту кода от вредоносных и естественных угроз.
- Быть производительным как по времени выполнения, так и по занимаемому месту.
Это привело нас к решению на чистом Python, использующем аутентифицированную криптографию.
Представляем расширение .pyce
На наших рабочих серверах вы найдете необычное расширение файла: .pyce . Вы, вероятно, привыкли к .pyc — скомпилированному байт-коду Python — и .py — необработанному исходному коду Python. Но вы никогда раньше не видели .pyce. Это потому, что он существует только в Soroco!
Рисунок 1. Формат .pyce на диске.
Мы используем конструкцию "зашифровать-затем-MAC", как показано на рис. 1. Этот формат шифрует байт-код Python с помощью AES-256 и сохраняет зашифрованный текст с добавлением HMAC в виде открытого текста. HMAC создается с использованием секретного ключа и SHA-512 в качестве криптографически безопасной хеш-функции.
Во время выполнения мы проверяем HMAC перед расшифровкой зашифрованного текста. Это гарантирует целостность (каждый бит точно соответствует назначению) кода, а также его подлинность — он исходит от объекта, контролирующего секретный ключ. Это также гарантирует, что мы не будем тратить время на расшифровку или выполнение даже одного бита, который не был задуман нашими инженерами.
Загрузка .pyce в Python
Но как нам получить эталонную реализацию Python.exe, работающую в формате .pyce?
Оказывается, интерпретатор Python имеет механизм импорта, который вы можете подключить для загрузки всего, что захотите. По сути, вы можете легко настроить и изменить значение импорта в Python!
Рис. 2. Мы реализовали загрузку .pyce путем подключения к sys.meta_path и наследования от предварительно определенных классов механизма импорта.
На приведенном выше рисунке 2 показано, как мы подключаемся к механизму импорта Python. Добавляем специальный SorocoPathFinder в начало списка известных загрузчиков модулей. sys.meta_path перечисляет все загрузчики для интерпретатора Python. Три показанных выше должны быть вам знакомы:
-
: загружает модули, встроенные в среду выполнения языка : загружает модули в автономном замороженном формате : загружает модули с известными расширениями файлов на пути Python
Как работает код? Прежде всего, мы повторно используем два промежуточных класса для их существующей реализации: PathFinder и FileFinder. Другими словами, мы извлекаем выгоду из всего того, что уже реализовано в импортной технике. Эти два класса ищут путь Python и вызывают наш специальный загрузчик расшифровки только в том случае, если они находят файл модуля с правильным расширением: .pyce. Вся магия происходит внутри SorocoFileLoader, который наследуется от SourcelessFileLoader:
Рисунок 3.Код из класса SorocoFileLoader, демонстрирующий расшифровку и загрузку зашифрованного файла.
Приведенный выше код в значительной степени взят из эталонной реализации Python с вставленной единственной строкой, вызывающей функцию под названием decrypt . Тот факт, что его реализация состоит всего из 5 строк исполняемого кода, свидетельствует о гибкости языка Python.
Именно эту мощную гибкость использует Soroco в своей собственной среде выполнения Python, ориентированной на автоматизацию бизнес-процессов.
Оптимизация пространства с помощью конвергентного шифрования
В наших производственных системах мы часто развертываем множество повторяющихся файлов. Это связано с общими библиотеками, в некоторых случаях общими кодовыми базами и общими ресурсами. В качестве оптимизации мы дедуплицируем слои хранилища, чтобы минимизировать занимаемую площадь на диске.
Но как мы можем дедуплицировать зашифрованные файлы? Зашифрованные данные изначально неотличимы от случайных данных. Таким образом, если мы зашифруем один и тот же файл Python 10 раз, мы получим 10 уникальных файлов.
Мы используем конвергентное шифрование для защиты конфиденциальной бизнес-логики, но по-прежнему создаем один и тот же зашифрованный текст при представлении одного и того же открытого текста. Мы находимся в таком сценарии, что злоумышленники не могут выбрать открытый текст. Поэтому они могут получать информацию только об общеизвестных файлах, таких как библиотеки с открытым исходным кодом. Поскольку мы уже раскрываем библиотеки с открытым исходным кодом, которые мы используем в производстве, мы не рассматриваем это как риск.
Рис. 4. Реализация конвергентного шифрования с использованием AES-256 и SHA-256.
На рис. 4 выше мы воспроизводим наш основной код конвергентного шифрования. Конвергентное шифрование принципиально зависит от детерминированной генерации ключа шифрования. Мы используем SHA-256 для детерминированного создания уникального 256-битного ключа для каждого файла, который затем шифруем с помощью AES-256. Одноразовый номер для режима счетчика детерминировано устанавливается на первые 16 байтов ключа. После шифрования мы используем HMAC с SHA-512 в качестве алгоритма хэширования, с детерминированным ключом с тем же хэшем SHA-256, что и открытый текст.
Распределение ключей
Естественно, мы никогда не хотим, чтобы ключи касались диска в текстовом формате. Мы всегда храним ключи на безопасном уровне хранения, реализующем криптографический барьер, то есть хранящиеся данные всегда зашифрованы. Например, хранилище Hashicorp реализует безопасный барьер записи. Когда мы выполняем на производственных серверах, наша среда выполнения передает словарь в формате JSON со всеми ключами через стандартный ввод в исполняемый процесс Python. Затем он возобновляет нормальное выполнение после считывания ключей. Всякий раз, когда импорт инициирует загрузку файла .pyce, наш пользовательский SorocoFileLoader, как показано на рис. 2, проверяет этот кэш ключей, проверяет HMAC, расшифровывает и загружает байт-код в кэш Python в памяти.
Производительность и влияние на производство
Наша реализация не требует накладных расходов. Это связано с кэшем байт-кода в памяти Python. Только когда наши процессы начинают выполняться и сначала импортируют байт-код, происходит расшифровка. Таким образом, при нормальной работе на время выполнения бизнес-логики Soroco никак не влияет!
Закрепление памяти
Для особо параноиков вам следует закрепить пространство памяти вашего процесса Python таким образом, чтобы он никогда не выгружался на диск. Закрепление памяти гарантирует, что бизнес-логика открытого текста никогда не будет постоянно храниться, равно как и ключи дешифрования. Из-за кэша байт-кода в памяти Python расшифрованная бизнес-логика может быть выгружена на диск. Закрепление области памяти вашего процесса устраняет этот риск.
Заключение
В этой статье мы узнаем, как шифровать и расшифровывать файлы с помощью Python с помощью криптографической библиотеки. Другими словами, вы можете сказать, что в этом руководстве вы узнаете, как защитить файлы с помощью Python? Мы живем в современном мире, где передача данных/информации очень проста и доступна. Но безопасная передача данных также важна, поэтому безопасность данных остается одной из самых больших проблем.
Шифрование: шифрование — это процесс преобразования обычного текста во что-то бессмысленное, которое будет выглядеть случайным (зашифрованный текст).
Расшифровка: дешифрование — это процесс преобразования зашифрованных файлов обратно в обычные файлы, которые мы можем понять (открытый текст).
Мы собираемся посмотреть, как мы можем шифровать и расшифровывать файлы с помощью Python, и в Python у нас есть библиотека, которая делает процесс шифрования и дешифрования очень простым. В этом руководстве мы будем следовать симметричному типу шифрования (симметричное шифрование: когда кто-то использует симметричное шифрование для шифрования файла или сообщения, только этот человек может прочитать файл, расшифровав его с помощью того же ключа, который он использовал для шифрования файла. Это означает, что ключ, который используется для шифрования файла или сообщения, только этот ключ может расшифровать файл обратно. Если у вас нет ключа или вы потеряли ключ, вы не сможете получить к нему доступ).
Как защитить файлы с помощью Python и криптографии?
- Установка библиотеки криптографии Python.
- Создание ключа для шифрования.
- Загружается ключ.
- Шифрование файла.
- Расшифровка файла.
Шаг 1. Установка библиотеки криптографии для Python:
Если у вас нет криптографической библиотеки, нам нужно установить ее, откройте командную строку или терминал, вставьте приведенную ниже команду и нажмите клавишу ввода:
Шаг 2. Генерация ключа для шифрования
Теперь откройте свою любимую IDE и создайте новый файл Python. Здесь мы используем симметричное уравнение для криптографии, для этого нам нужно импортировать fernet, это аутентифицированная криптография, которая не позволяет вам манипулировать или читать сообщение без использования «ключа», если у вас его нет, вы можете' не читал.
Теперь давайте сгенерируем ключ и сохраним его в том же месте/папке, где находится наш файл данных:
После запуска этого кода вы можете проверить место, где находится ваш код Python, вы должны увидеть новое имя файла unlock.key. Если вы хотите, вы можете открыть его в любом текстовом редакторе (код Microsoft Visual Studio). Вы можете видеть в файле, что он содержит наш ключ, который должен быть строкой из нескольких случайных символов.
Теперь, когда у нас есть ключ, давайте загрузим его в нашу среду, чтобы зашифровать/расшифровать файл. Дальше шаг очень простой, нам просто нужно открыть файл «unlock.key» и сохранить его в локальной системной памяти:
Для проверки мы видим следующий вывод, а также видим, что ключ шифрования хранится локально в системной памяти.
Шаг 3. Шифрование файла
Теперь у нас есть файл для шифрования и ключ шифрования, теперь мы обсудим, как писать код, а затем кодировать его:
Давайте обсудим, что нам нужно сделать для шифрования файла. Прежде всего, нам нужно инициализировать Fernet и сохранить файл в переменной fernet. Во-вторых, мы должны прочитать исходный файл (sample.txt). Затем мы должны зашифровать данные с помощью fernet и сохранить их в зашифрованном виде в объект. Затем, наконец, мы можем записать его в новый файл с именем «enc_sample.txt»
Давайте посмотрим код этого процесса:
Вывод
При выполнении кода вы должны увидеть что-то вроде этого:
Шаг 4. Расшифровка файла
После того как вы зашифровали файл, вы можете удалить исходный файл и не забудьте перенести созданный вами файл в другое место. Поскольку у вас есть шифрование исходного файла, вы можете расшифровать этот файл в любое время. В этом разделе мы увидим, как мы можем расшифровать его обратно в исходное содержимое.
Это просто: вам просто нужно повторить тот же процесс в обратном порядке, как в предыдущем разделе. Это точно такой же процесс, поэтому давайте обсудим, как мы можем преобразовать зашифрованный файл в расшифрованный файл, а затем закодировать его.
Во-первых, мы должны инициализировать объект Fernet и сохранить его в переменной fernet. Далее нам нужно прочитать зашифрованный файл (enc_sample.txt). Затем нам нужно расшифровать зашифрованный файл с помощью объекта Fernet и сохранить его как объект. и, наконец, мы запишем его в новый файл с именем «dec_sample.txt».
Давайте посмотрим код этого процесса:
Вывод
При выполнении кода вы должны увидеть следующий вывод:
Если вы сравните расшифрованный файл, который мы создали (dec_sample.txt), и исходный файл (sample.txt), вы увидите, что содержимое обоих файлов одинаково, что означает, что наш процесс шифрования и дешифрования прошел успешно.< /p>
Заключительные слова
В этой статье мы узнали, как использовать симметричный тип шифрования файлов для шифрования и расшифровки файла и данных внутри файла с помощью языка программирования под названием Python и библиотеки под названием криптография. В этой библиотеке шифрование файлов и дешифрование простой процесс. Нам не нужно реализовывать наш логический алгоритм, вы можете просто сгенерировать ключ, зашифровать файл, а затем расшифровать с помощью ключа, это безопасно и просто. Итак, как защитить файлы с помощью Python? Это легко, правда?
Дайте нам знать, если у вас есть какие-либо вопросы/комментарии относительно этого процесса.
Удачного кодирования!
Я хочу создать файл в программе python3, в котором я хочу хранить некоторую информацию, которую я не хочу, чтобы пользователи видели или манипулировали ею. Однако во время выполнения мне нужно прочитать и изменить его содержимое, будучи уверенным, что пользователи не могут изменить содержимое файла. Как я могу этого добиться?
3 ответа 3
Вся информация, хранящаяся на устройствах конечных пользователей, в конечном итоге может быть изменена.
Одним из вариантов является хранение данных, которыми пользователи не должны манипулировать, на веб-сервере и извлечение/обновление их при необходимости. Недостатком этого подхода является то, что ваш код не может работать в автономном режиме.
Есть ли у вас ссылка, где я могу найти, как это сделать? Можно ли сохранить информацию локально и отправить ее при наличии связи?
"Вся информация, хранящаяся на устройствах конечных пользователей, в конечном итоге может быть изменена", так что нет, у меня нет никаких предложений по этому поводу.
Вы можете хранить личную информацию в объекте python, например. словарь и т. д., а затем скомпилировать его (.py-->.pyc), зашифровать исходный файл (.py-->.py.cpt) и, наконец, опубликовать только скомпилированный файл, возможно, с его зашифрованной парой (сохраняя ключ шифрования при себе).
Дополнительную информацию можно найти здесь.
В этом примере я использовал Fernet и ключ, созданный с паролем "hardcode". Вы можете зашифровать файл и расшифровать информацию внутри только тогда, когда это необходимо. Если вам нужно изменить информацию, вы можете просто снова вызвать функцию шифрования.
Планируете ли вы жестко закодировать пароль или ключ? Если это так, то это определенно не выход.
@PedroLobito это был просто пример того, как работает Fernet. Конечно, можно создать лучший ключ и не использовать жестко заданный пароль.
@PedroLobito, однако, есть случаи, когда вы можете использовать «веб-сервер и извлекать/обновлять его при необходимости», как в ответе ChatoPaka, и случаи, когда вы не можете использовать это решение. В моем случае клиент использует мое программное обеспечение на очень больших производствах, где есть множество операторов, которые могут работать с моими файлами конфигурации. Нельзя сказать «не трогайте эти файлы», потому что 100% их кто-то тронет. В этих случаях я полагаю, что «глупой» защиты от шифрования может быть достаточно, чтобы решить эту проблему.
Не совсем понял: в этом примере программному обеспечению не нужно хардкодить пароль "my_password", его должен хранить оператор? Или я не понимаю?
Когда вы использовали: "key = hashlib.md5(encoded_Pwd).hexdigest()", это создание открытого ключа из закрытого ключа "encoded_Pw"?
«Почему сотрудники службы безопасности хватают людей и пытают их? Чтобы получить их информацию. Если вы создадите систему управления информацией, которая концентрирует информацию от десятков людей, вы сделаете ее в десятки раз более привлекательной. Вы обратили внимание репрессивного режима на жесткий диск. И жесткие диски не выдерживают пыток. Вы должны дать жесткому диску возможность сопротивляться. Это криптография».
До сих пор наши программы работали только с небольшими сообщениями, которые мы вводим непосредственно в исходный код в виде строковых значений. Программа шифрования в этой главе будет использовать шифр перестановки для шифрования и дешифрования целых файлов, размер которых может составлять миллионы символов.
Обычные текстовые файлы
Эта программа шифрует и расшифровывает текстовые файлы. Это файлы, которые содержат только текстовые данные и обычно имеют расширение .txt. Файлы из программ обработки текстов, которые позволяют изменять шрифт, цвет или размер текста, не создают файлы с обычным текстом. Вы можете создавать свои собственные текстовые файлы, используя Блокнот (в Windows), TextMate или TextEdit (в OS X), gedit (в Linux) или аналогичную программу для редактирования обычного текста. Вы даже можете использовать собственный редактор файлов IDLE и сохранять файлы с расширением .txt вместо обычного расширения .py.
Для некоторых примеров вы можете скачать следующие текстовые файлы с веб-сайта этой книги:
Если вы получаете сообщение об ошибке, похожее на «UnicodeDecodeError: кодек 'charmap' не может декодировать байт 0x90 в позиции 148: сопоставление символов с », значит, вы запускаете программу шифрования с непростым текстовым файлом, также называемым «двоичный файл».
Исходный код программы шифрования файла преобразования
Как и наша программа тестирования шифра перестановки, программа файла шифра перестановки импортирует наши файлы transpositionEncrypt.py и transpositionDecrypt.py, чтобы мы могли использовать в них функции encryptMessage() и decryptMessage(). Таким образом, нам не нужно повторно набирать код этих функций в нашей новой программе.
Исходный код для transpositionFileCipher.py
<р>4. время импорта, os, sys, transpositionEncrypt, transpositionDecrypt <р>7. inputFilename = 'frankenstein.txt' <р>10. outputFilename = 'frankenstein.encrypted.txt' <р>15. если не os.path.exists(inputFilename): <р>16. print('Файл %s не существует. Выход. ' % (inputFilename)) <р>20. если os.path.exists(outputFilename):21. print('Это перезапишет файл %s. (C)продолжить или (Q)уйти?' % (outputFilename))
22. ответ = ввод('> ')
23. если нет response.lower().startswith('c'):
27. fileObj = открыть (входное имя_файла)
28. содержимое = fileObj.read()
31. print('%sing.' % (myMode.title()))
34. startTime = время.время()
35. если myMode == 'зашифровать':
36. переведено = transpositionEncrypt.encryptMessage(myKey, content)
37. elif myMode == 'расшифровать':
38. translation = transpositionDecrypt.decryptMessage(myKey, content)
39. totalTime = round(time.time() - startTime, 2)
40. print('%время сеанса: %s секунд' % (myMode.title(), totalTime))
43. outputFileObj = open(outputFilename, 'w')
47. print('Готово %sing %s (%s символов).' % (myMode, inputFilename, len(content)))
48.print('%sed file is %s.' % (myMode.title(), outputFilename))
<р>53. если __name__ == '__main__':В каталоге, в котором находятся файлы frankenstein.txt и transpositionFileCipher.py, появится новый файл с именем frankenstein.encrypted.txt, содержащий содержимое frankenstein.txt в зашифрованном виде. Если дважды щелкнуть файл, чтобы открыть его, он должен выглядеть примерно так:
(остальное вырезано для краткости)
Чтобы расшифровать, внесите следующие изменения в исходный код (выделены жирным шрифтом) и снова запустите программу шифрования перестановки:
<р>7. inputFilename = 'frankenstein.encrypted.txt' <р>10. outputFilename = 'frankenstein.decrypted.txt'На этот раз, когда вы запустите программу, в папке появится новый файл с именем frankenstein.decrypted.txt, который идентичен исходному файлу frankenstein.txt.
Пример запуска программы шифрования файлов
Когда вы запускаете указанную выше программу, она выводит следующее:
Время шифрования: 1,21 секунды
Завершено шифрование файла frankenstein.txt (441034 символа).
Зашифрованный файл - frankenstein.encrypted.txt.
Новый файл frankenstein.encrypted.txt будет создан в том же каталоге, что и transpositionFileCipher.py . Если вы откроете этот файл в файловом редакторе IDLE, вы увидите зашифрованное содержимое frankenstein.py. Теперь вы можете отправить кому-нибудь этот зашифрованный файл по электронной почте, чтобы он расшифровал его.
Чтение из файлов
До сих пор любой ввод, который мы хотим дать нашим программам, должен был быть введен пользователем. Программы Python могут открывать и читать файлы прямо с жесткого диска. Чтение содержимого файла выполняется в три этапа: открытие файла, чтение в переменную и закрытие файла.
Функция open() и файловые объекты
Первый параметр функции open() — это строка с именем открываемого файла. Если файл находится в том же каталоге, что и программа Python, вы можете просто ввести имя, например «thetimemachine.txt». Вы всегда можете указать абсолютный путь к файлу, включая каталог, в котором он находится. Например, «c:\\Python32\\frankenstein.txt» (в Windows) и «/usr/foobar/frankenstein.txt». (в OS X и Linux) являются абсолютными именами файлов. (Помните, что перед \ обратной косой чертой должна стоять другая обратная косая черта.)
Функция open() возвращает значение типа данных «файловый объект». Это значение имеет несколько методов чтения, записи и закрытия файла.
Метод файлового объекта read()
Метод read() вернет строку, содержащую весь текст в файле. Например, предположим, что файл spam.txt содержит текст «Hello world!». (Вы можете создать этот файл самостоятельно с помощью редактора файлов IDLE. Просто сохраните файл с расширением .txt.) Запустите в интерактивной оболочке следующее (эти коды предполагают, что вы используете Windows, а файл spam.txt находится в каталоге c:\ каталог):
Если ваш текстовый файл состоит из нескольких строк, строка, возвращаемая функцией read(), будет содержать \n символов новой строки в конце каждой строки. Когда вы пытаетесь напечатать строку с символами новой строки, строка будет напечатана на нескольких строках:
Если вы получили сообщение об ошибке «IOError: [Errno 2] Нет такого файла или каталога», дважды проверьте правильность ввода имени файла (и, если это абсолютный путь, имя каталога). Также убедитесь, что файл действительно находится там, где вы думаете.
Метод файлового объекта close()
После того как вы прочитали содержимое файла в переменную, вы можете сообщить Python, что с файлом покончено, вызвав метод close() для файлового объекта.
Python автоматически закроет все открытые файлы при завершении работы программы. Но если вы хотите перечитать содержимое файла, вы должны закрыть объект файла, а затем снова вызвать функцию open() для файла.
Вот код нашей программы перестановочного шифра, который считывает файл, имя которого хранится в переменной inputFilename:
27. fileObj = открыть (входное имя_файла)
28. содержимое = fileObj.read()
Запись в файлы
Мы читаем исходный файл и теперь запишем зашифрованную (или расшифрованную) форму в другой файл. Файловый объект, возвращаемый open(), имеет функцию write(), хотя вы можете использовать эту функцию только в том случае, если вы открываете файл в режиме «записи», а не в режиме «чтения». Вы делаете это, передавая строковое значение 'w' в качестве второго параметра. Например:
>>> fo = open('имя файла.txt', 'w')
Наряду с «чтением» и «записью» есть еще режим «добавления». «Добавление» похоже на режим «записи», за исключением того, что любые строки, записанные в файл, будут добавлены в конец любого содержимого, которое уже находится в файле. Режим «Добавить» не перезапишет файл, если он уже существует. Чтобы открыть файл в режиме добавления, передайте строку 'a' в качестве второго аргумента функции open() .
(На всякий случай, если вам интересно, вы можете передать строку 'r' в open(), чтобы открыть файл в режиме чтения.Но поскольку без передачи второго аргумента файл также открывается в режиме чтения, нет причин передавать 'r' .)
Метод файлового объекта write()
Вы можете записать текст в файл, вызвав метод write() файлового объекта. Файловый объект должен быть открыт в режиме записи, иначе вы получите сообщение об ошибке «io.UnsupportedOperation: not readable». (И если вы попытаетесь вызвать read() для файлового объекта, который был открыт в режиме записи, вы получите сообщение об ошибке «io.UnsupportedOperation: not readable».)
Метод write() принимает один аргумент: строку текста, которая должна быть записана в файл. Строки с 43 по 45 открывают файл в режиме записи, выполняют запись в файл, а затем закрывают объект файла.
43. outputFileObj = open(outputFilename, 'w')
Теперь, когда у нас есть основы чтения и записи файлов, давайте посмотрим на исходный код программы шифрования файла преобразования.
Как работает программа
<р>4. время импорта, os, sys, transpositionEncrypt, transpositionDecrypt <р>7. inputFilename = 'frankenstein.txt' <р>10. outputFilename = 'frankenstein.encrypted.txt'Первая часть программы должна показаться вам знакомой. Строка 4 — это оператор импорта для наших программ transpositionEncrypt.py и transpositionDecrypt.py. Он также импортирует модули Python time , os и sys.
Функция main() будет вызываться после выполнения операторов def для определения всех функций в программе. Переменная inputFilename содержит строку файла для чтения, а зашифрованный (или расшифрованный) текст записывается в файл с именем в outputFilename .
Шифр перестановки использует целое число для ключа, хранящегося в myKey . Если в myMode хранится 'encrypt', программа зашифрует содержимое файла inputFilename. Если 'decrypt' хранится в myMode , содержимое inputFilename будет расшифровано.
Функция os.path.exists()
Чтение файлов всегда безвредно, но при записи файлов нужно соблюдать осторожность. Если мы вызовем функцию open() в режиме записи с уже существующим именем файла, этот файл будет сначала удален, чтобы освободить место для нового файла. Это означает, что мы можем случайно стереть важный файл, если передадим имя важного файла в функцию open(). Используя функцию os.path.exists(), мы можем проверить, существует ли уже файл с определенным именем.
Файл os.path.exists() имеет единственный строковый параметр для имени файла и возвращает значение True, если этот файл уже существует, и значение False, если его нет. Функция os.path.exists() существует внутри модуля path, который сам существует внутри модуля os. Но если мы импортируем модуль os, модуль пути тоже будет импортирован.
Попробуйте ввести в интерактивную оболочку следующее:
(Конечно, вы получите вышеуказанные результаты, только если вы используете Python в Windows. Файл calc.exe не существует в OS X или Linux.)
<р>15. если не os.path.exists(inputFilename): <р>16. print('Файл %s не существует. Выход. ' % (inputFilename))Мы используем функцию os.path.exists(), чтобы проверить, что имя файла в inputFilename действительно существует. В противном случае у нас нет файла для шифрования или расшифровки. В этом случае мы показываем сообщение пользователю и затем выходим из программы.
Строковые методы startwith() и endwith()
<р>20. если os.path.exists(outputFilename):21. print('Это перезапишет файл %s. (C)продолжить или (Q)уйти?' % (outputFilename))
22. ответ = ввод('> ')
23. если нет response.lower().startswith('c'):
Если файл, в который программа будет выполнять запись, уже существует, пользователю будет предложено ввести «C», если он хочет продолжить выполнение программы, или «Q», чтобы выйти из программы.
Для строки в переменной ответа будет вызван метод lower(), а для строки, возвращенной функцией lower(), будет вызван строковый метод startwith(). Метод startwith() вернет значение True, если его строковый аргумент находится в начале строки. Попробуйте ввести в интерактивную оболочку следующее:
>>> 'привет, мир!'.startswith('привет, привет')
В строке 23, если пользователь не ввел 'c' , 'continue' , 'C' или другую строку, начинающуюся с C, для завершения программы будет вызвана функция sys.exit(). Технически пользователю не нужно вводить «Q», чтобы выйти; любая строка, которая не начинается с «C», вызовет функцию sys.exit() для выхода из программы.
Существует также строковый метод endwith(), который можно использовать для проверки того, заканчивается ли строковое значение другим определенным строковым значением. Попробуйте ввести в интерактивную оболочку следующее:
Строковый метод title()
Точно так же, как строковые методы lower() и upper() возвращают строку в нижнем или верхнем регистре, строковый метод title() возвращает строку в «заглавном регистре». Регистр заглавия — это когда каждое слово вводится в верхнем регистре для первого символа и в нижнем регистре для остальных символов. Попробуйте ввести в интерактивную оболочку следующее:
>>> 'привет, мир! КАК ТЫ?'.title()
'Привет, мир! Как дела?"
>>> 'дополнительно! дополнительный! человек кусает акулу!'.title()
'Дополнительно! Дополнительный! Человек кусает акулу!"
27. fileObj = открыть (входное имя_файла)
28. содержимое = fileObj.read()
31. print('%sing.' % (myMode.title()))
Строки с 27 по 29 открывают файл с именем, хранящимся в inputFilename, и считывают его содержимое в переменную content. В строке 31 мы отображаем сообщение, сообщающее пользователю, что шифрование или дешифрование началось. Поскольку myMode должен либо содержать строку 'encrypt', либо 'decrypt', вызов строкового метода title() будет отображать либо 'Encrypting. " или "Расшифровка. ' .
Модуль time и функция time.time()
На всех компьютерах есть часы, которые отслеживают текущую дату и время. Ваши программы Python могут получить доступ к этим часам, вызвав функцию time.time(). (Это функция с именем time(), которая находится в модуле с именем time.)
Функция time.time() вернет значение с плавающей запятой количества секунд с 1 января 1970 года. Этот момент называется эпохой Unix. Попробуйте ввести в интерактивную оболочку следующее:
Значение с плавающей запятой показывает, что функция time.time() может иметь точность до миллисекунды (то есть 1/1000 секунды). Конечно, числа, которые time.time() отображает для вас, будут зависеть от момента времени, когда вы вызываете эту функцию. Может быть неясно, что 1349411356.892 — это четверг, 4 октября 2012 г., около 21:30. Однако функция time.time() полезна для сравнения количества секунд между вызовами time.time(). Мы можем использовать эту функцию, чтобы определить, как долго работает наша программа.
34. startTime = время.время()
35. если myMode == 'зашифровать':
36. переведено = transpositionEncrypt.encryptMessage(myKey, content)
37. elif myMode == 'расшифровать':
38. translation = transpositionDecrypt.decryptMessage(myKey, content)
39. totalTime = round(time.time() - startTime, 2)
40. print('%время сеанса: %s секунд' % (myMode.title(), totalTime))
Мы хотим измерить, сколько времени занимает процесс шифрования или дешифрования содержимого файла. Строки с 35 по 38 вызывают функцию encryptMessage() или decryptMessage() (в зависимости от того, хранится ли в переменной myMode значение 'encrypt' или 'decrypt'). Однако перед этим кодом мы вызовем time.time() и сохраним текущее время в переменной с именем startTime .
В строке 39 после возврата вызовов функций шифрования или дешифрования мы снова вызовем time.time() и вычтем из него значение startTime. Это даст нам количество секунд между двумя вызовами time.time() .
Например, если вычесть значения с плавающей запятой, возвращаемые при вызове time.time() в интерактивной оболочке, вы получите количество времени между этими вызовами, пока я печатаю:
Выражение time.time() - startTime оценивается как значение, которое передается функции round(), которая округляет до двух ближайших десятичных знаков. Это значение хранится в totalTime. В строке 40 количество времени отображается пользователю с помощью вызова функции print() .
Назад к Кодексу
43. outputFileObj = open(outputFilename, 'w')
Содержимое зашифрованного (или расшифрованного) файла теперь хранится в переведенной переменной. Но эта строка будет забыта, когда программа завершится, поэтому мы хотим записать строку в файл, чтобы сохранить ее на жестком диске. Код в строках с 43 по 45 делает это, открывая новый файл (передавая 'w' в open(), чтобы открыть файл в режиме записи), а затем вызывая метод файлового объекта write().
47. print('Готово %sing %s (%s символов).' % (myMode, inputFilename, len(content)))
48. print('%sed file is %s.' % (myMode.title(), outputFilename))
<р>53. если __name__ == '__main__':После этого мы выводим пользователю еще несколько сообщений о том, что процесс завершен, и о том, как называется записанный файл. Строка 48 — последняя строка функции main().
Строки 53 и 54 (которые выполняются после выполнения оператора def в строке 6) вызовут функцию main(), если эта программа запускается, а не импортируется. (Это объясняется в главе 8, в разделе «Специальная переменная __name__».)
Практические упражнения, глава 11, набор А
Обзор
Поздравляем! В этой новой программе не было ничего особенного, кроме функций open(), write(), read() и close(), но это позволяет нам шифровать текстовые файлы на нашем жестком диске размером в мегабайты или гигабайты. Для этого не потребуется много нового кода, потому что вся реализация шифра уже написана. Мы можем расширять наши программы (например, добавлять возможности чтения и записи файлов), импортируя их функции для использования в новых программах. Это значительно расширяет наши возможности использования компьютеров для шифрования информации.
Существует слишком много возможных ключей, чтобы просто перебрать и изучить вывод сообщения, зашифрованного с помощью шифра перестановки. Но если мы сможем написать программу, которая распознает английский язык (в отличие от строк тарабарщины), мы сможем заставить компьютер изучить результаты тысяч попыток дешифрования и определить, какой ключ может успешно расшифровать сообщение на английском языке.
Криптография — это пакет Python, используемый для шифрования или дешифрования файлов, таких как текстовый файл, файл документа, файл csv, файл Python и т. д.
Здесь мы будем использовать криптографический модуль fernet для генерации ключа шифрования и шифрования файла с помощью метода encrypt().
Шифрование файла преобразует обычный текст в зашифрованный текст, который можно расшифровать только с использованием того же ключа шифрования.
Установка:
Предположим, у нас есть файл test.txt, как показано ниже.
Зашифровать текстовый файл
Вывод:
Давайте разберемся с кодом.
После импорта зависимостей сгенерируйте ключ с помощью метода generate_key().
Сохраните ключ в файле file_key.key.
Загрузить сгенерированный ключ с экземпляром класса Fernet.
Прочитайте файл, который вы хотите зашифровать.
Зашифровать файл с помощью метода encrypt().
Перезаписать файл с зашифрованными данными.
Расшифровать текстовый файл
Вывод:
Давайте рассмотрим еще один пример шифрования и расшифровки следующего файла Python (pytest.py).
Зашифровать файл Python
Вывод:
Расшифровать файл Python
Вывод:
Таким образом, мы можем шифровать или расшифровывать такие файлы, как текстовый файл, файл документа, файл csv и т. д.
Читайте также: