Передача учетных данных в командной строке небезопасна. Это приведет к тому, что ваш пароль будет виден в списке процессов системы - даже если openssl удалит его из списка процессов, как только сможет, он будет там на мгновение.
openssl
дает вам несколько способов передачи учетных данных - на странице руководства есть раздел «ПАРАМЕТРЫ ПАРОЛЬНОЙ ФРАЗЫ», который документирует все способы передачи учетных данных в openssl
. Я объясню соответствующие:
ENV: вар
Позволяет передавать учетные данные в переменную среды. Это лучше, чем использование списка процессов, потому что в Linux среда вашего процесса по умолчанию не читается другими пользователями, но это не обязательно верно для других платформ.
Недостатком является то, что другие процессы, работающие от имени того же пользователя или от имени root, смогут легко просматривать пароль через /proc.
.
Это довольно легко использовать с подпроцессом python:
new_env=copy.deepcopy(os.environ)
new_env["MY_PASSWORD_VAR"] = "my key data"
p = subprocess.Popen(["openssl",..., "-passin", "env:MY_PASSWORD_VAR"], env=new_env)
ФД: номер
Это позволяет вам openssl
прочитать учетные данные из файлового дескриптора, который, как он полагает, уже открыт для чтения. Используя это, вы можете записать данные ключа непосредственно из вашего процесса в openssl, примерно так:
r, w = os.pipe()
p = subprocess.Popen(["openssl", ..., "-passin", "fd:%i" % r], preexec_fn=lambda:os.close(w))
os.write(w, "my key data\n")
os.close(w)
Это сохранит ваш пароль в безопасности от других пользователей в той же системе, при условии, что они вошли в систему с другой учетной записью.
С помощью приведенного выше кода вы можете столкнуться с проблемами с блокировкой вызовов os.write
. Это может произойти, если openssl
ждет, пока что-то произойдет, прежде чем считывать ввод. Это может быть решено с помощью асинхронного ввода-вывода (например, цикла выбора) или дополнительного потока для выполнения write () & close ().
Одним из недостатков этого является то, что он не будет работать, если вы передадите closeFds=true
в подпроцесс. Подпроцесс не может сказать «не закрывать один конкретный fd», поэтому если вам нужно использовать closeFds = true, тогда я бы предложил использовать синтаксис file:
(ниже) с именованным каналом.
Файл: путь к файлу
Не используйте это с реальным файлом для хранения паролей! Этого следует избегать по многим причинам, например, Ваша программа может быть уничтожена до того, как сможет стереть файл, и в большинстве журналируемых файловых систем практически невозможно действительно стереть данные с диска.
Однако, если используется с именованным каналом с ограничивающими разрешениями, это может быть так же хорошо, как использование опции fd
выше. Код для этого будет аналогичен предыдущему фрагменту, за исключением того, что вам необходимо создать fifo вместо использования os.pipe()
:
pathToFifo = my_function_that_securely_makes_a_fifo()
p = subprocess.Popen(["openssl", ..., "-passin", "file:%s" % pathToFifo])
fifo = open(pathToFifo, 'w')
print >> fifo, "my key data"
fifo.close()
У print
здесь могут быть те же проблемы с блокировкой ввода / вывода, что и у вызова os.write
выше, разрешения также такие же.