Можно ли подписать файл с помощью ключа ssh?

36

Я использую SSH (если быть точным, OpenSSH 5.5p1 в Linux). У меня есть ключ, на котором у меня есть пароль. Я использую это для обычного входа в компьютерные вещи.

Могу ли я также использовать его для подписи файлов?

Насколько я понимаю, ключ SSH является ключом RSA (или DSA), и во время процесса входа в систему SSH он используется для подписи сообщений, отправляемых на сервер. Таким образом, в принципе и на практике, он может быть использован для подписания вещей - действительно, это его единственная цель.

Но, насколько я вижу, нет способа использовать ключ для подписи произвольного файла (как, скажем, с PGP). Есть ли способ сделать это?

Том Андерсон
источник
Разве OpenSSH не использует Ed25519 в качестве протокола данных ? Кажется, только вопрос инструментов.
Пабло А

Ответы:

24

Не может быть способа сделать это только с помощью инструментов OpenSSH.

Но это можно сделать довольно легко с помощью инструментов OpenSSL. На самом деле, есть как минимум два способа сделать это. В приведенных ниже примерах ~/.ssh/id_rsaэто ваш личный ключ.

Одним из способов является использование dgst :

openssl dgst -sign ~/.ssh/id_rsa some-file

Другой использует pkeyutl :

openssl pkeyutl -sign -inkey ~/.ssh/id_rsa -in some-file

Оба они записывают двоичную подпись в стандартный вывод. Параметр dgst принимает -hexпечать текстового представления с некоторыми подробностями о форме подписи. pkeyutl принимает -hexdumpпараметр , который немного менее полезным. Оба будут принимать ключи RSA и DSA. Я понятия не имею, каков формат вывода. Две команды создают разные форматы. У меня складывается впечатление, что pkeyutl считается более современным, чем dgst .

Чтобы проверить эти подписи:

openssl dgst -verify $PUBLIC_KEY_FILE -signature signature-file some-file

а также:

openssl pkeyutl -verify -inkey $PUBLIC_KEY_FILE -sigfile signature-file -in some-file

Проблема здесь в том $PUBLIC_KEY_FILE. OpenSSL не может прочитать формат открытого ключа OpenSSH, поэтому вы не можете просто использовать id_rsa.pub. У вас есть несколько вариантов, ни один из которых не идеален.

Если у вас версия OpenSSH 5.6 или новее, вы можете сделать это:

ssh-keygen -e -f ~/.ssh/id_rsa.pub -m pem

Который запишет открытый ключ в стандартный вывод в формате PEM, который OpenSSL может прочитать.

Если у вас есть закрытый ключ, и это ключ RSA, то вы можете извлечь из него открытый ключ (я предполагаю, что файл закрытого ключа в кодировке PEM включает в себя копию открытого ключа, поскольку невозможно получить открытый ключ). от самого закрытого ключа), и используйте это:

openssl rsa -in ~/.ssh/id_rsa -pubout

Я не знаю, есть ли эквивалент DSA. Обратите внимание, что этот подход требует некоторого сотрудничества от владельца закрытого ключа, который должен будет извлечь открытый ключ и отправить его потенциальному верификатору.

Наконец, вы можете использовать программу на Python, написанную главой под названием Lars, для преобразования открытого ключа из формата OpenSSH в формат OpenSSL.

Том Андерсон
источник
1
Я просто хотел бы отметить, что «невозможно получить открытый ключ из самого закрытого ключа», это неправда. На практике (то есть во всех фактически используемых криптосистемах) открытый ключ в большинстве случаев легко получается из закрытого ключа.
Кирелагин
@kirelagin: я этого не знал. Не могли бы вы рассказать мне или связать меня с дополнительной информацией о том, как это можно сделать?
Том Андерсон
1
Я не уверен, есть ли какое-то конкретное чтение по этой теме ... Давайте просто подумаем об этом. Возьмите любую дискретную логарифмическую криптосистему (ElGamal). В этом случае закрытый ключ (размер группы, генератор, мощность) и открытый ключ (размер группы, генератор, генератор ^ мощность). Итак, войти сложно, но силы нет, вы просто рассчитываете.
Кирелагин
В случае RSA эта инверсия на самом деле трудна, но здесь ситуация немного другая. Открытый ключ (n, d) и закрытый ключ (n, d ^ (- 1) mod phi (n)). Инвертировать d также было бы сложно, если бы вы не хранили phi (n), но вот хитрость: почти все используют e = 65537 (когда вы генерируете ключ, есть возможность изменить это значение по умолчанию, но я никогда не видел любой, кто использует его, потому что это не имеет никакого практического смысла), поэтому получение открытого ключа из частного тривиально.
Кирелагин
С эллиптическими кривыми это фактически так же, как с дискретным бревном и мощностью, инвертировать легко. Тем не менее, я не уверен насчет других криптосистем, но эти три - те, которые используются на практике.
Кирелагин
10

@ Ответ Тома помог мне начать, но не сработал.

Эти команды будут работать с:

  • OpenSSL 1.0.1 14 марта 2012 г.
  • OpenSSH_5.9p1

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

# openssl pkeyutl -sign -inkey ~/.ssh/id_sample -in $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl pkeyutl -verify -pubin -inkey pub -in $1 -sigfile $1.sig
Signature Verified Successfully

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

# openssl dgst -sign ~/.ssh/id_sample $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl dgst -verify pub -signature $1.sig $1
Verified OK

Версия pkeyutl может подписывать только файлы небольшого размера. В то время как dgst может подписывать произвольно большие файлы, потому что перед подписанием результата требуется дайджест.

stephen.z
источник
Для меня также ответ Stephen.z работал из коробки. Сначала я некоторое время продолжал играть с ответом Тома и, наконец, нашел ответ Stephen.z, который отлично сработал для меня. Спасибо Стивен.з!
Гжегож Вежовецкий
PS Здесь я поделился моими фрагментами: gist.github.com/gwpl/2c7636f0b200cbfbe82cc9d4f6338585
Grzegorz Wierzowiecki
Вы пытались использовать pkeyutl, чтобы подписать только хэш файла?
Гайя
-3

Чтобы проверить эти подписи - более простое решение:

Более простой способ убедиться, что подписанный документ одинаков, - заново сгенерировать файл цифровой подписи и затем использовать diff, чтобы проверить, совпадают ли два файла подписи.

Эрхард Ле Гранж
источник
3
Вы думаете о хэшах , а не о подписи . Аналогично, но не то же самое: хеш только проверяет, что файл не изменился; подпись также подтверждает, откуда она пришла.
Писквор