Аппаратный ключ SSH в Windows с использованием TPM

Оказывается у Microsoft есть удивительно простой способ создания и использования аппаратного SSH-ключа.

Виртуальная смарт-карта

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

Большинство относительно-новых компьютеров имеют на материнке TPM 2.0 (модуль доверенной платформы), который можно использовать для реализации виртуальной смарт-карты. Проверить наличие и версию можно командой Get-Tpm в PowerShell или через tpm.msc — виртуальные смарт-карты требуют именно версию 2.0. Обычно это микросхема, распаянная на плате, но бывают варианты в виде внешнего модуля, вставляемого в разъём на материнке. Это больше для параноидальных случаев, когда надо надолго оставить ПК на стороне и не хочется заморачиваться с чисткой приватных штук. А если на такую карту завязать bitlocker на системном разделе.. в общем есть куда размахнуться.

Виртуальная смарт-карта записывается в TPM (шифруется с его помощью?) и шифрует/подписывает данные только в ответ на ввод ключа, который в современных Windows 10+ представлен в виде системного интерфейса ввода пин-кода. Вроде как это безопасно. ВНЕЗАПНО, как для Microsoft, оказывается, что для создания виртуального считывателя смарт-карт и соответствующей карты достаточно одной команды.

tpmvscmgr.exe create /name MyCard /pin PROMPT /adminkey RANDOM /generate /attestation AIK_AND_CERT

Вводим 8-значный пин-код, мы молодцы! /name может быть любой. Пунктом /attestation AIK_AND_CERT в принципе можно пренебречь если нет интернета, иначе всё крашнется. Но с ним секурнее.

Перед созданием карты стоит сразу запомнить, как найти её <instance ID> — он понадобится для удаления. Список виртуальных смарт-карт выводится командой:
wmic path win32_PnPEntity where "DeviceID like '%smartcardreader%'" get DeviceID,Name,Status.
В большинстве случаев, если речь идёт о первой созданной виртуальной смарт-карте, её инстанс-ИД равен ROOT\SMARTCARDREADER\0000. Удаляется при помощи команды:
tpmvscmgr.exe destroy /instance <instance ID>

Для расширения кругозора, полный мануал по tpmvscmgr.

Самоподписанный сертификат

Теперь у нас есть виртуальная смарт-карта, но она пустая.

Обычно для windows требуется целая куча серверов active directory, настроенные политики самозачисления сертификатов, запросы сертификатов. Однако нас вполне устраивает “самоподписанный” сертификат. Нам нужен только открытый ключ.

New-SelfSignedCertificate -Subject "CN=Ivor Barhansky" -KeyAlgorithm RSA -KeyLength 4096 -Provider "Microsoft Smart Card Key Storage Provider"

Только нужно подставить своё имя в поле CN=.

Putty-CAC и Pageant

Карта и сертификат есть, теперь бы сами ключики. Тут пригодится программа Pageant из комплекса Putty. Но тут мы сталкиваемся с дополнительным ПО, нетривиальным импортом ключей и прочими прелестями. К счастью, энтузиасты пилят свою версию Putty с маджонгом и гейшами — Putty-CAC, которая умеет из коробки работать с API Windows. Опять же, редакция для кровавого энтерпрайза с их смарт-картами, но приложения отлично прожёвывают и виртуальные карты. Ещё и в автоматическом режиме.

Фактически из всей мешанины необходим только Pageant, который устанавливается как системный сервис. После установки запускаем, выбираем “Add CAPI Cert”, выбираем свой сертификат и вводим пин. Ключ в системе. Чтобы получить текст публичного ключа в формате base64, надо выбрать “Copy to Clipboard” — это и есть то, что нужно добавить в ~/.ssh/authorized_keys на целевом сервере.

Ключ намертво привязан к TPM конкретной машины и не экспортируется — это и есть суть всей затеи. Обратная сторона: при переустановке Windows карта и ключ умрут вместе со старой системой. Заранее стоит держать под рукой список серверов, где прописан публичный ключ, чтобы после пересоздания карты обновить authorized_keys на каждом из них.

Шашечки

Переадресация агента SSH

Обычно редактирование git-репозиториев происходит в сеансах SSH. Общение с сервером git (например, github) может осуществляться с помощью HTTPS или SSH. Если URL git-репозитория является SSH-соединением (не начинается с HTTPS), то операции push будут выполняться в отдельной SSH-сессии.

Переадресация агента необходима в тех случаях, если мы ходим от сервера к серверу по цепочке.

ПК → Удаленный хост один → Удаленный хост два

Фактически она работает по принципу, когда на удалённый хост пробрасываются ключи с локального ПК (всё несколько сложнее, не суть). Это простая и полезная, но весьма неочевидная опция, которую можно включить либо в Putty либо в .ssh/config прописав там

Host *
    ForwardAgent yes

Интеграция с Windows

В новых версиях Windows нормальное OpenSSH вшито во все три терминала и расширение для VS Code VS Code SSH Remote Development Extension, что позволяет работать со всем этим раз в день вводя протухающий пин-код.

!! Да, даже если ПК 24\7 онлайн, где-то раз в день пин-код протухает, а окно его повторного ввода может появиться под активными окнами, а не поверх. Можно не заметить и хорошо наклацав завесить себе систему. PhpStorm можно просто в говнище уложить, когда он куда-то стучится, ты не видишь результат, обновляешь, он уже в несколько потоков стучится, ты не видишь, нервничаешь, а где-то под всеми окнами “Введите пин-код!”.

Аналогично существует клиент OpenSSH под WSL. Подробнее, WSL SSH Pageant.


Дополнительно на почитать: