Збереження хеш-значень SHA1 в MySQL


160

У мене є просте запитання, яке виникало, коли я хотів зберегти результат хеша SHA1 в базі даних MySQL:

Як довго має бути поле VARCHAR, в якому я зберігаю результат хешу?


9
Якщо ви просто google sha1, клацніть їм пощастило, і ви повинні бути на wikipedia, де ви можете знайти, це завжди 160 біт.
Тім Меттьюз

Відповіді:


315

Я б використовував VARCHARдля даних змінної довжини, але не для даних фіксованої довжини. Оскільки значення SHA-1 завжди 160 біт, VARCHARто просто витрачається додатковий байт для довжини поля фіксованої довжини .

І я також не зберігав би значення, SHA1яке повертається. Тому що для цього використовується всього 4 біта на символ, і тому знадобиться 160/4 = 40 символів. Але якщо ви використовуєте 8 біт на символ, вам знадобиться лише поле 160/8 = 20 символів.

Тому я рекомендую вам використовувати BINARY(20)та UNHEXфункцію для перетворення SHA1значення у бінарне.

Я порівняв вимоги щодо зберігання для BINARY(20)та CHAR(40).

CREATE TABLE `binary` (
    `id` int unsigned auto_increment primary key,
    `password` binary(20) not null
);
CREATE TABLE `char` (
    `id` int unsigned auto_increment primary key,
    `password` char(40) not null
);

З мільйонами записів binary(20)займає 44,56 млн, тоді як char(40)займає 64,57 млн. InnoDBдвигун.


2
У PostgreSQL це перекладається на використання поля bytea, правда?
mvexel

Рішення чудове, але є інший момент використовувати char (40) із зафіксованим sha1 - це набагато ширше використовується, і в коді програми буде менше проблем з перетворенням.
Артур Кушман

2
Примітка для користувачів phpmyadmin. Зберігаючи хеш як бінарний, phpmyadmin відображатиме його як шістнадцяткову рядок, але pma не зможе використовувати його на наданій "вкладці пошуку". Працює лише в тому випадку, якщо ви додасте UNHEX()вручну до sql.
Тімо Хуовінен

2
@Gumbo Ви можете зберігати змінну кількість байтів у байті. Ви посилаєтесь на вимоги до зберігання типу bytea. Що означає "1 або 4 байти плюс фактичний двійковий рядок". Те, на що посилається "1 або 4", може бути довжиною збережених даних, оскільки ви не можете використовувати нульовий байт, щоб закінчити рядок, як це робиться з varchar. Це означає, але не вказано в посібнику, що ви можете зберігати до 2 ^ (8 * 4) або 4+ гігабайт у байті. postgresql.org/docs/9.0/static/datatype-binary.html Зберігання хешу в базі даних postgres, ймовірно, буде найменшим як стовпчик бітів або байтів.
Віктор

2
dev.mysql.com/doc/refman/5.5/uk/… надає інформацію про продуктивність та зберігання під час зберігання результатів функцій крипт
Clocker


11

Довідка з цього блогу:

Нижче наведено список алгоритму хешування, а також його необхідний розмір бітів:

  • MD5 = 128-бітове хеш-значення.
  • SHA1 = 160-бітове хеш-значення.
  • SHA224 = 224-бітове хеш-значення.
  • SHA256 = 256-бітове хеш-значення.
  • SHA384 = 384-бітове хеш-значення.
  • SHA512 = 512-бітове хеш-значення.

Створено одну зразкову таблицю з вимогою CHAR (n):

CREATE TABLE tbl_PasswordDataType
(
    ID INTEGER
    ,MD5_128_bit CHAR(32)
    ,SHA_160_bit CHAR(40)
    ,SHA_224_bit CHAR(56)
    ,SHA_256_bit CHAR(64)
    ,SHA_384_bit CHAR(96)
    ,SHA_512_bit CHAR(128)
); 
INSERT INTO tbl_PasswordDataType
VALUES 
(
    1
    ,MD5('SamplePass_WithAddedSalt')
    ,SHA1('SamplePass_WithAddedSalt')
    ,SHA2('SamplePass_WithAddedSalt',224)
    ,SHA2('SamplePass_WithAddedSalt',256)
    ,SHA2('SamplePass_WithAddedSalt',384)
    ,SHA2('SamplePass_WithAddedSalt',512)
);

10
Будь ласка , будь ласка, будь ласка , не зберігайте такі паролі.
Беррі М.

Ей, Беррі, ти можеш пояснити, ЧОМУ? докладно
Анвеш

4
Зберігання простих хешів паролів значно спрощує "вилучення" паролів, якщо ваша база даних порушена, ніж якщо ви використовуєте солений (сподіваємось, розтягнутий) хеш паролів. Пропоноване читання: paragonie.com/blog/2016/02/how-safely-store-password-in-2016
мат

2
@BerryM. читаючи це через рік, і не замислювався ні на секунду, що хтось говорить про паролі або що якщо люди все ще використовують простий хеш для зберігання автентичних даних. Але вони так: D
Rohit Hazra

6

Розмір виводу sha1 - 160 біт. Це 160/8 == 20 символів (якщо ви використовуєте 8-бітні символи) або 160/16 = 10 (якщо ви використовуєте 16-бітні символи).


Припускаючи, що 8-бітні двійкові символи. 40 символів, якщо вони зберігаються як шістнадцятковий.
Тизоїд

3

Отже, довжина становить 10 10-бітних символів та 40-ти шістнадцяткових цифр.

У будь-якому випадку визначте формат, який ви збираєтесь зберігати, і зробіть поле фіксованого розміру, виходячи з цього формату. Таким чином у вас не буде зайвого місця.


2

Ви все ще можете використовувати VARCHAR у випадках, коли ви не завжди зберігаєте хеш для користувача (наприклад, автентифікація облікових записів / забутий URL для входу). Після того, як користувач підтвердив / змінив інформацію про вхід, він не повинен мати можливість використовувати хеш і не повинен мати жодних причин. Ви можете створити окрему таблицю для зберігання тимчасових хеш -> асоціацій користувачів, які можна видалити, але я не думаю, що більшість людей це заважають.


2

Якщо вам потрібен індекс у колонці sha1, я пропоную CHAR (40) з міркувань продуктивності. У моєму випадку стовпець sha1 - це маркер підтвердження електронною поштою, тому на цільовій сторінці запит вводиться лише з маркером. У цьому випадку CHAR (40) з INDEX, на мій погляд, найкращий вибір :)

Якщо ви хочете прийняти цей метод, не забудьте залишити $ raw_output = false.


1
Чому б ви не індексували ДОВІДНИК (20)? Хіба це не так швидко і вдвічі більше за розміром?
nickdnk

Ну це ~ 5 років тому назад, але я думаю, я мав на увазі той факт, що вам все одно потрібно зняти шрифт, що додає певного навантаження (+ робить додаток складніше в обслуговуванні та менш портативний?). Це якось залежить і від вашого обладнання, якщо у вас менше місця на зберігання, і це повільно, ймовірно, найкраще дотримуватися двійкового (20), інакше я б сказав char (40). Важко сказати, не запускаючи тести з мовою та обладнанням, якими ви користуєтесь, і подивіться, що вам найбільше підходить.
Франческо Касула

1
Я гадаю, що якщо ви робите щось, окрім вибору, де unhex (хеш) = хеш, щоб отримати один рядок, то, можливо, ви маєте рацію. Але збереження буферизованого індексу займе вдвічі більше пам'яті.
nickdnk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.