Почему шифрование MySQL возвращает разные результаты при каждом вызове?

#mysql #linux #unix #hash #crypt

#mysql #linux #unix #хэш #crypt

Вопрос:

У меня ужасная проблема с сервером, и я стараюсь не упускать из виду никаких деталей по этому поводу.

Пароли пользователей моей виртуальной электронной почты хранятся с помощью ENCRYPT функции MySQL. Моя основная идея заключалась в том, что я дампну таблицу моих виртуальных пользователей со старого компьютера, а затем импортирую ее на новый.

Просто для двойной проверки я попытался сохранить строку с ENCRYPT затем еще раз, и сохраненные данные отличались. Означает ли это, что я не могу экспортировать / импортировать своих пользователей просто, как я думал?

Комментарии:

1. Encrypts str using the Unix crypt() system call and returns a binary string. — ваш вопрос, вероятно, должен заключаться в том, отличается ли вывод crypt() от системы к системе или от дистрибутива к дистрибутиву.

2. @Pekka я только что прочитал, что говорится в руководстве, но когда я дважды попробовал одну и ту же строку на одном компьютере, это дало мне разные результаты. Извините за мои скудные знания, но электронная почта — это самая важная служба в ящике, поэтому я должен быть очень осмотрительным.

3.ах! Я почти ничего не знаю о crypt() себе, поэтому не могу ответить на этот вопрос. Может быть, добавить еще несколько тегов, чтобы привлечь нужных людей? Linux Unix и crypt приходит на ум.

4. да. Вы могли бы рассмотреть вопрос о unix.stackexchange.com если здесь ничего не появляется

Ответ №1:

То, что Datajam уже описал, верно. Вот еще несколько объяснений.

Если вы не предоставляете соль ENCRYPT() функции, то будет сгенерирована случайная соль, которая будет использована для шифрования строки. Соль состоит всего из двух байтов / символов.

Сначала я продемонстрирую, что если я выполню ENCRYPT() дважды с одной и той же строкой, это выдаст разные значения (потому что случайная соль отличается)

 mysql> SELECT ENCRYPT('hello');
 ------------------ 
| ENCRYPT('hello') |
 ------------------ 
| 5Q5CiJWj4GItY    | 
 ------------------ 
1 row in set (0.02 sec)

mysql> SELECT ENCRYPT('hello');
 ------------------ 
| ENCRYPT('hello') |
 ------------------ 
| 7QHPY3iSLVdas    | 
 ------------------ 
1 row in set (0.00 sec)
  

Теперь, если я использую последнюю запись и попытаюсь ENCRYPT() снова использовать значение, которое у нас уже есть в качестве соли, мы получим тот же результат:

 mysql> SELECT ENCRYPT('hello', '7QHPY3iSLVdas');
 ----------------------------------- 
| ENCRYPT('hello', '7QHPY3iSLVdas') |
 ----------------------------------- 
| 7QHPY3iSLVdas                     | 
 ----------------------------------- 
1 row in set (0.00 sec)
  

Просто чтобы доказать, что если мы получим неправильную строку (пароль) с той же самой солью, мы получим другое значение. Обратите внимание, что в этом примере два первых символа (которые являются просто солью) остаются неизменными.

 mysql> SELECT ENCRYPT('helloX', '7QHPY3iSLVdas');
 ------------------------------------ 
| ENCRYPT('helloX', '7QHPY3iSLVdas') |
 ------------------------------------ 
| 7QKDSis4DZnCU                      | 
 ------------------------------------ 
1 row in set (0.01 sec)
  

Используя эту информацию, вы должны попытаться запустить ENCRYPT() функцию на обоих серверах MySQL, указав одну и ту же соль, с обоими вы должны получить тот же результат обратно. Если нет, то реализация crypt(), вероятно, варьируется между ними.

Комментарии:

1. @James C К сожалению, я ничего не знаю о том, что такое hello , и в этом моя проблема. Я не хочу расшифровывать эти зашифрованные строки, но я хотел бы быть уверенным, что моя недавно импортированная база данных примет оригинальные пароли.

2. Если вы запустите ENCRYPT('foo','bar') на обоих серверах и получите одинаковое значение обратно на них обоих, то старые пароли будут работать на новой машине.

3. @James C соль изначально не была добавлена, поэтому зашифрованные строки являются случайными. Похоже, ничего не осталось, кроме как построить куб, а затем попробовать, работает ли он. Спасибо, Джеймс.

4. Пожалуйста, внимательно прочитайте сообщение. «Если вы не предоставляете соль функции ENCRYPT(), то будет сгенерирована случайная соль, которая будет использована для шифрования строки. Соль состоит всего из двух байтов / символов.». Соль отображается в виде первых двух символов зашифрованной строки, которая хранится в вашей базе данных.

5. @James C теперь эта часть в основном ясна. Но поскольку я ничего не знаю о паролях своих пользователей, я не могу импортировать их в новую базу данных. Или я что-то недопонимаю?

Ответ №2:

Я понимаю, что это старый пост, но если у вас похожая проблема, вам не нужно перестраивать все зашифрованные пароли. Соль — это первые два символа.

Ответ №3:

Вероятно, что функция ENCRYPT заменяет входные данные случайным значением именно по этой причине — вы хотите дважды зашифровать одни и те же данные, чтобы получить разный зашифрованный текст.

Комментарии:

1. К сожалению, соль не была добавлена при сохранении паролей : (

Ответ №4:

ENCRYPT() Функция MySQL имеет необязательный второй аргумент для определения соли, используемой алгоритмом хеширования. Если вы не укажете соль, то результат будет другим, даже для одной и той же входной строки.

Если вы переносите базу данных и хотите сохранить те же хэши, просто убедитесь, что вы также используете то же значение salt. ENCRYPT() должно выдавать тот же результат с той же входной строкой и значением соли.

Комментарии:

1. Спасибо за ваш ответ, но, к сожалению, соль не была добавлена при сохранении паролей.