Подпись (в частности — подпись кода) представляет собой процесс использования шифрования для добавления цифровой подписи к данным. Получатель данных может проверить достоверность подписи и убедиться, что послание пришло именно от указанного отправителя.
GNU Privacy Guard (GnuPG или GPG) позволяет создавать асимметричные пары ключей, которые можно использовать для шифрования и подписи данных. Каждая пара состоит из открытого и закрытого ключа.
Открытым ключом можно поделиться с кем угодно. Вы можете загрузить его в свои учетные записи GitHub и GitLab или разместить в Интернете, чтобы любой мог получить к нему доступ. Закрытый ключ, он же секретный, известен только владельцу. При помощи закрытого ключа происходит создание подписи, а при помощи открытого ключа кто угодно может проверить электронную подпись.
Подготовка
Чтобы работать с ключами нам надо установить gnupg
и pinentry-mac
.
brew install gnupg pinentry-mac
И настроить конфиг для GPG агента
$ cat > .gnupg/gpg-agent.conf <<EOF
use-standard-socket
enable-ssh-support
default-cache-ttl 14400
max-cache-ttl 86400
pinentry-program /opt/homebrew/bin/pinentry-mac
EOF
Чтобы новые настройки применились надо перезапустить агента, а точнее убить старого, а новый запустится автоматом.
gpgconf --kill gpg-agent
Генерация ключей
Переходим к ключам. Для начала нам надо сгенерировать пару.
$ gpg --full-generate-key
gpg (GnuPG) 2.3.4; 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.
Please select what kind of key you want:
(1) RSA and RSA
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(9) ECC (sign and encrypt) *default*
(10) ECC (sign only)
(14) Existing key from card
Your selection? 9
Please select which elliptic curve you want:
(1) Curve 25519 *default*
(4) NIST P-384
(6) Brainpool P-256
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: Michael Bruskov
Email address: mixanemca@yandex.ru
Comment: Example GPG key pair
You selected this USER-ID:
"Michael Bruskov (Example GPG key pair) <mixanemca@yandex.ru>"
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.
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: revocation certificate stored as '/Users/mbr/.gnupg/openpgp-revocs.d/2800BA0967A8161D7D177DEEB5AE319DE4956950.rev'
public and secret key created and signed.
pub ed25519 2022-04-21 [SC]
2800BA0967A8161D7D177DEEB5AE319DE4956950
uid Michael Bruskov (Example GPG key pair) <mixanemca@yandex.ru>
sub cv25519 2022-04-21 [E]
После подтверждения запустится pinentry-mac
и попросит ввести парольную фразу.
Можно установить любое значение или оставить поле пустым.
Конечно, в идеале нужно придумать хороший, сильный пароль. Воспользуйтесь для этого своим менеджером паролей.
Список имеющихся GPG-ключей можно получить с помощью команды:
$ gpg --list-keys
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u
/Users/mbr/.gnupg/pubring.kbx
-----------------------------
pub ed25519 2022-04-21 [SC]
2800BA0967A8161D7D177DEEB5AE319DE4956950
uid [ultimate] Michael Bruskov (Example GPG key pair) <mixanemca@yandex.ru>
sub cv25519 2022-04-21 [E]
Включаем подпись коммитов и тегов
Отлично, ключи у нас есть, настрало время добавить из в Git.
Я подписываю все теги и коммиты, так что добавляю настройки в глобальный .gitconfig
, но можно включать и на уровне отдельного репозитория.
git config --global commit.gpgsign true
git config --global tag.gpgSign true
git config --global log.showSignature true
Осталось только указать, каким ключом подписывать.
git config --global user.signingkey 2800BA0967A8161D7D177DEEB5AE319DE4956950
Экспорт публичного ключа
Для того, чтобы загрузить наш открытый ключ на GitHub или GitLab его нужно экспортировать
$ gpg --export --armor 2800BA0967A8161D7D177DEEB5AE319DE4956950
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEYmHOHBYJKwYBBAHaRw8BAQdARKqQPRA3ZtJWDM1hkRsOhFBfpogvLRDLw1DR
9KGFevi0PE1pY2hhZWwgQnJ1c2tvdiAoRXhhbXBsZSBHUEcga2V5IHBhaXIpIDxt
aXhhbmVtY2FAeWFuZGV4LnJ1PoiUBBMWCgA8FiEEKAC6CWeoFh19F33uta4xneSV
aVAFAmJhzhwCGwMFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJELWuMZ3k
lWlQVmYBAI1xT4W2YNh1WaGEFxsi9bua/+tuWP55p9BVH3zyRSXQAPwLrAWDdA8E
c+QhEm6wNu02bl3SN2G4CRhz7zzwSVogCLg4BGJhzhwSCisGAQQBl1UBBQEBB0AS
T4n0mcCK8zH0VwMXo2klodF/5oNjTUtkPAczaR38XgMBCAeIdwQYFgoAIBYhBCgA
uglnqBYdfRd97rWuMZ3klWlQBQJiYc4cAhsMAAoJELWuMZ3klWlQp4gA93nQBnbk
oBsQvuVgd5FzM0EO2h6doDbdfcm3EWfo9T4A/iU5qTyDOiGlZYoLDeYX4GGuDe/E
KcWd5U3mx0CTTkwL
=/Nc3
-----END PGP PUBLIC KEY BLOCK-----
Как сделать резервную копию
Закрытый ключ можно экспортировать почти так же, как мы экспортировали открытый
gpg --export-secret-keys --armor 2800BA0967A8161D7D177DEEB5AE319DE4956950 > gpg-key.asc
Если к ключу задана парольная фраза, то опять запустится pinentry-mac
и попросит ее ввести.