open atlas
↑ К треку
Git: от нуля до сеньора GIT · 09 · 04

Подпись коммитов и доверие

Любой может поставить любые имя и email автора, поэтому это поле ничего не доказывает. Подпись коммита/тега ключом GPG или SSH доказывает, кто его сделал. git commit -S и git log --show-signature проверяют авторство; хостинг показывает Verified после регистрации ключа.

GIT Senior ◷ 16 min
Уровень
ОсновыJuniorMiddleSenior

Автор на коммите — это просто две строки, которые ты задаёшь сам. Выполни git config user.name "Linus Torvalds" и подгони user.email, закоммить — и история теперь читается так, будто твой код написал Линус. Git ничего не делает, чтобы тебя остановить, — поле автора это ярлык, а не доказательство. В публичном проекте любой может подделать коммит, который выглядит исходящим от доверенного мейнтейнера, а ревьюер, бегло глядя в git log, ничего не заметит.

К концу этого урока ты сможешь криптографически подписывать свои коммиты и теги так, чтобы их авторство было проверяемым, настраивать автоматическую подпись и объяснять, почему значок «Verified» — это разница между заявленным автором и доказанным.

Цель

После этого урока ты сможешь подписывать коммиты и теги ключом GPG или SSH, настроить Git на автоматическую подпись, проверять подписи локально через git log --show-signature и объяснять, что значок Verified на хостинге гарантирует, а что нет.

1

Поля автора и коммиттера не аутентифицированы — подпись это единственное настоящее доказательство того, кто сделал коммит. Когда ты коммитишь, Git записывает Author: Имя <email> из твоей локальной конфигурации, без какой-либо проверки, что имя или email твои. Это сделано намеренно — Git распределён и не доверяет никакому центральному провайдеру личности. Решение — криптографическая подпись: ты подписываешь коммит приватным ключом, который есть только у тебя, и любой с твоим соответствующим публичным ключом может проверить, что коммит сделан этим ключом и не был изменён. Личность перестаёт быть заявлением и становится доказательством.

2

Подписывать можно ключом GPG или, проще, SSH-ключом, который у тебя уже есть. Git поддерживает оба формата. Подпись через SSH новее и проще, потому что у большинства разработчиков уже есть SSH-ключ для push. Настрой это один раз:

# Использовать подпись SSH-ключом и указать Git на твой публичный ключ
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub

Для GPG вместо этого верни gpg.format к значению по умолчанию, а user.signingkey укажи на ID твоего GPG-ключа. В любом случае user.signingkey говорит Git, каким ключом подписывать; соответствующий публичный ключ — это то, чем другие (и хостинг) проверяют.

3

Подписывай отдельные коммиты и теги через -S / -s или включи подпись для всего. Явные флаги подписывают по одному объекту за раз:

git commit -S -m "Add rate limiter"   # подписать этот коммит
git tag -s v2.1.0 -m "Release 2.1.0"  # подписать аннотированный тег

Набирать -S каждый раз легко забыть, поэтому настрой автоматическую подпись:

git config --global commit.gpgsign true   # подписывать каждый коммит
git config --global tag.gpgsign true      # подписывать каждый тег

Подписанные теги особенно важны для релизов: подписанный тег v2.1.0 доказывает, что ровно тот коммит, который ты благословил как релиз, исходит от тебя, — а это якорь надёжной цепочки поставки.

4

Проверяй подписи локально, а хостинг пусть показывает значок Verified всем остальным. На своей машине ты можешь проверить любой коммит или тег:

git log --show-signature        # показать статус подписи по коммитам
git verify-commit <sha>         # проверить подпись одного коммита
git verify-tag v2.1.0           # проверить подпись тега

Для коллег, которые не запускают эти команды, GitHub и GitLab делают проверку на стороне сервера: как только ты загрузишь свой публичный ключ подписи в аккаунт, хостинг помечает твои подписанные коммиты зелёным значком Verified и сигнализирует обо всём, подписанном неизвестным или несовпадающим ключом. Значок — это видимая команде, с одного взгляда понятная версия verify-commit.

Почему это работает

Почему это важно за пределами тщеславия? Две реальные угрозы. Первая — имперсонация: в open-source проекте злонамеренный контрибьютор может смастерить коммит, выглядящий написанным ключевым мейнтейнером, протаскивая бэкдор мимо ревьюеров, доверяющих этому имени. Обязательная подпись означает, что неподписанный или неверно подписанный коммит отклоняется, так что поддельный автор не может выдать себя за доверенного. Вторая — доверие к цепочке поставки: потребители твоего релиза хотят доказательства, что помеченный артефакт действительно пришёл от твоей команды и не был подменён на каком-то переходе. Подписанный тег — это доказательство. Подпись превращает «в логе сказано, что это написала Алиса» в «ключ Алисы это подписал», а именно на это опираются аудиты, защищённые ветки и воспроизводимые релизы.

Разбор примера

Имперсонированный коммит, пойманный подписью.

Популярная библиотека требует подписанных коммитов в main через правило ветки. Атакующий открывает pull request и, чтобы выглядеть доверенным, ставит user.name и user.email ровно совпадающими с известным мейнтейнером. В наивном проекте это могло бы проскочить — git log показал бы имя мейнтейнера на коммите, добавляющем тонкую подмену зависимости.

Но правило ветки требует валидную подпись. Атакующий не может её создать: для подписи нужен приватный ключ мейнтейнера, которого у него нет. Его коммит появляется неподписанным (или подписанным его собственным неизвестным ключом), поэтому хостинг показывает его как Unverified, правило обязательной подписи блокирует merge, а ревьюеры сразу видят несоответствие между заявленным автором и отсутствующей/чужой подписью. Тем временем у настоящего мейнтейнера установлено commit.gpgsign true, так что каждый легитимный коммит по умолчанию несёт зелёный значок Verified — контраст делает подделку очевидной. Поле автора солгало; подпись не смогла. Личность устояла, потому что была доказана, а не заявлена.

Частая ошибка

Частая ошибка: ты ставишь commit.gpgsign true, но так и не зарегистрировал публичный ключ на GitHub/GitLab, поэтому твои коммиты по-настоящему подписаны, но показываются всем как Unverified — хостинг не может сопоставить подпись с известным ключом. Подписать локально и зарегистрировать ключ — два отдельных шага; сделай оба. Зеркальная ловушка — значок «Verified», который значит меньше, чем думают люди: он лишь доказывает, что коммит подписан ключом, который у хостинга есть на учёте для какого-то аккаунта, — он не ручается за качество кода или безопасность изменения. Verified означает подлинное происхождение, а не хороший код.

Проверь себя
Викторина

Почему подпись коммита — значимо более сильное доказательство авторства, чем имя и email автора в коммите?

Итог

Имя и email автора коммита — это не аутентифицированный текст, который любой может задать, поэтому они ничего не доказывают; единственное настоящее свидетельство авторства — криптографическая подпись. Подписывай ключом GPG или, проще, SSH (gpg.format ssh, user.signingkey), по одному объекту через git commit -S / git tag -s или автоматически через commit.gpgsign true. Проверяй локально через git log --show-signature и git verify-commit; как только ты зарегистрируешь публичный ключ, GitHub и GitLab показывают значок Verified, чтобы вся команда видела доказанное авторство с одного взгляда. Подпись защищает от имперсонации и лежит в основе доверия к цепочке поставки, особенно через подписанные теги релизов, — но помни, что значок доказывает происхождение, а не качество кода. Дальше ты соберёшь спокойный набор для аварийного восстановления на случай, когда у репо очень плохой день.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.