Инструменты разработчика · SHA хеш-калькулятор
Hex, Base64 и необработанные байты: три способа записи одного и того же SHA дайджеста
· Как это работает
ша-256 base64 кодирование форматы файлов
sha256sum печатает шестнадцатеричный код, package-lock.json хранит base64, а Docker использует префикс sha256:. Все они могут быть одинаковыми 32 bytes. В этом посте объясняется каждое представление и способы преобразования между ними.
Хэши, которые выглядят по-разному, но совпадают — строка файла блокировки и контрольная сумма терминала для одного и того же файла.
Дайджест SHA-256 по сути является 32 bytes. То, как вы записываете эти байты, определяет, как будет выглядеть дайджест. Один дайджест, 32 идентичных байтов, отображается как 64 шестнадцатеричных символов (два на байт) или 44 символов base64 (примерно четыре на три байта), а также в виде символов разной длины и формата в зависимости от кодировки. Путаница возникает из-за того, что файл блокировки может отображать одно представление, а терминал — другое, причем оба для одного и того же базового 32 bytes.
Понимание кодировки — это шаг, который решает вопрос: «Почему они выглядят по-другому?» на «Я могу подтвердить, что они одинаковые». Все три представления эквивалентны, если вы декодируете их обратно в байты.
Дайджест представляет собой байты — 20, 32, 48 или 64 из них в зависимости от алгоритма, до любого кодирования текста.
Прежде чем появится какое-либо текстовое представление, результатом является ArrayBuffer байтов дайджеста. ToolAcre оборачивает этот буфер Uint8Array, затем либо записывает каждый байт как две шестнадцатеричные цифры, либо преобразует каждый байт в двоичный символ перед вызовом btoa. Ни один из форматтеров не перезапускает хэш и не меняет ни одного бита дайджеста.
Ширина байта соответствует выбранному алгоритму в этом инструменте: SHA-1 возвращает двадцать байтов, SHA-256 тридцать два, SHA-384 сорок восемь и SHA-512 шестьдесят четыре. Это поддерживаемые выходные данные, проверенные метаданными и тестами алгоритма. Необработанные байты подходят для программного сравнения; hex и base64 — это транспортные обозначения для каналов, ожидающих текст.
Hex — два символа в байте, почему он доминирует над инструментами командной строки и вопрос о регистре
Шестнадцатеричное представление использует цифры 0-9 и буквы A-F (или a-f) для представления возможных значений 16 4-битного полубайта. Две шестнадцатеричные цифры представляют один байт. Дайджест SHA-256 входного abc равен 32 bytes, поэтому он отображается в виде шестнадцатеричных символов 64: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad. Это формат, который печатает большинство инструментов командной строки. Шестнадцатеричный формат удобочитаем и однозначен; каждый байт каждый раз представлен одними и теми же двумя символами.
Шестнадцатеричный формат — это формат по умолчанию для контрольных сумм и хешей в документации и в командной строке. Его легко читать и копировать, в нем нет дополнений, нет учета регистра при интерпретации (хотя соглашение требует последовательного использования нижнего или верхнего регистра), а также нет специальных символов, которые необходимо экранировать в URL-адресах или JSON. Обратной стороной является то, что он требует вдвое больше символов, чем необработанных байтов, поэтому существуют другие форматы.
Base64 и base64url — примерно четыре символа на три байта, заполнение и место появления каждого (SRI, npm, SSH отпечатки пальцев)
Base64 кодирует три байта как четыре символа, взятых из алфавита символов 64: A-Z, a-z, 0-9, +, /. Три байта 61 62 63 ( ASCII коды для abc) кодируются как YWJj в base64. Полный дайджест 32 байт SHA-256 кодируется приблизительно как 44 символов base64. Заполнение символами = приводит к тому, что длина вывода становится кратной 4, то есть 44 символов плюс дополнение 0 (поскольку 32 кратно 3, заполнение не требуется). Декодирование меняет процесс: четыре символа base64 декодируются в три байта.
Base64 появляется в файлах package-lock.json, термоусадочной упаковке npm, атрибутах SRI (целостность подресурса) в HTML и SSH отпечатках ключей. Он компактен — примерно на 33% длиннее, чем необработанные байты, по сравнению с шестнадцатеричным форматом, который на 100% длиннее. Компромисс заключается в том, что не все текстовые представления одинаково легко читаются; Base64 для человеческого глаза выглядит более зашифрованным, чем шестнадцатеричный.
Формы с префиксами — sha256: в дайджестах контейнера, sha384- в атрибутах целостности, SHA256: в SSH.
Base64url — это вариант, определенный в RFC 4648, который заменяет - и _ на + и /.. Алфавит становится A-Z, a-z, 0-9, -, _. JWT используют base64url, поскольку + и / имеют особое значение в URL-адресах (+ можно читать как пробел в строках запроса, / — это разделитель пути). Сегмент JWT всегда закодирован в формате Base64url, и декодер, который настаивает на стандарте Base64, отклонит его. И наоборот, декодер base64url, который не принимает стандартный алфавит, не будет работать со стандартным base64.
Заполнение не является обязательным в base64url. Стандартный base64 дополняется знаком =, чтобы гарантировать, что длина вывода кратна 4. Base64url обычно опускает заполнение, потому что = сам по себе URL неудобен. Декодер должен принимать base64url с заполнением или без него, а кодировщик должен четко указывать, что именно он выдает. Инструмент ToolAcre base64 принимает оба алфавита, допускает отсутствие дополнений при вводе и позволяет выбирать формат при выводе.
Рабочий пример — один дайджест, преобразованный из шестнадцатеричного формата в base64 и обратно, с отмеченными границами байтов.
Формы с префиксами добавляют в дайджест идентификатор схемы. В дайджестах образов Docker используется sha256:ba7816bf..., где sha256: — префикс. В отпечатках SSH используется SHA256: с двоеточием. Некоторые инструменты используют sha256= или SHA256= (со знаком равенства). Префикс носит чисто информационный характер; он сообщает вам, какой алгоритм создал дайджест. Удаление префикса оставляет те же байты в той же кодировке.
При сравнении дайджестов префиксом является шум. Если один инструмент печатает SHA256:ba78..., а другой печатает ba78..., это один и тот же дайджест; префикс — это просто метаданные о формате. Аналогично, такие префиксы, как sha256:- (используется в некоторых контекстах контейнеров) или sha384- (используется в атрибутах целостности), представляют собой соглашения о форматировании, которые не изменяют байты. Разденьте их для сравнения.
Чего это не касается — какую кодировку испускает данный инструмент; проверьте выходной формат перед сравнением
Один дайджест, SHA-256 входного abc, появляется в нескольких формах: шестнадцатеричный (символы 64), base64 с заполнением (символы 44), base64url с заполнением (символы 44, с - и _ вместо + и /), или с различными префиксами. Чтобы убедиться, что они одинаковы, декодируйте каждый обратно в байты и сравнивайте байты. Шестнадцатеричное представление ba7816bf... декодирует в байты 0xba 0x78 0x16 0xbf 0x8f 0x01 0xcf 0xea... Представление base64 преобразуется в ту же последовательность байтов при декодировании.
По умолчанию хеш-калькулятор ToolAcre SHA выводит данные в шестнадцатеричном формате. Если вам нужен base64, вы можете использовать отдельный инструмент для преобразования шестнадцатеричного значения в base64 или использовать утилиту base64 на том же сайте для прямого кодирования текста. Инструменты, разработанные для определенных контекстов (npm для package-lock.json, Docker для дайджестов изображений), выводят результат в формате, ожидаемом их контекстом. Понимание того, что это все одни и те же 32 bytes в разной одежде, устраняет путаницу, когда инструменты расходятся по формату.
Вывод: сравнивайте байты, а не строки — вычислите дайджест с помощью ToolAcre SHA хеш-калькулятора, а затем преобразуйте его в представление, по которому вы проверяете.
Чтобы вручную преобразовать шестнадцатеричный дайджест в Base64, сгруппируйте шестнадцатеричные цифры в байты, преобразуйте каждый байт в десятичный, а затем закодируйте с использованием алфавита Base64. Байт 0xba (шестнадцатеричный ba) имеет десятичное значение 186; 0x78 — это 120; 0x16 — это 22; 0xbf — это 191. Группировка этих четырех байтов и кодировка в формате base64 дают символы w (0 + 22 в алфавите), as (кодировка 186), AA (кодировка 120), vw (кодировка 191). Для полного дайджеста необходимо выполнить это 10 раз и при необходимости дополнить. Этот ручной процесс поучителен, но утомителен; инструмент преобразования base64 делает это мгновенно.
Ключевой вывод заключается в том, что дайджест — это сначала байты, а текстовое представление — вторично. Каждое кодирование одних и тех же байтов декодирует обратно в одни и те же байты и, таким образом, является взаимозаменяемым для целей проверки целостности. Различия в регистре в шестнадцатеричном формате, различия в заполнении в base64, префиксах и интервалах — все это варианты форматирования, которые не влияют на фактическое значение. Когда вы овладеете способностью конвертировать представления, несоответствия формата дайджеста станут проблемой отладки, которую вы сможете решить, а не загадкой.