
Я сгенерировал закрытый ключ с помощью libressl 3.0 и curve secp521r1
.
openssl genpkey -aes128 -algorithm EC -pkeyopt ec_paramgen_curve:secp521r1 -pkeyopt ec_param_enc:named_curve
Насколько мне известно, эта кривая та же самая, которую использует ssh-keygen, ssh-keygen -t ecdsa -b 521
и из документации я знаю, что ssh-keygen теперь использует aes128 для шифрования закрытого ключа.
Размер закрытого ключа libressl составляет 534
, а размер ключа ssh-keygen — 736
.
У меня такой вопрос: что делает ssh-keygen дополнительно, что увеличивает размер ключа?
Также: являются ли оба варианта взаимозаменяемыми? Можно ли один закрытый ключ, сгенерированный в одном из них, преобразовать в другой?
решение1
TLDR: существует множество различных форматов файлов закрытых ключей.
И это частично зависит от версии OpenSSH, которую вы не указали.
Исторически сложилось так, что за исключением давно устаревшей версии протокола 1 (и типа ключа 'rsa1') OpenSSH использовал (часть libcrypto) OpenSSL для выполнения большинства своих криптографических операций, включая хранение закрытых ключей (или, по сути, пар ключей) в файлах с использованием«традиционные» или «устаревшие» форматы, определенные SSLeay/OpenSSL. OpenSSL также поддерживает «новые» (примерно с 1998 года!) форматы PKCS8, которые (несколько) более безопасны. Таким образом, OpenSSL поддерживает 4 формата PEM для «ECDSA» (точнее, X9-style Weierstrass EC, который охватывает как X9.62 ECDSA, так и X9.63 ECDH), из которых OpenSSHгенерируеттолько 2, но (используя libcrypto) может читать все. Когда ssh-keygen
шифруетOpenSSL-форматфайлы, последние версии используют AES-128-CBC, но это не всегда было так.
Начиная с версии 6.5 в 2014-01,OpenSSH добавил свой собственный «новый» формат файла, отчасти для обеспечения лучшей безопасности, чем устаревшие форматы OpenSSL (при шифровании), а отчасти для поддержки нового на тот момент алгоритма Ed25519, который OpenSSL тогда вообще не поддерживал. ssh-keygen
имел возможность -o
запрашивать новый формат для любого типа ключа, отличного от ed25519 (или rsa1), и вы найдете много Stack Q и A за последние несколько лет, ссылающихся и обычно рекомендующих эту опцию. Файлы «нового» формата по умолчанию шифруются с помощью AES256-CBC, который можно переопределить с помощью -Z ciphername
, но страница руководства, по-видимому, не была обновлена ни для одного из них. Начиная с выпуска 7.8 в 2018-08, OpenSSH теперь по умолчанию использует «новый» формат для всех типов ключей, хотя вы можете использовать -m pem
для запроса формата OpenSSL для чего-либо, отличного от ed25519. Если вы проверите man ssh-keygen
свою систему (если это не Windows), она должна описать один из этих случаев, вероятно, последний.
(Существует также формат PKCS12, он же PFX, который OpenSSLможетиспользовать для закрытого ключа, но обычно используется только для объединения закрытого ключа (или нескольких) с одним или несколькими сертификатами X.509 для этого(их) ключа(ей), что является другой ситуацией и не применимо к SSH, который никогда не использует сертификаты X.509. Другие программы или системы используют другие форматы: 'commercial'/Tectia SSH имеет свой собственный формат, а PuTTY имеет свой собственный формат PPK = PuTTY Private Key. И так далее, и так далее, Юл Бриннер. Все они семантически эквивалентны, и при наличии подходящих инструментов могут быть преобразованы друг в друга.)
Все форматы закрытых ключей, используемые OpenSSH,PEM-стиль; двоичные данные кодируются в текст как base64 со строками заголовка и концевика в форме
-----BEGIN (something)-----
(sometimes some headers here)
(data encoded in base64, broken into lines of 64 characters)
-----END (something)-----
так что вы можете определить, какой у вас формат, просто взглянув на эту линию тире-BEGIN. Смотрите near-crossdupeshttps://security.stackexchange.com/questions/39279/stronger-encryption-for-ssh-keysили более краткоhttps://security.stackexchange.com/questions/129724/how-to-check-if-an-ssh-private-key-has-passphrase-or-notиhttps://security.stackexchange.com/questions/200935/how-do-i-determine-if-an-existing-ssh-private-key-is-secure(мой).
Различия:размер 736 символов для ключа ecdsa-p521 соответствует новому формату OpenSSHнезашифрованный-- тыконечновы дали ему парольную фразу? -- и 534 соответствует зашифрованному формату PKCS8, созданному OpenSSL 1.0.2, который IIRC является, когда LibreSSL разветвился. (OpenSSL 1.1.0 и выше изменяет шифрование PKCS8 на использование HMAC-SHA256 в PBKDF2, что делает файл немного больше. OpenSSL 1.1.0 и выше также делает param_enc=named значением по умолчанию, поэтому вам больше не нужно его указывать.) Новый формат OpenSSH больше формата PKCS8-enc в основном потому, что, по непонятной причине, он хранит значение publickey (для ECDSA точка кривой в формате X9.62)дважды-- один раз в разделе файла, указанном для publickey, исновав разделе, указанном для privatekey. Кроме того, формат OpenSSH имеет большую часть своих метаданных в виде текстовых строк, и все поля длины 4 байта, в то время как PKCS8 (как и устаревшие форматы OpenSSL) использует ASN.1 с полями переменной длины, в основном только 1 байт, и метаданные в основном двоичные, особенно 'OID' для используемых алгоритмов.)
Также: являются ли оба варианта взаимозаменяемыми? Можно ли один закрытый ключ, сгенерированный в одном из них, преобразовать в другой?
И да, и нет. Как отмечено, OpenSSH с использованием OpenSSL может читать (но не записывать) PKCS8, поэтому ssh-keygen
может преобразовать его в OpenSSH-new, внеся в него нулевое изменение, т. е. «изменяя» пароль на существующее значение; с 6.5 по 7.7 вы должны указать, -o
а с 7.8 и выше это значение по умолчанию. Идя другим путем, ssh-keygen
можно преобразовать в OpenSSL-legacy, но не напрямую в PKCS8, вам нужно использовать openssl
для этого либо явно с помощью, pkcs8 -topk8
либо в 1.0.0 и выше (что к настоящему времени должно быть у всех, и определенно у всех LibreSSL), просто pkey
. (Первый по умолчанию зашифрован, а второй — незашифрован, но оба значения можно переопределить.)