PKCS#11 в контексте OpenSSH — это способ использовать ключевой материал, который физически хранится на токене/смарткарте (например, YubiKey в режиме PIV или обычная smartcard), не выгружая приватный ключ на диск сервера или рабочей машины. Для админов и DevOps это один из самых практичных компромиссов между удобством SSH и стойкостью к компрометации рабочей станции.
Ниже — рабочая схема без «магии»: что именно делает OpenSSH, как выбрать PKCS#11 provider, как завести ssh-agent, добавить ключи через ssh-add -s, выгрузить публичный ключ на сервер и что проверять, если «не видит токен».
Что такое PKCS#11 в OpenSSH и чем отличается от обычных ключей
Обычная пара ключей SSH выглядит так: приватный ключ лежит у вас в ~/.ssh/ (часто под паролем), а публичный — на сервере в ~/.ssh/authorized_keys. При входе по SSH клиент доказывает владение приватным ключом.
В схеме со смарткартой приватный ключ создаётся и остаётся внутри токена. Подписывающие операции выполняются «внутри железки», а OpenSSH общается с устройством через библиотеку PKCS#11 (её обычно и называют «провайдером»).
- приватный ключ нельзя просто скопировать с диска — его там нет;
- для использования требуется физический токен и (обычно) PIN;
- компрометация файлов на ноутбуке уже не означает автоматическую кражу приватного ключа.
PKCS#11 — это интерфейс к криптопровайдерам и токенам: доступ и операции подписи идут через слой PKCS#11, а не через файл приватного ключа на диске.
Где в OpenSSH используется PKCS#11
PKCS#11 почти всегда нужен на клиенте. Сервер в большинстве случаев вообще «не знает», что ключ на токене: он просто видит обычную аутентификацию публичным ключом.
sshиспользует ключи, доступные черезssh-agent(в том числе добавленные из PKCS#11).ssh-agentхранит ссылки на ключи токена и в нужный момент просит токен выполнить подпись.ssh-addдобавляет ключи из PKCS#11 в агент командойssh-add -s.
Если вы параллельно усиливаете криптографию на инфраструктуре (KEX/шифры/MAC), пригодится отдельный разбор: безопасные шифры, MAC и KEX для OpenSSH.
Предварительные требования: PC/SC, OpenSC и базовая диагностика
Если PKCS#11 «не работает», начинать нужно не с SSH, а с того, видит ли систему PC/SC стек. Минимум на Linux обычно такой:
- OpenSSH-клиент;
- PC/SC стек: демон
pcscdи утилитыpcsc_scan; - PKCS#11 провайдер: чаще всего это OpenSC (
opensc-pkcs11.so), иногда — библиотека от вендора.
Debian/Ubuntu: установка и проверка
sudo apt update
sudo apt install -y openssh-client pcscd pcsc-tools opensc
sudo systemctl enable --now pcscd
pcsc_scan
Если pcsc_scan не показывает вставленную карту/токен — сначала решайте это (ридер, доступ к USB, политика udev, контейнер/VM), иначе через PKCS#11 OpenSSH тоже ничего не увидит.
RHEL/Alma/Rocky: установка и проверка
sudo dnf install -y openssh-clients pcsc-lite pcsc-lite-libs pcsc-lite-ccid pcsc-tools opensc
sudo systemctl enable --now pcscd
pcsc_scan

