Интервьюер: Как вы храните пароли в базе данных?
Интервьюер: Как вы храните пароли в базе данных?

У меня есть друг, назовем его Сяо Ван. Несколько дней назад Сяо Ван пошел на собеседование;

Интервьюер спросил: Как хранить пароли в базе данных?

сцена: Сяо Ван — заявитель, а г-н Чжан — интервьюер. Собеседование в основном посвящено хранению паролей и соответствующим технологиям безопасности.


Г-н Чжан: «Здравствуйте, Сяо Ван. Я видел, что вы упомянули в своем резюме, что имеете некоторое представление о безопасности паролей. Можете ли вы вкратце рассказать о том, какие меры следует предпринять, когда мы хотим хранить пароли пользователей?»

Сяо Ван: «Конечно, пароль — это конфиденциальная информация, поэтому нам необходимо его зашифровать, чтобы обеспечить его защиту в базе данных».

Г-н Чжан: «Шифрование? Вы имеете в виду, что пароль необходимо шифровать при его хранении? Можете ли вы это объяснить?»

Сяо Ван: «Да, мы можем использовать алгоритмы шифрования, такие как AES, чтобы зашифровать пароль и сохранить его в базе данных».

Г-н Чжан: «Вы уверены, что хотите его зашифровать? Если мы зашифруем пароль, системе потребуется расшифровать пароль для сравнения при проверке входа пользователя. Это безопасно?»

Сяо Ван: «Хм… Я думаю, может быть, пароль не стоит расшифровывать. Может быть, хеширование уместнее?»

Г-н Чжан: Да. Обычно мы не шифруем пароли, а хешируем их, потому что хэши необратимы. Знаете, почему мы это делаем?

Сяо Ван: «Я думаю, это сделано для предотвращения утечки пароля. Даже если база данных будет взломана, хакер не сможет напрямую получить пароль в виде открытого текста».

Г-н Чжан: Да. Но одной хэш-обработки недостаточно. Знаете ли вы об атаке с помощью радужной таблицы?

Сяо Ван: «Радужная таблица? Я слышал о ней, похоже, она связана со взломом хеш-значений?»

Г-н Чжан: «Да, радужная таблица — это заранее рассчитанная таблица хеш-значений. Злоумышленник может использовать ее для сопоставления хэш-значения в базе данных и поиска соответствующего открытого текстового пароля. Таким образом, просто полагаться на хэш-значение недостаточно. .Знаете, можем ли мы еще что-нибудь сделать, чтобы предотвратить это нападение?»

Сяо Ван: «Добавление соли? Мы можем сгенерировать случайное значение соли для каждого пароля, а затем хэшировать его».

Г-н Чжан: «Да, добавление соли является важной мерой для предотвращения атак по радужным таблицам. Добавляя уникальные случайные соли, мы можем значительно повысить сложность взлома. Можете ли вы привести пример того, какой алгоритм хэширования вы будете использовать?»

Сяо Ван: «Раньше наша компания использовала SHA-256 для хеширования паролей. Я слышал, что он более безопасен, чем MD5».

Г-н Чжан: «SHA-256 действительно намного безопаснее, чем MD5, но на самом деле существуют более подходящие варианты хеширования паролей. Вы слышали об Argon2?»

Сяо Ван: «Argon2 — это алгоритм, разработанный специально для хеширования паролей и получивший награду конкурса криптозоологии 2015 года. Он может устанавливать использование памяти и количество итераций, что делает его более эффективным в борьбе с грубым взломом. По сравнению с SHA-256 , Argon2 устойчив к параллельным атакам на современное оборудование».

Г-н Чжан: «Звучит очень убедительно. Тогда почему бы нам просто не использовать SHA-256? Разве он не очень широко используется?»

Сяо Ван: «SHA-256 — это алгоритм хеширования общего назначения, в основном используемый для проверки целостности данных, таких как блокчейн и цифровые подписи. Однако его применение в криптографии не так хорошо, как специализированные хэши паролей, такие как алгоритм хеширования паролей Argon2. чтобы справиться с проблемами грубой силы и временной сложности, а Argon2 может обеспечить лучшую защиту».

