C# Чтение зашифрованных паролей

Я использую приведенный ниже код для сохранения пароля в реестре, как мне преобразовать его обратно? Приведенный ниже код не мой, но он хорошо шифруется.

Спасибо

using System.Security.Cryptography;

public static string EncodePasswordToBase64(string password)
{  byte[] bytes   = Encoding.Unicode.GetBytes(password);
   byte[] dst     = new byte[bytes.Length];
   byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(dst);
   return Convert.ToBase64String(inArray);
}

Я просто хотел убедиться, что вы знаете, что здесь не хэшируете пароль.

Kevin 07.11.2008 01:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
1
6 878
11

Ответы 11

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

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

Как сказал кто-то другой, вычислите хэш из пароля пользователя и сравните с сохраненным значением хеша.

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

Вы этого не сделаете.

SHA1 - это хеш, а не шифрование. Это односторонняя операция; обратное преобразование невозможно.

(Хорошо, это не совсем так; если у вас есть таблица возможных значений SHA1 и значений обычного текста, таблица радуги, вам может повезти)

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

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

Kevin 07.11.2008 00:48

Хорошо, я знаю, что это не ответ на ваш конкретный вопрос, но почему вы хотите преобразовать его обратно?

Если это сравнение для обеспечения аутентификации, стандартный подход состоит в том, чтобы ТАКЖЕ зашифровать этот текст и сравнить сохраненный пароль с предоставленным паролем.

Это более безопасно, поскольку это означает, что исходный пароль никогда не нужно расшифровывать.

Гм, просто любопытно, но разве это не вернет один и тот же хеш для всех паролей одинаковой длины?

Чтобы надежно сохранить пароль, чтобы его можно было прочитать, используйте класс Защищенные данные.

public static string ProtectPassword(string password)
{
    byte[] bytes = Encoding.Unicode.GetBytes(password);
    byte[] protectedPassword = ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser);
    return Convert.ToBase64String(protectedPassword);
}

public static string UnprotectPassword(string protectedPassword)
{
    byte[] bytes = Convert.FromBase64String(protectedPassword);
    byte[] password = ProtectedData.Unprotect(bytes, null, DataProtectionScope.CurrentUser);
    return Encoding.Unicode.GetString(password);
}

Я использую ProtectedData, чтобы шифровать пароли. Я заметил, что если я запускаю Protect несколько раз, он каждый раз дает другую строку. Расшифровка дает мне оригинал, но это означает, что для сравнения строк я должен расшифровать и сравнить результат, а не зашифровать то, что они вводят, и сравнить два зашифрованных результата. Интересно, как это работает и почему каждый раз не дает одно и то же.

Stephen Price 22.03.2013 04:21

@StephenPrice: большинство криптографических алгоритмов используют вектор инициализации или nonce (см. Также соль), чтобы избежать генерации одного и того же зашифрованного вывода для одного и того же ввода. Если вы пытаетесь сравнить зашифрованные пароли (например, для аутентификации), посмотрите что-нибудь вроде bcrypt.

Bradley Grainger 22.03.2013 07:56

спасибо посмотрю на это. Только что понял, что ProtectedData для каждой машины / пользователя. Таким образом, другой разработчик (или пользователь) на другой машине не может его расшифровать. Взгляд на пространство имен Cryptography выглядит лучше, но тогда возникает проблема с тем, где хранить ключ для этого, чтобы ключ был безопасным. Раздел зашифрованного файла конфигурации? Это снова мы...

Stephen Price 22.03.2013 08:13

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

При этом известно, что у SHA1 есть слабые места, и вам следует выбрать более сильный алгоритм. Если вы хотите остаться в семействе SHA, SHA512 вполне подойдет.

Вы хотите использовать шифрование, а не хеширование. SHA подойдет, но используйте для этого методы шифрования. Проблема с шифрованием всегда в том, где поставить ключ. Вы не упомянули, была ли это рабочая станция или сервер, на котором вы это делали. На сервере я считаю, что лучше просто использовать ACL для ограничения доступа к ключу reg. Администраторы обычно могут получить доступ к ключу шифрования в любом случае ... вы должны где-то доверять. На рабочей станции вы можете использовать шифрование и сохранить ключ в коде или использовать сертификат и ограничить доступ к нему, по крайней мере, в корпоративной среде ... не для продажи программного обеспечения).

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

Чтобы использовать класс System.Security.Cryptography.ProtectedData, вы должны добавить ссылку на System.Security в свой проект.

(Щелкните правой кнопкой мыши папку «Ссылки», выберите «Добавить ссылку ...», найдите System.Security на вкладке .NET)

Я заметил недавнее добавление класса XMLEncryptedData. Для шифрования данных в файл XML предпочтительнее ли метод XMLEncryptedData, чем метод DPAPI?

Другие вопросы по теме