Не удалось расшифровать из стандартного ввода: “ошибка расшифровки открытого ключа: неподходящая ioctl для устройства”

Вопрос или проблема

Если я выполняю gpg foo.gpg, мне показывается диалоговое окно, которое выглядит следующим образом:

   ┌────────────────────────────────────────────────────────────────┐
   │ Пожалуйста, введите парольную фразу, чтобы разблокировать секре… │
   │ ключ OpenPGP: "Edward A. Falk <[email protected]>"                              │
   │ 1024-битный ELG ключ, ID xxxxxxxxxxxxxxxx,                      │
   │                                                                │
   │                                                                │
   │ Парольная фраза: _____________________________________________ │
   │                                                                │
   │         <ОК>                                     <Отмена>         │
   └────────────────────────────────────────────────────────────────┘

и все работает просто отлично.

Если я выполняю cat foo.gpg | gpg, я получаю

gpg: ошибка расшифровки публичного ключа: Неподходящий ioctl для устройства

Я пробовал --passphrase-fd 0 и --batch --pinentry-mode loopback, но безрезультатно. Мне удалось заставить это работать, указав парольную фразу в командной строке, но я действительно хочу этого избежать, если можно.

Я подозреваю, что это как-то связано с агентом pinentry, но я не совсем понимаю, как управлять агентом. (Я действительно не знаю, почему gpg вообще его требуется.)

Я использую gpg 2.2.26.


Одно небольшое пояснение: мой стандартный ввод на самом деле не поступает из “cat foo.gpg”; это больше похоже на aws s3 cp "s3://myawsbucket.tar.gz.gpg" -, где именованный бакет значительно больше, чем я хочу хранить на моем локальном компьютере, только чтобы расшифровать его и извлечь из него всего один файл.

Я выяснил, что мне нужно сделать по-другому. Оказалось, что если gpg-agent работает и правильно настроен, все будет работать. gpg-agent знает, как взаимодействовать с пользователем для получения парольной фразы. Дополнительную информацию смотрите в man-странице gpg-agent.

Ответ или решение

Причина возникновения ошибки "public key decryption failed: Inappropriate ioctl for device" при использовании команды gpg заключается в разнице работы механизмов обработки ввода/вывода данных в команде. Давайте рассмотрим основные аспекты, объясняющие, почему возникает эта ошибка и как ее можно устранить.

Теория

Ошибка "Inappropriate ioctl for device" связана с тем, что при использовании команды cat foo.gpg | gpg ввод данных для gpg осуществляется через пайп. В такой конфигурации gpg ожидает данные с stdin, но не может получить доступ к терминальному устройству для запроса пароля. Когда gpg запускается с файла, он имеет доступ к терминалу и может корректно запросить у пользователя ввод пароля через интерфейс pinentry, который используется агентом gpg.

GPG (GNU Privacy Guard) — это инструмент с открытым исходным кодом для шифрования и дешифрования данных, который использует различные криптографические алгоритмы. Поскольку многие команды Linux взаимодействуют с файлом или устройствами, GPG использует свою отдельную утилиту — gpg-agent — для управления вводом/выводом паролей.

Когда gpg-agent активен и правильно настроен, он обрабатывает запросы к пользователю о вводе пароля, независимо от того, как именно происходит запуск команды. В данном случае, отсутствие корректной настройки или работа gpg-agent может привести к тому, что gpg не может запросить пароль и соответственно выдает ошибку.

Пример

Вы можете запускаете следующую команду для дешифровки файла, используя stdin:

aws s3 cp "s3://myawsbucket.tar.gz.gpg" - | gpg

В результате возникает ошибка:

gpg: public key decryption failed: Inappropriate ioctl for device

Это связано с тем, что GPG не может получить доступ к терминальному устройству для запроса ввода пароля через стандартный PGP интерфейс, управляющийся gpg-agent.

Применение

Для решения этой проблемы необходимо следующее:

  1. Активировать и настроить gpg-agent. Убедитесь, что gpg-agent запущен и правильным образом настроен. Для активации можете использовать команду:

    gpgconf --launch gpg-agent
  2. Настроить файл конфигурации. Проверьте или создайте файл ~/.gnupg/gpg-agent.conf, чтобы он содержал:

    pinentry-program /usr/bin/pinentry
    allow-loopback-pinentry
  3. Перезапустить gpg-agent. После внесения изменений, агент необходимо перезапустить:

    gpgconf --kill gpg-agent
    gpgconf --launch gpg-agent
  4. Использовать –pinentry-mode=loopback. Теперь можете использовать ключи параметров для gpg:

    aws s3 cp "s3://myawsbucket.tar.gz.gpg" - | gpg --pinentry-mode=loopback --decrypt

    Оператор --pinentry-mode=loopback позволяет gpg использовать loopback для интерактивных запросов пароля через stdin, причем при этом активность gpg-agent остается необходимой, чтобы он обрабатывал все необходимые вызовы и не блокировал выполнение программы.

Настройка gpg-agent позволяет вам обрабатывать неудобные ситуации с вводом, например, когда stdin не может предоставить привычный набор команд для ввода пароля. Описанное решение позволит вам дешифровать файлы, которые не были скачаны локально полностью, с применением оболочки, что весьма важно в случае работы с большими объемами данных, например, в облачных средах.

Этот подход позволяет сохранять высокий уровень безопасности, недопуская ввод пароля через командную строку, что не рекомендуется из соображений безопасности. Надеюсь, что эта информация будет полезна и поможет устранить проблемы, связанные с дешифровкой файлов через gpg с использованием промежуточного пайплайна данных.

Оцените материал
Добавить комментарий

Капча загружается...