Г-н Чжан сказал в своем сердце: «Молодой человек неплох... он талант».


Сегодня у нас будет углубленный разговор, основанный на опыте собеседования моего друга Сяо Вана: Как хранить пароли в базе данных?


Почему мы можем только сбросить пароль, но не восстановить исходный пароль?

Была ли у вас когда-нибудь такая путаница?:Почему система всегда просит нас создать новый пароль вместо того, чтобы сообщить нам исходный пароль, когда мы забываем пароль для входа в учетную запись и нажимаем «Забыли пароль»?

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

В этой статье мы подробно обсудим эту проблему и поможем студентам, которые были или не уверены в этой проблеме, понять ее причины.

Риски прямого хранения паролей в виде открытого текста

Предположим, что пользователь регистрирует учетную запись на вашем сайте, например. xw@qq.com,и установите пароль на abc654321。Самый прямой способ — хранить пароль пользователя в открытом виде в базе данных.:

Язык кода:plaintext
копировать
username      password
xw@qq.com     abc654321

Этот метод прост и понятен,Но существуют огромные риски для безопасности。Если хакер получил доступ к вашей базе данных,Он не только может увидеть пароль пользователя,Он также может легко угадать ту же учетную запись и пароль пользователя на других веб-сайтах.。фактически,Многие пользователи используют одну и ту же комбинацию адреса электронной почты и пароля на нескольких веб-сайтах.,Это позволяет хакерам скомпрометировать веб-сайт путем,Получите информацию о пользователе с нескольких веб-сайтов. поэтому,Хранение паролей в открытом виде практически не обеспечивает защиты.

Алгоритм хеширования: необратимое хранение паролей

Чтобы устранить риски, вызванные хранением обычного текста,Разработчики часто преобразуют пароли в необратимыеХэш-значение,Затем сохраните Хэш-значение в базе данных. Например:

Язык кода:plaintext
копировать
username         password
xw@qq.com        5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

В этом примере пароль abc654321 передается через алгоритм хеширования (например, SHA-1 или SHA-256) в необратимую строку символов. Даже если хакер получит это значение хеш-функции, он не сможет напрямую вывести исходный пароль из значения хеш-функции.

Зачем это делать?

Защитите конфиденциальность пользователей:Если систему можно восстановитьили Посмотреть исходный пароль,Таким образом,Сама система будет иметь текстовую копию пароля пользователя. Это значительно увеличит риск компрометации пароля.

Предотвращение неправомерного использования после утечки данных:Даже если хакер взломает базу данных,Хэш-значение кто получил пароль,Также невозможно обратно вычислить исходный пароль посредством этих Хэш-значений. Такая конструкция значительно снижает риск кражи пароля.

Однако,Алгоритм Хэша Не совсем оборонительный。Хотя Хэшэто односторонний,Но хакеры могут взломать его грубой силой.илииспользоватьзаранее рассчитанный Хэш-значениеповерхность(Например彩虹поверхность)Выполнить вывод。вот почемуЧем быстрее рассчитывается алгоритм хеширования, тем менее он пригоден для хранения паролей.。Например,SHA-1 Расчет происходит очень быстро, поэтому он не подходит для прямого использования при хешировании паролей.

Хеширование пароля с использованием SHA-256

Язык кода:python
кодКоличество запусков:0
копировать
import hashlib

def hash_password_sha256(password: str) -> str:
    # использовать SHA-256 Алгоритм Хэша
    sha_signature = hashlib.sha256(password.encode()).hexdigest()
    return sha_signature

# Пример
password = "abc654321"
hashed_password = hash_password_sha256(password)
print("SHA-256 Хэш-значение:", hashed_password)

Хотя этот метод более безопасен, чем хранение паролей в открытом виде, его все же недостаточно, чтобы противостоять современным атакам методом перебора.

Соленое хеширование: предотвращение атак на радужные таблицы

Что такое радужная атака?

