# SHA-1 в Git _Объектная модель · GitLab Knowledge Base_ **TL;DR:** 40-символьный хэш, по которому Git адресует объекты. Считается от содержимого с префиксом типа. Сломан криптографически в 2017 (SHAttered), но в Git до сих пор основной - миграция на SHA-256 идёт медленно. SHA-1 - Secure Hash Algorithm 1, выдаёт 160-битное значение, обычно записываемое как 40 hex-символов. В Git каждый объект ([blob](/courses/git/kb/blob.md), [tree](/courses/git/kb/tree.md), [commit](/courses/git/kb/commit.md), [tag](/courses/git/kb/tag.md)) адресуется своим 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) репозиторий можно создать с другим хэшем: ```bash git init --object-format=sha256 ``` SHA-256 даёт 64-символьные хэши вместо 40. Совместимости с SHA-1-репозиториями нет - можно либо тот, либо другой. Большинство публичных хостингов (GitHub, GitLab) до сих пор не поддерживают SHA-256, поэтому де-факто все live-проекты на SHA-1. ## Короткие SHA В команды Git можно передавать не весь хэш, а первые 4+ символов: ```bash 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 ` или полную форму. ## Команды ```bash git rev-parse HEAD ``` Полный 40-символьный SHA текущего коммита ```bash git rev-parse --short HEAD ``` Короткий уникальный SHA ```bash git config --global init.defaultObjectFormat sha256 ``` Дефолт для новых репозиториев - SHA-256 ## См. также - [Blob](/courses/git/kb/blob.md) - [Tree](/courses/git/kb/tree.md) - [Commit](/courses/git/kb/commit.md)