Перейти к содержимому
ecdsa.com
Командная строка

OpenSSH (ssh-keygen)

OpenSSH 10 — набор программ SSH, в котором ssh-keygen также преобразует ключи и подписывает файлы и коммиты git: Ed25519 по умолчанию, гибридный обмен ключами ML-KEM на первом месте, DSA удалён, а подписи ECDSA записываются в собственной кодировке SSH mpint.
Лицензия
SSH-OpenSSH
Проверенная версия
10.3p1 ·
Исходный код
github.com/openssh/openssh-portable
Документация
www.openssh.com/manual.html

Совместимость вкратце

ECDSAEdDSAПостквантовая криптография

Кривые ECDSA
P-256P-384P-521
EdDSA
Ed25519
Форматы закрытых ключей
pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

Помимо ssh и sshd, в OpenSSH входит ssh-keygen, который генерирует и преобразует ключи, а с -Y sign создаёт подписи SSHSIG для файлов и коммитов git. Факты на этой странице проверены на пакетах Alpine 3.24.2 с OpenSSH 10.3p1, скомпонованным с OpenSSL 3.5.8 из того же образа. Если не указать -t, ssh-keygen записывает ключ Ed25519. Ключи ECDSA бывают только для P-256, P-384 и P-521 (-b 224 отклоняется), Ed448 нет, а DSA удалён: на ssh-keygen -t dsa утилита отвечает «unknown key type dsa». Разберите любой ключ в инспекторе SSH-ключей.

Без файла конфигурации клиент первым предлагает гибридный обмен ключами mlkem768x25519-sha256, затем sntrup761x25519-sha512 — это постквантовая защита ключей сеанса. ssh -Q sig не выводит ни одного постквантового алгоритма подписи, поэтому аутентификация хоста и пользователя остаётся классической. RSA с SHA-1 (ssh-rsa) по-прежнему реализован, но отсутствует в списках алгоритмов ключей хоста и открытых ключей по умолчанию, поэтому с настройками по умолчанию клиент его никогда не использует; для стороны, которая не предлагает ничего новее ssh-rsa, его нужно явно включить снова, например директивой PubkeyAcceptedAlgorithms +ssh-rsa для пользовательских ключей. Какие алгоритмы согласует сервер, проверьте в аудите SSH-сервера.

Подпись ECDSA в SSH — это ни DER, ни raw r‖s: blob состоит из строки ecdsa-sha2-nistp256, за которой следует строка с r и s в виде чисел SSH mpint (RFC 5656). Поэтому преобразование подписей в X.509, JWS или WebAuthn и обратно требует сменить кодировку двух целых чисел. Nonce случайны (две подписи одного файла различались), s не нормализуется, а подпись, в которой s заменили на n − s, прошла проверку.

При создании подписей SSHSIG (ssh-keygen -Y sign) сообщение по умолчанию хешируется SHA-512; единственная альтернатива — -O hashalg=sha256, а SHA-1 и SHA-384 отклоняются. Пространство имён, заданное через -n, входит в подписываемые данные, и проверка подписи с пространством имён file как email завершается ошибкой «namespace does not match». Причины неудачи различимы в stderr: «invalid format» для повреждённого blob и «incorrect signature» для верной подписи других данных, а stdout в обоих случаях выводит «Could not verify signature.» Проверьте подпись в инструменте проверки SSH-подписей.

ssh-keygen -e -m PKCS8 экспортирует открытый ключ в SPKI PEM, а -i -m PKCS8 импортирует его обратно; -m PEM тоже даёт SPKI для ECDSA, но PKCS#1 для RSA, а -m RFC4716 — формат «SSH2 PUBLIC KEY». Открытые ключи Ed25519 нельзя экспортировать через -e -m PKCS8 («unsupported key type ED25519»), хотя -p -m PKCS8 перезаписывает закрытый ключ Ed25519 в PKCS#8. Закрытые ключи по умолчанию хранятся в формате OPENSSH PRIVATE KEY; -p -m PEM перезаписывает ключи ECDSA в SEC1, а ключи RSA — в PKCS#1, и -m PKCS8 с парольной фразой записывает зашифрованный PKCS#8.

Факты и проверки, на которых они основаны