Атака по радужной таблице — это метод, который пытается быстро взломать хешированные пароли путем предварительного вычисления большого количества общих паролей и их хешей. Злоумышленник может использовать эти таблицы для быстрого поиска, сопоставления хеш-значения в базе данных и получения пароля.

Моделирование атаки по радужной таблице

Язык кода:javascript
копировать
import hashlib

# Простая имитация общего словаря паролей
common_passwords = ["123456", "password", "abc123", "qwerty", "letmein"]

# Хэш-значение (то есть имитация радужной таблицы), используемое для хранения общих паролей.
rainbow_table = {}

# Создайте радужный стол (использовать SHA-256 Алгоритм Хэша)
def create_rainbow_table():
    for password in common_passwords:
        hashed_password = hashlib.sha256(password.encode()).hexdigest()
        rainbow_table[hashed_password] = password
    print("Генерация радужной таблицыуспех!")

# Имитация взлома злоумышленником пароля Хэш через радужную таблицу
def crack_password(hashed_password):
    # Попробуйте использовать радужную таблицу, чтобы найти оригинальный пароль.
    if hashed_password in rainbow_table:
        return rainbow_table[hashed_password]
    else:
        return None

# Создайте радужный стол
create_rainbow_table()

# Имитировать пароли Хэша, хранящиеся в базе данных
stored_hashed_password = hashlib.sha256("abc123".encode()).hexdigest()
print("Сохраненный пароль Хэша:", stored_hashed_password)

# Попытка взломать сохраненный пароль Хэша через радужную таблицу.
cracked_password = crack_password(stored_hashed_password)
if cracked_password:
    print(f"Пароль взломан: {cracked_password}")
else:
    print("Невозможно взломать пароль")

Генерация радужной таблицы:我们首先创建Понятно一个简单的彩虹поверхность,Хэш-значение, содержащее общие пароли. Настоящая радужная таблица будет очень большой.,Содержит миллионы и более общих паролей и их Хэш-значение.

симуляция атаки:我们尝试通过彩虹поверхность匹配数据库中存储的Хэшпароль。Если соответствующий найден Хэш-значение,Мы можем восстановить исходный пароль.

Ограничения атак по радужным таблицам:

Радужный стол Хотя работает,Но есть ограничения,特别是当пароль存储中использовать ПонятноС сольютехническое время:

С сольюзащита:每个пароль都有独立的随机盐,Даже если радужная таблица содержит тот же пароль,И не может соответствовать Хэш-значение. так,Даже если злоумышленник получит базу данных,Им также необходимо взломать каждый пароль один за другим.

bcrypt и Другой «медленный» алгоритм Хэша:картина bcrypt、PBKDF2 Такой алгоритм хеширования паролей не только автоматически использует соль, но и еще больше увеличивает сложность взлома за счет увеличения времени вычислений.

Что такое добавленная соль?

С здесь солью,Это не поваренная соль, которую мы едим,С солью,По сути, это понятие в программировании,Используется для повышения безопасности паролей. чтобы понять это,Вы можете представить себе сцену из нашей повседневной жизни.

Предположим, вы любите пить кофе, и всем тоже нравится пить кофе. Кому-то нравится добавлять сахар, кому-то – нет. Теперь, если бы я дал вам ту же самую чашку черного кофе без сахара, вы могли бы с первого глотка сказать, что это чистый кофе и по вкусу точно такой же, как кофе в чьей-то чашке. То же самое верно и для хакеров при взломе паролей. Если у каждого метода хранения паролей является прямое хэширование пароля, хакеры могут взломать ваш пароль, сопоставив множество «обычных черных кофе» (простых паролей).

С солью,Это все равно, что добавить в кофе немного «уникальной специи».,Такие как сахар и сливки,Или даже другие начинки, которые вам нравятся. так,Даже если ингредиенты кофе у двух человек одинаковые (например, пароль одинаковый),Но каждый добавляет в него разные ингредиенты.,В результате вкус совершенно другой.

