Почему SHA-1 хэш длиной 40 символов, если он всего 160 бит?
Название вопроса говорит само за себя. Я исследовал SHA-1, и в большинстве мест я вижу его длиной 40 шестнадцатеричных символов, который для меня составляет 640 бит. Разве это не может быть представлено так же хорошо только с 10 шестнадцатеричными символами 160 бит = 20 байт. И один шестнадцатеричный символ может представлять 2 байта, верно? Почему это вдвое дольше, чем нужно? Чего мне не хватает в моем понимании.
И не может ли SHA-1 быть всего 5 или менее символов, если используется Base32 или Base36?
6 ответов
Один шестнадцатеричный символ может представлять только 16 различных значений, то есть 4 бита. (16 =24)
40 × 4 = 160.
И нет, вам нужно гораздо больше, чем 5 символов в base-36.
Всего имеется 2160 различных хэшей SHA-1.
2160 = 1640, так что это еще одна причина, почему нам нужно 40 шестнадцатеричных цифр.
Но 2160 = 36160 log362 = 3630,9482..., поэтому вам все равно нужно 31 символ, используя base-36.
Я думаю, что путаница OP происходит из-за того, что строка, представляющая хэш SHA1, занимает 40 байтов (по крайней мере, если вы используете ASCII), что равно 320 битам (не 640 битам).
Причина в том, что хэш находится в двоичном формате, а шестнадцатеричная строка является только его кодировкой. Поэтому, если бы вы использовали более эффективную кодировку (или вообще не использовали кодировку), вы могли бы занять всего 160 бит (20 байт), но проблема в том, что она не будет бинарно-безопасной.
Вы можете использовать base64, но в этом случае вам понадобится около 27-28 байт (или символов) вместо 40 (см. Эту страницу).
На 8-битный байт приходится два шестнадцатеричных символа, а не два байта на шестнадцатеричный символ.
Если вы работаете с 8-битными байтами (как в определении SHA-1), то шестнадцатеричный символ кодирует один высокий или низкий 4-битный полубайт в байте. Таким образом, для полного байта требуется два таких символа.
Мой ответ отличается от предыдущих в моей теории только ТОЧНЫМ происхождением путаницы ОП, а также детскими шагами, которые я приведу для пояснения.
Символ занимает различное количество байтов в зависимости от используемой кодировки ( см. Здесь). В наши дни существует несколько контекстов, когда мы используем 2 байта на символ, например, при программировании на Java ( вот почему). Таким образом, 40 символов Java будут равны 80 байтам = 640 битам, вычисление OP, и 10 символов Java действительно будут инкапсулировать нужное количество информации для хэша SHA-1.
Однако, в отличие от тысяч возможных символов Java, существует только 16 различных шестнадцатеричных символов, а именно 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E и F. Но это не то же самое, что символы Java, и занимают гораздо меньше места, чем кодировки символов Java от 0 до 9 и от A до F. Это символы, обозначающие все возможные значения, представленные всего 4 битами:
0 0000 4 0100 8 1000 C 1100
1 0001 5 0101 9 1001 D 1101
2 0010 6 0110 A 1010 E 1110
3 0011 7 0111 B 1011 F 1111
Таким образом, каждый шестнадцатеричный символ составляет только половину байта, а 40 шестнадцатеричных символов дают нам 20 байтов = 160 битов - длину хеша SHA-1.
2 шестнадцатеричных символа составляют диапазон от 0 до 255, то есть 0x00 == 0 и 0xFF == 255. Таким образом, 2 шестнадцатеричных символа являются 8-битными, что составляет 160 бит для вашего дайджеста SHA.
SHA-1 составляет 160 бит
Это переводит в 20 байтов = 40 шестнадцатеричных символов (2 шестнадцатеричных символа на байт)