GNUK на BluePill 2

Пишем OpenPGP ключ на криптографический токен.

   /|      .----.      |\
 /  |  __ |      | __  |  \
|   .Y`  `\|    |/`  `Y.   |
|  |        `--`        |  |
 \|        ,----,        |/
  |      /        \      |
  |     |          |     |
   |   / )  GNUK  ( \   |
    \/ /|          |\ \/
    | |  \        /  | |
   |  |\   ~----~   /|  |
   |  | ~-.______.-~ |  |
    |  \ ___    ____/  |
     \      ~~~~      /
       ~ - .____. - ~

Заметка: Команды выполнены на реальном оборудовании, результат может отличаться от вашего.

В работе экосистемы смарт-карт задействовано много демонов и служб. Убедитесь, что у вас установлены и запущены все из них:

                  +-----+
                  | gpg | <-+
                  +-----+   |
                            |
                  +-----+   |   +-----------+     +----------+     +-------+     +---------+     +-----+
                  | ssh | <-+-> | gpg_agent | <-> | scdaemon | <-> | pcscd | <-> | libccid | <-> | USB |
                  +-----+   |   +-----------+     +----------+     +-------+     +---------+     +-----+
                            |
+---------+     +-------+   |
| mozilla | <-> | scute | <-+
+---------+     +-------+

Начальная настройка

Gnuk не позволяет устанавливать пароли до импорта приватных ключей, поэтому произведём начальную настройку.

Переходим в интерактивный режим настройки токена GPG:

$ gpg --card-edit

Reader ...........: 234B:0000:FSIJ-2.2-4314351B:0
Application ID ...: D276000124010200FFFE4314351B0000
Application type .: OpenPGP
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 4314351B
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
KDF setting ......: off
UIF setting ......: Sign=off Decrypt=off Auth=off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

Разрешаем команды администратора:

gpg/card> admin
Admin commands are allowed

Настраиваем KDF-DO (Key Derived Function - Data Object) (функция OpenPGP, позволяющая безопасно генерировать приватные ключи с использованием ресурсов хоста):

gpg/card> kdf-setup

Бонус: Настраиваем KDF-DO на использование одного кода (adminless):

gpg/card> kdf-setup single

Здесь нужен PIN-код администратора. Стандартно установлены следующие:

User:  123456
Admin: 12345678

Опционально: Добавляем имя, логин, язык, пол, приветствие и URL публичного ключа соответственно:

gpg/card> name
Cardholder's surname: Savin
Cardholder's given name: Aleksei

gpg/card> login
Login data (account name): lessavin

gpg/card> lang
Language preferences: ru

gpg/card> sex
Salutation (M = Mr., F = Ms., or space): M

gpg/card> salutation
Salutation (M = Mr., F = Ms., or space): M

gpg/card> url
URL to retrieve public key: https://lessavin.ru/6D3554C2128F2DB5C783D74CB6C5D439AF2E62B5.asc

Опционально: Отключаем PIN-код для цифровой подписи.

gpg/card> forcesig

Выходим из интерактивного режима:

gpg/card> quit

Генерация ключей

Gnuk на данный момент (версия 2.2) поддерживает алгоритмы Ed25519 и X25519, а также экспериментально Ed448 и X448. Для генерации пары ключей изучите мою предыдущую статью про GnuPG.

Внимание: После генерации ключей на компьютере сохраните приватный ключ в надёжном месте. Для безопасности в токене отсутствует функция экспорта ключей.

Импорт ключей

Переходим в интерактивного режима GPG ключа:

$ gpg --edit-key 6D3554C2128F2DB5C783D74CB6C5D439AF2E62B5
gpg (GnuPG) 2.4.7; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  ed25519/B6C5D439AF2E62B5
    created: 2026-07-16  expires: 2029-07-16  usage: SC
    trust: ultimate      validity: ultimate
ssb  cv25519/64446374763F07DC
    created: 2026-07-16  expires: 2029-07-16  usage: E
ssb  ed25519/03B7C091952C3E12
    created: 2026-07-16  expires: 2029-07-15  usage: A
[ultimate] (1). Aleksei Savin <lessavin@hotmail.com>

Импортируем основной ключ:

gpg> keytocard
Really move the primary key? (y/N) y
Please select where to store the key:
  (1) Signature key
  (3) Authentication key
Your selection? 1

sec  ed25519/B6C5D439AF2E62B5
    created: 2026-07-16  expires: 2029-07-16  usage: SC
    trust: ultimate      validity: ultimate
ssb  cv25519/64446374763F07DC
    created: 2026-07-16  expires: 2029-07-16  usage: E
ssb  ed25519/03B7C091952C3E12
    created: 2026-07-16  expires: 2029-07-15  usage: A
[ultimate] (1). Aleksei Savin <lessavin@hotmail.com>

Note: the local copy of the secret key will only be deleted with "save".

Выделяем подключ 1:

gpg> key 1

sec  ed25519/B6C5D439AF2E62B5
    created: 2026-07-16  expires: 2029-07-16  usage: SC
    trust: ultimate      validity: ultimate
ssb* cv25519/64446374763F07DC
    created: 2026-07-16  expires: 2029-07-16  usage: E
ssb  ed25519/03B7C091952C3E12
    created: 2026-07-16  expires: 2029-07-15  usage: A
[ultimate] (1). Aleksei Savin <lessavin@hotmail.com>

Импортируем подключ 1:

gpg> keytocard
Please select where to store the key:
  (2) Encryption key
Your selection? 2

sec  ed25519/B6C5D439AF2E62B5
    created: 2026-07-16  expires: 2029-07-16  usage: SC
    trust: ultimate      validity: ultimate
ssb* cv25519/64446374763F07DC
    created: 2026-07-16  expires: 2029-07-16  usage: E
ssb  ed25519/03B7C091952C3E12
    created: 2026-07-16  expires: 2029-07-15  usage: A
[ultimate] (1). Aleksei Savin <lessavin@hotmail.com>

Note: the local copy of the secret key will only be deleted with "save".

Снимаем выделение с подключа 1:

gpg> key

sec  ed25519/B6C5D439AF2E62B5
    created: 2026-07-16  expires: 2029-07-16  usage: SC
    trust: ultimate      validity: ultimate
ssb  cv25519/64446374763F07DC
    created: 2026-07-16  expires: 2029-07-16  usage: E
ssb  ed25519/03B7C091952C3E12
    created: 2026-07-16  expires: 2029-07-15  usage: A
[ultimate] (1). Aleksei Savin <lessavin@hotmail.com>

Выделяем подключ 2:

gpg> key 2

sec  ed25519/B6C5D439AF2E62B5
    created: 2026-07-16  expires: 2029-07-16  usage: SC
    trust: ultimate      validity: ultimate
ssb  cv25519/64446374763F07DC
    created: 2026-07-16  expires: 2029-07-16  usage: E
ssb* ed25519/03B7C091952C3E12
    created: 2026-07-16  expires: 2029-07-15  usage: A
[ultimate] (1). Aleksei Savin <lessavin@hotmail.com>

Импортируем подключ 2:

gpg> keytocard
Please select where to store the key:
  (3) Authentication key
Your selection? 3

sec  ed25519/B6C5D439AF2E62B5
    created: 2026-07-16  expires: 2029-07-16  usage: SC
    trust: ultimate      validity: ultimate
ssb  cv25519/64446374763F07DC
    created: 2026-07-16  expires: 2029-07-16  usage: E
ssb* ed25519/03B7C091952C3E12
    created: 2026-07-16  expires: 2029-07-15  usage: A
[ultimate] (1). Aleksei Savin <lessavin@hotmail.com>

Note: the local copy of the secret key will only be deleted with "save".

Сохраняем результат и выходим:

gpg> save
$

Бонус: Загружаем ключи, не удаляя с компьютера (вместо последнего шага):

gpg> quit
Save changes? (y/N) n
Quit without saving? (y/N) y
$

Смена PIN-кодов

Теперь, когда ключи были перенесены на токен, можно сменить PIN-коды.

Переходим в интерактивного режима GPG токена:

$ gpg --card-edit

Reader ...........: 234B:0000:FSIJ-2.2-4314351B:0
Application ID ...: D276000124010200FFFE4314351B0000
Application type .: OpenPGP
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 4314351B
Name of cardholder: Aleksei Savin
Language prefs ...: ru
Salutation .......: Mr.
URL of public key : https://lessavin.ru/6D3554C2128F2DB5C783D74CB6C5D439AF2E62B5.asc
Login data .......: lessavin
Signature PIN ....: not forced
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
KDF setting ......: on
UIF setting ......: Sign=off Decrypt=off Auth=off
Signature key ....: 6D35 54C2 128F 2DB5 C783  D74C B6C5 D439 AF2E 62B5
      created ....: 2026-07-16 09:14:36
Encryption key....: 5E48 B653 64DF F9CD A282  62D9 6444 6374 763F 07DC
      created ....: 2026-07-16 09:14:36
Authentication key: D521 62B0 0A26 A4F6 9C75  1248 03B7 C091 952C 3E12
      created ....: 2026-07-16 09:16:06
General key info..:
pub  ed25519/B6C5D439AF2E62B5 2026-07-16 Aleksei Savin <lessavin@hotmail.com>
sec>  ed25519/B6C5D439AF2E62B5  created: 2026-07-16  expires: 2029-07-16
                                card-no: FFFE 4314351B
ssb>  cv25519/64446374763F07DC  created: 2026-07-16  expires: 2029-07-16
                                card-no: FFFE 4314351B
ssb>  ed25519/03B7C091952C3E12  created: 2026-07-16  expires: 2029-07-15
                                card-no: FFFE 4314351B

Разрешаем команды администратора:

gpg/card> admin
    Admin commands are allowed

Меняем PIN-код администратора:

gpg/card> passwd

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
PIN changed.

Меняем PIN-код пользователя:

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.

Опционально Задаем PIN-код сброса.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 4
Reset Code set.

Выходим из меню:

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? Q

Выходим из интерактивного режима:

gpg/card> quit

Поздравляю, вы успешно настроили токен. В следующей статье мы разберём способы применения токена.

P.S. Для наглядности был выбран GPG, но в качестве более удобной альтернативы рекомендую использовать Kleopatra, графический интерфейс для GnuPG.

Смотрите также