в хранилище паролей,«Соль» – это уникальная приправа. каждый раз, когда ты устанавливаешь пароль,Система добавляет к вашему паролю «соль» (случайно сгенерированную строку символов). Когда система сохраняет ваш пароль,它保存的是пароль加上盐后的一串Хэш-значение(类似你加Понятно调料后咖啡的味道)。Таким образом, даже если хакер узнает, что чужой пароль — «123456», поскольку вы добавили разные соли, он все равно не сможет выяснить, какой пароль вы использовали при его взломе.

Приведем более простой пример:

Предположим, что вы и ваш друг установили один и тот же пароль «пароль». Без соли хакер, получивший хэш пароля человека, может сразу сделать вывод, что ваш пароль и пароли всех остальных — это «пароли».

Но если добавить соль,Эквивалент пароля каждого человека больше не является простым «паролем».,Вместо этого он становится «salt1+пароль» (вы добавили немного соли 1) и «salt2+пароль» (ваш друг добавил другую соль 2). так,Даже если пароль тот же,Хакеры видят нечто совершенно иное: они не смогут взломать пароль каждого, используя только один пароль.

Таким образом, «добавление соли» — это уникальная приправа к вашему паролю, которая затрудняет взлом хакерам и делает ваш пароль более безопасным.

Язык кода:plaintext
копировать
username         salt                      password
xw@qq.com        2dc7fcc...                sha256("2dc7fcc..." + password_1)
john@163.com     afadb2f...                sha256("afadb2f..." + password_2)

Таким образом, «соли» — это уникальная приправа в пароле. Пароль каждого пользователя будет иметь уникальное значение соли. Даже если хакер получит базу данных, он не сможет легко взломать пароль через радужную таблицу, что сделает ваш пароль более безопасным.

Хэш SHA-256 с использованием случайной соли

Язык кода:python
кодКоличество запусков:0
копировать
import os
import hashlib

def generate_salt() -> str:
    # Создайте 16-байтовое случайное значение соли
    return os.urandom(16).hex()

def hash_password_with_salt(password: str, salt: str) -> str:
    # использовать SHA-256 и Случайный соль Хэш пароль
    salted_password = salt + password
    sha_signature = hashlib.sha256(salted_password.encode()).hexdigest()
    return sha_signature

# Пример
password = "abc654321"
salt = generate_salt()
hashed_password = hash_password_with_salt(password, salt)
print("Случайная соль:", salt)
print("Пароль после Хэш:", hashed_password)

Более безопасные алгоритмы хеширования паролей: bcrypt и PBKDF2.

Хотя SHA-256 С солью повышает безопасность паролей,Однако определенный риск взлома все же существует.。bcrypt и PBKDF2 Такие алгоритмы разработаны специально для хранения паролей, и их вычисления выполняются намного медленнее, чем обычные алгоритмы хеширования, что затрудняет взлом. Эти алгоритмы имеют встроенные случайные соли, и вычислительные затраты могут быть скорректированы по мере необходимости.

Хеширование пароля с использованием bcrypt

Язык кода:python
кодКоличество запусков:0
копировать
import bcrypt

def hash_password_bcrypt(password: str) -> str:
    # Генерация соли и пароля
    salt = bcrypt.gensalt()  # Автоматически генерировать соль
    hashed_password = bcrypt.hashpw(password.encode(), salt)
    return hashed_password

def check_password_bcrypt(password: str, hashed_password: str) -> bool:
    # Подтвердить пароль
    return bcrypt.checkpw(password.encode(), hashed_password)

# Пример
password = "abc654321"
hashed_password = hash_password_bcrypt(password)
print("bcrypt Пароль после Хэш: ", hashed_password)

# Подтвердить пароль
is_valid = check_password_bcrypt(password, hashed_password)
print("Результат проверки пароля:", is_valid)

Сброс пароля: соображения безопасности

Именно потому, что пароли хранятся необратимо.,Когда пользователь забывает свой пароль,Система не может напрямую сообщить пользователю исходный пароль. Напротив,Система обеспечит безопасность путем сброса пароля. Отправив код подтверждения и другие методы аутентификации.,Убедитесь, что только законные пользователи могут сбрасывать пароли. Этот метод может эффективно помешать злоумышленникам получить пароли через систему.

