Пароль SHA-512 хранится как не шестнадцатеричная строка

Я чувствую, что это настолько очевидно, что поиск в Интернете не дает никаких результатов по моей проблеме. Я смотрю на пароль root в /etc/shadow , который выглядит примерно так:

 $6$Etg2ExUZ$F9NTP7omafhKIlqaBMqng1..... 

Пароль – это то, что после второго знака $ . Используется хеширование sha512, но оно не отображается в шестнадцатеричном виде. Мой вопрос заключается в том, как преобразовать вывод hashа sha512, который обычно находится в шестнадцатеричном формате, в эту строку:

 F9NTP7omafhKIlqaBMqng1.... 

с не шестнадцатеричными символами?

    Вывод sha512 (или любого hashа) представляет собой последовательность битов, в данном случае 512, которые кодируют (очень большое) число и могут быть разделены на байты или любые другие деления, которые требуются.

    Шестнадцатеричные представления превращают каждый четырехбитный fragment в шестнадцатеричную цифру и являются обычным способом представления хешей для пользователя, но не свойственны самой hash-функции. Это могут быть как необработанные байты, так и десятичные числа, или длинная строка из 0 и 1. Важно то, что писатель и читатель договариваются о том, как кодируется число.

    В этом случае необработанные байты не будут работать, поскольку shadow файл использует новые строки для разделения записей, поэтому байт недоступен, и человеку будет трудно читать или копировать его, если он окажется с другими нечетными символами в Это. Вот почему кодировки ASCII обычно используются для hashей, которые вы можете увидеть.

    Однако представленные в ASCII шестнадцатеричные, десятичные и двоичные числа являются довольно неэффективными механизмами: шестнадцатеричный код удваивает размер необработанных байтов (4 бита ввода на один байт вывода ASCII). Для более коротких хешей это не проблема: MD5 – это всего 128 бит, 16 байтов, то есть 32 шестнадцатеричных числа, и это управляемо, но для более длинных хешей это становится громоздким быстро. Однако для такого 512-битного hashа это будет 128 байтов только для hashа. Десятичный или двоичный код будет еще хуже, хотя, вероятно, не очень важно, как долго они в этом случае, если все согласны.


    В этом конкретном случае man 3 crypt говорит, что :

    Символы «соль» и «зашифрованный» взяты из набора [a-zA-Z0-9./] .

    az (26), AZ (26), 0-9 (10) . (1) и / (1) в общей сложности 26 + 26 + 10 + 1 + 1 = 64 доступных символов, поэтому представление base-64 звучит так, как будто оно используется. Это означает, что каждый байт ASCII представляет 6 бит (2 ^ 6 = 64) данных: четыре байта (32 бита) из base64 содержат три байта (24 бита) исходных данных, поэтому он расширился только на 33% с того места, где они начались. 512-битному значению требуется 86 байтов для хранения в этой кодировке.

    Base64 является хорошим значением по умолчанию, когда а) вам нужно хранить или передавать произвольные двоичные данные в ASCII и б) никому никогда не придется читать их вслух. И то, и другое держится здесь, так что это разумный выбор. Шестнадцатеричные представления удобны, когда вам, возможно, придется читать или проверять хеш вручную, потому что регистр не важен и не так много различных значений. Существует также мало используемая, но стандартная кодировка base32, которая находится посередине (все в верхнем регистре и цифры), но нет особой причины использовать ее здесь.


    Вероятно, у вас установлен инструмент base64 , который будет выполнять эти преобразования для вас в обоих направлениях. В конце он может использовать другие байты, чем crypt – кодировка MIME base64 использует + и / вместо . и / , например – но вы можете видеть, как он превращает произвольный ввод в чуть более длинный ASCII-кодированный вывод. Существуют также онлайн-инструменты для кодирования и декодирования , но для hashа пароля вы, скорее всего, получите непечатаемые байты и недопустимые последовательности байтов, поэтому это может не сильно помочь.

    Вывод хеша представляет собой серию байтов, а не букв. Поскольку некоторые значения байтов имеют особое значение для большинства текстовых программ, байты обычно кодируются каким-либо образом. Обычная хеш-кодировка – шестнадцатеричная, одна буква на клев (полбайта). Другие тоже возможны (и тоже распространены). Тот, который используется в теневом файле, аналогичен основному 64, но использует строку преобразования ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz каждые 6 бит из вывода hashа становятся буквой из этого списка.

    Хеш-код размером 512 бит (64 байта) будет использовать 86 букв (фиксированной длины) в base64-подобной кодировке вместо более длинных 128 букв для шестнадцатеричного кодирования.

    Существует прямая функция C для выполнения шифрования. Вам не нужно декодировать его, просто сравните вывод следующей программы с фактическим значением в /etc/shadow .

    Файл: passwd-sha512.c

     #define _XOPEN_SOURCE #include  #include  #include  #include  int main(int argc, char *argv[]) { if ( argc < 3 || (int) strlen(argv[2]) > 16 ) { printf("usage: %s password salt\n", argv[0]); printf("--salt must not larger than 16 characters\n"); return; } char salt[21]; sprintf(salt, "$6$%s$", argv[2]); printf("%s\n", crypt((char*) argv[1], (char*) salt)); return; } 

    Скомпилировать:

     $ /usr/bin/gcc -lcrypt -o passwd-sha512 passwd-sha512.c 

    использование:

     $ passwd-sha512   

    Из вашего примера строка $6$Etg2ExUZ$F9NTP7omafhKIlqaBMqng1..... :

     $ ./passwd-sha512 password Etg2ExUZ $6$Etg2ExUZ$k01JYPOzptT0enZUP........ 

    Помните, что пароли в командной строке могут быть прочитаны другими пользователями, адаптируйте код C для использования stdin или другого безопасного метода.