Использование GPG для подписи коммитов в Git
Заметка по командам и настройке GPG для подписи в Git.
GPG
В GPG есть публичные и приватные ключи. Подписываем приватным, проверяем подпись публичным. Всё как обычно.
Также есть мастер-ключ (master-key) и дочерние (sub-key). У ключей есть набор предназначений (capabilities). В общем, похоже на PKI.
Так вот мастер ключ имеет предназначения подписи (S signing) и удостоверения других ключей (C certifying), аналог удостоверяющего центра (certificate authority). Поэтому использовать его нужно только для выпуска дочерних ключей, а хранить подальше от рабочей станции, идеально в оффлайн хранилище.
Генерация мастер-ключа
Используем команду gpg --full-generate-key, для установки расширенных опций используем флаг --expert:
$ gpg --full-generate-key --expert
gpg (GnuPG) 2.2.29-unknown; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Выбираем только подпись и, например, ECC:
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC and ECC
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
(14) Existing key from card
Your selection? 10
Выбираем тип кривой, например, Curve 25519:
Please select which elliptic curve you want:
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Your selection? 1
Выбираем срок действия:
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Указываем идентификатор (имя, почта):
GnuPG needs to construct a user ID to identify your key.
Real name: qwerty
Email address: qwerty@example.com
Comment:
You selected this USER-ID:
"qwerty <qwerty@example.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
Двигаем мышкой и задаём пароль:
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
Готово:
gpg: key 1F3D4A3F59B015FC marked as ultimately trusted
gpg: revocation certificate stored as
'~.gnupg/openpgp-revocs.d/B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC.rev'
public and secret key created and signed.
pub ed25519 2023-04-21 [SC]
B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
uid qwerty <qwerty@example.com>
Генерация рабочего ключа для подписи
Для генерации дочернего ключа нужно отредактировать мастер-ключ:
$ gpg --expert --edit-key B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
gpg (GnuPG) 2.2.29-unknown; Copyright (C) 2021 Free Software Foundation, Inc.
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.
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u
sec ed25519/1F3D4A3F59B015FC
created: 2023-04-21 expires: never usage: SC
trust: ultimate validity: ultimate
[ultimate] (1). qwerty <qwerty@example.com>
Добавляем дочерний ключ:
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
(14) Existing key from card
Your selection? 10
Please select which elliptic curve you want:
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Your selection? 1
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Sat Apr 27 18:12:39 2024 BST
Is this correct? (y/N) y
Готово:
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
sec ed25519/1F3D4A3F59B015FC
created: 2023-04-21 expires: never usage: SC
trust: ultimate validity: ultimate
ssb ed25519/53FE09215FE59025
created: 2023-04-21 expires: 2024-04-20 usage: S
[ultimate] (1). qwerty <qwerty@example.com>
Сохраняем:
gpg> save
Просмотр ключей
Просмотр списка публичных ключей:
$ gpg -k
---------------------------------
pub ed25519 2023-04-21 [SC]
B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
uid [ultimate] qwerty <qwerty@example.com>
sub ed25519 2023-04-21 [S] [expires: 2024-04-20]
Или:
$ gpg --list-keys --keyid-format long --list-options show-unusable-subkeys --with-subkey-fingerprints
---------------------------------
pub ed25519/1F3D4A3F59B015FC 2023-04-21 [SC]
B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
uid [ultimate] qwerty <qwerty@example.com>
sub ed25519/53FE09215FE59025 2023-04-21 [S] [expires: 2024-04-20]
Просмотр списка приватных ключей:
$ gpg -K
---------------------------------
sec ed25519 2023-04-21 [SC]
B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
uid [ultimate] qwerty <qwerty@example.com>
ssb ed25519 2023-04-21 [S] [expires: 2024-04-20]
Или:
$ gpg --list-secret-keys --keyid-format long --list-options show-unusable-subkeys --with-subkey-fingerprints
---------------------------------
sec ed25519/1F3D4A3F59B015FC 2023-04-21 [SC]
B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
uid [ultimate] qwerty <qwerty@example.com>
ssb ed25519/53FE09215FE59025 2023-04-21 [S] [expires: 2024-04-20]
Экспорт
Публичные ключи экспортируются связкой — мастер вместе со всеми дочерними:
$ gpg --output qwerty@example.com.pub.gpg --export B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
Приватные ключи по умолчанию тоже экспортируются связкой + публичные:
$ gpg --output qwerty@example.com.gpg --export-secret-keys B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
Но можно эеспортировать только конкретный дочерний приватный + публичные:
$ gpg --output qwerty@example.com.sign1.gpg --export-secret-subkey 53FE09215FE59025!
Для резервной копии добавляем опцию --export-options backup.
Импорт
Для импорта единая команда:
$ gpg --import qwerty@example.com.gpg
Для резервной копии добавляем опцию --import-options restore.
Удаление
Перед удалением публичного ключа нужно удалить приватный:
$ gpg --delete-secret-key 1F3D4A3F59B015FC
sec ed25519/1F3D4A3F59B015FC 2023-04-21 qwerty <qwerty@example.com>
Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
Если удалять мастер-ключ, то потребует подтверждения удаления и дочерних. Удалять дочерний отказался:
gpg: deleting secret subkey failed: Not confirmed
gpg: 1F3D4A3F59B015FC: delete key failed: Not confirmed
При этом мастер удалился (# указывает на это):
$ gpg --list-secret-keys --keyid-format long
---------------------------------
sec# ed25519/1F3D4A3F59B015FC 2023-04-21 [SC]
B6FAB23B1A4F62B5F279AFF21F3D4A3F59B015FC
uid [ultimate] qwerty <qwerty@example.com>
ssb ed25519/53FE09215FE59025 2023-04-21 [S] [expires: 2024-04-20]
Удаление публичного ключа производится командой:
$ gpg --delete-key 1F3D4A3F59B015FC
Смена пароля
$ gpg --edit-key qwerty@example.com
gpg> passwd
gpg> save
GPG Agent
Запуск агента:
$ gpgconf --launch gpg-agent
Настройка таймаутов:
$ echo 'max-cache-ttl 86400' > ~/.gnupg/gpg-agent.conf
$ echo 'default-cache-ttl 14400' > ~/.gnupg/gpg-agent.conf
Полезности
Восстановление доверия после импорта:
$ gpg --edit-key qwerty@example.com
gpg> trust
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
gpg> save
Распаковка ключа:
$ gpgsplit qwerty@example.com.gpg
Git
Включение автоматической подписи в Git:
$ git config user.signingkey 53FE09215FE59025!
$ git config commit.gpgsign true
Список использованных материалов
- Signing Git commits with GPG keys that use modern encryption
- How to create a GPG master key and subkeys
- Telling Git about your signing key
- Backup and Restore a GPG Key
- Is it possible to export a GPG subkey’s public component?
- Short OpenPGP key IDs are insecure, how to configure GnuPG to use long key IDs instead?
- Are exported private keys in GPG still encrypted?
- gpg —list-keys command outputs uid [ unknown ] after importing private key onto a clean install
- GPG Option Summary
- How do I install and use gpg-agent on Windows?
- GPG Agent Option Summary
- GPG Change Passphrase Secret Key Password Command
- Why is gpg –list-keys sometimes printing subkeys, sometimes not?