Подвести итог

Правильный способ хранения паролей имеет решающее значение. Независимо от того, используете ли вы алгоритмы хеширования, методы «соли» или более безопасные алгоритмы хеширования паролей, такие как bcrypt и PBKDF2),Конечная цель — защитить пользовательские данные от атак. Вместо того, чтобы разрешать пользователям сбрасывать свои пароли вместо просмотра исходного пароля,Это необходимое средство для обеспечения безопасного хранения паролей. через эту статью,Я надеюсь, что у вас есть более глубокое понимание принципов и соображений безопасности, лежащих в основе хранения паролей.


Дополнительно:

  1. HMAC (Код аутентификации ХэшMessage):可以进一步加强пароль的安全性,Особенно когда сервер и база данных разделены.
  2. Инструменты управления паролями:использовать Инструменты управления паролямигенерироватьи保存复杂的пароль,Это также часть обучения пользователей.,Снижает риск повторения пользователями. Используйте простые пароли.
boy illustration
[Углубленное понимание Java IO] Используйте InputStreamReader для чтения содержимого файла и легкого выполнения задач преобразования текста.
boy illustration
сравнение строк PHP
boy illustration
9 сценариев асинхронного сбоя @Async
boy illustration
Эффективная обработка запланированных задач: углубленное изучение секретов библиотеки APScheduler на Python
boy illustration
Рекомендации по облегченному артефакту развязки внутренних компонентов Spring Event (событие Spring)
boy illustration
Go: Лесоруб-лесоруб на колесах Введение
boy illustration
Основы серверной разработки: технология кэширования, которую должен освоить каждый программист
boy illustration
Java Advanced Collections TreeSet: что это такое и зачем его использовать?
boy illustration
Оказывается, у команды go build столько знаний
boy illustration
Node.js
boy illustration
Анализ исходного кода, связанный с запланированными задачами версии ruoyi-vue (7), то есть анализ модуля ruoyi-quartz.
boy illustration
Вход в систему с помощью скан-кода WeChat (1) — объяснение процесса входа в систему со скан-кодом, получение авторизованного QR-кода для входа.
boy illustration
HikariPool-1 — обнаружено отсутствие потока или скачок тактовой частоты, а также конфигурация источника данных Hikari.
boy illustration
Сравнение высокопроизводительной библиотеки JSON Go
boy illustration
Простое руководство по извлечению аудио с помощью FFmpeg
boy illustration
Подсчитайте количество строк кода в проекте
boy illustration
Spring Boot элегантно реализует многопользовательскую архитектуру: концепции и практика
boy illustration
Как интегрировать функцию оповещения корпоративного WeChat в систему планирования xxl-job
boy illustration
SpringBoot интегрирует отправку сообщений через веб-сокет в режиме реального времени
boy illustration
Краткий анализ основных библиотек журналов в Go: узнайте, как интегрировать функции вращения и резки бревен на уровне проектирования.
boy illustration
Реализация API-шлюза с нуля-Golang
boy illustration
[Разговорный сайт] Как Springboot получает значения свойств из файлов конфигурации yml или свойств
boy illustration
Spring Boot — синхронные события приложения против асинхронных событий публикации и подписки. Практический бой
boy illustration
Spring Boot использует Swagger3 для создания документов интерфейса API.
boy illustration
[1269] Использование Gunicorn для развертывания проектов flask.
boy illustration
Краткое изложение 10 способов регистрации bean-компонентов в SpringBoot
boy illustration
Flask Learning-9. 2 способа включения режима отладки (debug mode).
boy illustration
Руководство по настройке самостоятельного сервера для Eudemons Parlu
boy illustration
40 вопросов для собеседований по SpringBoot, которые необходимо задавать на собеседованиях! При необходимости ответьте на вопросы для собеседования SpringBoot [предлагаемый сборник] [легко понять]
boy illustration
Через два года JVM может быть заменен GraalVM.