Ничего из приведённого ниже не скопировано из документации. 20 октября 2026 г. проверка content/libraries/verify/openssh/run.sh запустила OpenSSH (ssh-keygen) 10.3p1 в образе контейнера alpine:3.24.2; содержимое страницы должно совпадать с выводом проверки, а у каждого факта приведены соответствующие строки вывода.

  • Тип ключа по умолчанию

    ed25519

    ssh-keygen без -t записал ключ ssh-ed25519.

    Что записала проверка
    fact default-key-type = ed25519
    evidence default-key-type: ssh-keygen without -t wrote a ssh-ed25519 key
  • Кривые ECDSA

    P-256P-384P-521

    -b 256, 384 и 521; -b 224 отклоняется с сообщением «valid lengths are 256, 384 or 521 bits».

    Что записала проверка
    fact ecdsa-curves = P-256, P-384, P-521
    evidence ecdsa-curves: ssh -Q key: ssh-ed25519 ssh-ed25519-cert-v01@openssh.com sk-ssh-ed25519@openssh.com sk-ssh-ed25519-cert-v01@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp256-cert-v01@openssh.com ecdsa-sha2-nistp384 ecdsa-sha2-nistp384-cert-v01@openssh.com ecdsa-sha2-nistp521 ecdsa-sha2-nistp521-cert-v01@openssh.com sk-ecdsa-sha2-nistp256@openssh.com sk-ecdsa-sha2-nistp256-cert-v01@openssh.com ssh-rsa ssh-rsa-cert-v01@openssh.com
  • EdDSA

    Ed25519

    ssh -Q key выводит ssh-ed25519 и его вариант для FIDO; типа ключа Ed448 нет.

    Что записала проверка
    fact eddsa = Ed25519
  • Ключи DSA

    removed

    ssh-keygen -t dsa завершается ошибкой «unknown key type dsa», а ssh-dss отсутствует в выводе ssh -Q key.

    Что записала проверка
    fact dsa-keys = removed
  • Обмен ключами по умолчанию

    mlkem768x25519-sha256

    Первая запись kexalgorithms в выводе ssh -F none -G.

    Что записала проверка
    fact default-kex = mlkem768x25519-sha256
    evidence default-kex: ssh -F none -G: kexalgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
  • Постквантовые алгоритмы

    ML-KEMsntrup761

    Гибридный обмен ключами mlkem768x25519-sha256 и sntrup761x25519-sha512; в ssh -Q sig нет ни одного постквантового алгоритма подписи.

    Что записала проверка
    fact pqc = ML-KEM, sntrup761
    evidence pqc: ssh -Q kex: diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 curve25519-sha256 curve25519-sha256@libssh.org sntrup761x25519-sha512 sntrup761x25519-sha512@openssh.com mlkem768x25519-sha256
    evidence pqc: ssh -Q sig: ssh-ed25519 sk-ssh-ed25519@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 sk-ecdsa-sha2-nistp256@openssh.com webauthn-sk-ecdsa-sha2-nistp256@openssh.com ssh-rsa rsa-sha2-256 rsa-sha2-512
  • Подписи ssh-rsa с SHA-1

    disabled-by-default

    ssh-rsa есть в ssh -Q sig, но отсутствует в pubkeyacceptedalgorithms и hostkeyalgorithms по умолчанию.

    Что записала проверка
    fact ssh-rsa-sha1 = disabled-by-default
    evidence ssh-rsa-sha1: ssh-rsa in ssh -Q sig: yes; in the default pubkeyacceptedalgorithms or hostkeyalgorithms: no
    evidence ssh-rsa-sha1: with -o PubkeyAcceptedAlgorithms=+ssh-rsa it is in the list: yes
  • Кодировка подписи ECDSA

    ssh-mpint

    Blob подписи SSHSIG содержит строку типа, а также r и s в минимальной кодировке SSH mpint.

    Что записала проверка
    fact ecdsa-signature-encoding = ssh-mpint
    evidence ecdsa-signature-encoding: ssh-keygen -Y sign: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • Nonce в ECDSA

    random

    Две подписи одного файла различались.

    Что записала проверка
    fact ecdsa-nonce = random
    evidence ecdsa-nonce: two signatures of one file are different
  • Low-S при подписи

    either

    s не нормализуется: среди 32 подписей встретились значения high-S.

    Что записала проверка
    fact ecdsa-low-s-sign = either
    evidence ecdsa-low-s-sign: signatures with s > n/2 among 32: yes
  • High-S при проверке

    accepts-high-s

    Подпись, в которой s заменили на n − s, прошла проверку с результатом «Good».

    Что записала проверка
    fact ecdsa-low-s-verify = accepts-high-s
    evidence ecdsa-low-s-verify: s replaced by n - s: ok
  • Вывод проверки при ошибке

    distinguishable

    В stderr выводится «invalid format» для raw r‖s и для 3-байтового фрагмента данных и «incorrect signature» для неверного сообщения; код возврата в обоих случаях — 255.

    Что записала проверка
    fact cli-verify-output = distinguishable
  • Хеш-функция SSHSIG по умолчанию

    sha512

    В заголовке SSHSIG подписи с настройками по умолчанию указан sha512.

    Что записала проверка
    fact sshsig-default-hash = sha512
    evidence sshsig-default-hash: hash=sha512 type=ecdsa-sha2-nistp256 mpints=yes
  • Хеш-алгоритмы SSHSIG

    sha256sha512

    -O hashalg= принял sha256 и sha512 и отклонил sha1 и sha384.

    Что записала проверка
    fact sshsig-hash-algorithms = sha256, sha512
    evidence sshsig-hash-algorithms: ssh-keygen -Y sign -O hashalg= accepted: sha256, sha512
  • Пространство имён SSHSIG

    enforced

    Подпись, созданная с -n file, не прошла проверку с -n email: «namespace does not match».

    Что записала проверка
    fact sshsig-namespace = enforced
  • Форматы открытых ключей

    spki-pemopensshpkcs1

    SPKI PEM (-e -m PKCS8, импорт обратно через -i), строка OpenSSH и PKCS#1 для RSA (-e -m PEM).

    Что записала проверка
    fact public-key-formats = spki-pem, openssh, pkcs1
    evidence public-key-formats: P-256 -e -m PKCS8: -----BEGIN PUBLIC KEY-----, -i back to the same key: yes
    evidence public-key-formats: P-256 -e -m PEM: -----BEGIN PUBLIC KEY-----; -e -m RFC4716: ---- BEGIN SSH2 PUBLIC KEY ----
    evidence public-key-formats: RSA -e -m PEM: -----BEGIN RSA PUBLIC KEY-----, -i back to the same key: yes
  • Форматы закрытых ключей

    pkcs8-pemencrypted-pkcs8sec1-pempkcs1openssh

    Помимо формата OpenSSH по умолчанию: PKCS#8, зашифрованный PKCS#8 и SEC1 для ECDSA и PKCS#1 для RSA; ssh-keygen -y прочитал обратно каждый из них.

    Что записала проверка
    fact private-key-formats = pkcs8-pem, encrypted-pkcs8, sec1-pem, pkcs1, openssh
    evidence private-key-formats: P-256 default: -----BEGIN OPENSSH PRIVATE KEY-----; -m PKCS8: -----BEGIN PRIVATE KEY----- (read back: yes); -m PKCS8 with a passphrase: -----BEGIN ENCRYPTED PRIVATE KEY----- (read back: yes); -m PEM: -----BEGIN EC PRIVATE KEY----- (read back: yes)
    evidence private-key-formats: RSA -m PEM: -----BEGIN RSA PRIVATE KEY----- (read back: yes); Ed25519 -m PKCS8: -----BEGIN PRIVATE KEY----- (read back: yes); Ed25519 -m PEM: refused

Использование

Сгенерируйте ключ Ed25519, подпишите файл в пространстве имён `file` и проверьте подпись по файлу allowed_signers.
# Without -t, ssh-keygen generates an Ed25519 key.
ssh-keygen -q -N "" -C alice@example.com -f id_ed25519
printf 'order #1042 approved\n' > order.txt

# -n names what the signature is for; a different namespace fails verification.
ssh-keygen -q -Y sign -f id_ed25519 -n file order.txt   # writes order.txt.sig

# Verifiers trust keys through allowed_signers: a principal, then the public key.
echo "alice@example.com $(cut -d' ' -f1,2 id_ed25519.pub)" > allowed_signers
ssh-keygen -Y verify -f allowed_signers -I alice@example.com -n file -s order.txt.sig < order.txt

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

Подготовка
apk add --no-cache -q openssh-keygen=10.3_p1-r1 >/dev/null
Команда
sh sign.sh
Вывод должен совпадать (регулярное выражение)
Good "file" signature for alice@example\.com with ED25519 key SHA256:

Библиотеки