SHA-1 - Secure Hash Algorithm 1, выдаёт 160-битное значение, обычно записываемое как 40 hex-символов. В Git каждый объект (blob, tree, commit, tag) адресуется своим SHA-1.
Как Git считает SHA для объекта
Не от чистого содержимого, а от строки с префиксом:
<тип> <длина-в-байтах>\0<содержимое>
Для blob с содержимым hello\n (6 байт):
blob 6\0hello\n
Префикс плюс контент → SHA-1 → 40 символов.
Это значит, что blob и tree с одинаковым набором байтов будут иметь разный SHA - потому что префикс другой.
Атака SHAttered (2017)
В феврале 2017 Google CWI Amsterdam опубликовали два разных PDF с одинаковым SHA-1. Затраты - около 6500 CPU-лет и $100k на тот момент. Это было первое практическое доказательство коллизии.
С точки зрения криптографии SHA-1 после этого считается сломанным для подписей и identity. Но для Git это менее критично, чем кажется:
- SHA-1 используется как адрес, не как подпись.
- Префикс
<тип> <длина>\0усложняет атаку: нужно подобрать коллизию не для произвольных байтов, а для байтов с известным префиксом и фиксированной длиной. - Git с 2017 проверяет каждый получаемый объект на признаки SHAttered-атаки и отказывается принимать заведомо коллидирующие.
Тем не менее с 2018 идёт миграция на SHA-256.
SHA-256 в Git
С Git 2.29 (2020) репозиторий можно создать с другим хэшем:
git init --object-format=sha256
SHA-256 даёт 64-символьные хэши вместо 40. Совместимости с SHA-1-репозиториями нет - можно либо тот, либо другой. Большинство публичных хостингов (GitHub, GitLab) до сих пор не поддерживают SHA-256, поэтому де-факто все live-проекты на SHA-1.
Короткие SHA
В команды Git можно передавать не весь хэш, а первые 4+ символов:
git show 8d0e41 # вместо 8d0e41234f24...
Если в репозитории несколько объектов с таким префиксом - Git
ругнётся «ambiguous». Тогда нужно больше символов. По умолчанию
Git выбирает длину префикса так, чтобы не было неоднозначности
(минимум 7 символов в --abbrev).
Подводные камни
- SHA-1 даёт ложное чувство аутентичности. Если хочешь
криптографических гарантий - подписывай коммиты GPG/SSH (
git commit -S). Сам по себе SHA от подделки не защищает.- SHA-1 в Git - не HMAC и не учитывает секрет. Любой может посчитать SHA любого содержимого.
- При написании скриптов не парси короткие SHA. Используй
git rev-parse --abbrev-commit <ref>или полную форму.