Выбор PKCS#11 provider: как найти нужную библиотеку
OpenSSH не «подключается к YubiKey» напрямую. Он загружает динамическую библиотеку PKCS#11 (провайдер) и вызывает её функции. Поэтому главный практический шаг — найти путь к .so на вашей системе.
Самый частый вариант — OpenSC. Провайдер обычно называется opensc-pkcs11.so.
ls -1 /usr/lib*/opensc-pkcs11.so 2>/dev/null
ls -1 /usr/lib*/pkcs11/*.so 2>/dev/null
ldconfig -p | grep -E 'opensc|pkcs11|ykcs11' || true
Типичные пути (зависят от дистрибутива и архитектуры):
/usr/lib/x86_64-linux-gnu/opensc-pkcs11.so/usr/lib64/opensc-pkcs11.so
Если в системе несколько PKCS#11 библиотек, начинайте с OpenSC: это самый предсказуемый вариант для PIV/смарткарт. Экзотические провайдеры подключайте только если понимаете, что именно они дают в вашем сценарии.
Как получить публичный ключ с токена (для authorized_keys)
Серверу нужен публичный ключ в формате OpenSSH. Быстрый способ получить его напрямую с токена — ssh-keygen -D с указанием провайдера:
ssh-keygen -D /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
Команда выведет одну или несколько строк публичных ключей (если на токене несколько слотов/сертификатов). Дальше нужную строку добавляете на сервер в ~/.ssh/authorized_keys соответствующего пользователя.
Быстро добавить ключ на сервер через ssh-copy-id
Если у вас уже есть доступ на сервер (по паролю или старому ключу), можно обойтись без ручного редактирования:
ssh-keygen -D /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so | head -n 1 > /tmp/token.pub
ssh-copy-id -i /tmp/token.pub user@server
Если публичных ключей несколько — выберите нужную строку (не обязательно head -n 1).
Рекомендуемая схема: ssh-agent + ssh-add -s (PKCS#11)
Для повседневной работы удобнее всего держать ключ токена в ssh-agent. Тогда любые ssh, git, rsync и прочие клиенты, умеющие работать с агентом, будут использовать токен без ручного указания провайдера каждый раз.
Запуск агента (если он ещё не запущен)
eval "$(ssh-agent -s)"
Добавление ключей токена: ssh-add -s
ssh-add -s /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
Если токен требует PIN, будет запрос. Проверить, что ключи добавились:
ssh-add -L
ssh-add -l
Проверка входа на сервер
ssh -v user@server
В выводе -v смотрите, что клиент «предлагает» ожидаемый ключ и получает успешную аутентификацию.
YubiKey: PIV vs OpenPGP vs FIDO2 (и где тут PKCS#11)
С YubiKey чаще всего путают три независимых стека:
- PIV — режим смарткарты, хорошо ложится на PKCS#11/OpenSC и сценарий «SSH-ключ на токене».
- OpenPGP — обычно работает через
gpg-agent(это уже не PKCS#11-путь OpenSSH, хотя рядом по смыслу). - FIDO2/U2F — ключи OpenSSH вида
sk-ssh-ed25519@openssh.com; это отдельная технология, не PKCS#11.
В этой статье — именно PKCS#11 (на практике чаще PIV). Если у вас FIDO2-ключи OpenSSH, набор команд и провайдеров будет другой.
Типичные ошибки и быстрая диагностика
Удобно классифицировать проблемы так: (1) система не видит токен, (2) провайдер не грузится, (3) ключей «как бы нет», (4) сервер отвергает публичный ключ.
1) Токен не виден: pcsc_scan пустой
- убедитесь, что
pcscdзапущен; - проверьте доступ к USB (особенно в контейнерах и на hardened-десктопах);
- для внешних ридеров проверьте, установлен ли CCID-драйвер.
systemctl status pcscd --no-pager
journalctl -u pcscd --no-pager -n 200
2) cannot load PKCS#11 provider / dlopen error
Почти всегда это неверный путь к библиотеке или отсутствующие зависимости.
file /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
ldd /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
Если ldd показывает not found — доустановите пакеты зависимостей или используйте корректный провайдер для вашего устройства/режима.
3) Провайдер грузится, но ключей нет
Нужно проверить, что на токене действительно есть ключи/сертификаты в ожидаемом режиме. Для OpenSC обычно достаточно pkcs11-tool:
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -L
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -O
Если объектов нет — значит, ключи не созданы/не импортированы, или YubiKey не в том режиме (например, вы ожидаете PIV, а настроен другой стек).
4) Сервер не принимает ключ: Permission denied (publickey)
Часто PKCS#11 тут ни при чём. Проверьте на сервере:
- правильный пользователь и его
~/.ssh; - права: каталог
~/.sshобычно700, файлauthorized_keys—600; - в
sshd_configвключеноPubkeyAuthentication; - нет ограничений в блоках
Match.
ssh -vvv user@server
На сервере смотрите логи SSHD (путь зависит от дистрибутива) — там обычно прямо написано, почему ключ отклонён.

Практика эксплуатации: PIN, кэширование и «план Б»
- PIN-политика. Если PIN спрашивается слишком часто, проверьте, не стартует ли у вас новый
ssh-agentна каждый терминал. Обычно лучше один агент на сессию пользователя. - Слишком много ключей в агенте. Если сервер ограничивает число попыток, используйте
IdentitiesOnly yesи держите в агенте только то, что реально нужно. - Аварийный доступ. Токен можно потерять, а PIN можно заблокировать. Для критичных узлов держите понятную процедуру восстановления доступа (консоль провайдера, break-glass учётка, второй независимый метод).
Токен повышает безопасность, но усложняет восстановление доступа. Процедура «что делаем, если токен потерян» должна быть продумана заранее и проверена на практике.
Мини-чеклист: от «с нуля» до рабочего логина
Установить
pcscdи OpenSC, убедиться, чтоpcsc_scanвидит устройство.Найти путь к PKCS#11 провайдеру (обычно
opensc-pkcs11.so).Получить публичный ключ через
ssh-keygen -Dи добавить его вauthorized_keysна сервере.Запустить
ssh-agentи выполнитьssh-add -sс путём к провайдеру.Проверить
ssh -v, а при ошибках разделить проблему на «PC/SC и провайдер» и «сервер/authorized_keys/sshd».
Заключение
Связка OpenSSH + PKCS#11 — зрелый способ усилить SSH-аутентификацию за счёт смарткарты или токена: вы получаете привычный publickey login, но без копируемого приватного ключа. На практике успех почти всегда упирается в три вещи: здоровье PC/SC стека, правильный выбор провайдера и корректное добавление ключей через ssh-add -s в ssh-agent.


