Хранить, получать и проверять пароль (SecureString) в SQL Server - PullRequest
1 голос
/ 05 сентября 2011

У меня есть окно входа в систему, которое получает имя пользователя и пароль от пользователя, и я хотел бы знать, как лучше всего обработать пароль.Имя пользователя - это обычное текстовое поле, а пароль - это PasswordBox.Я передаю имя пользователя непосредственно в ViewModel, но устанавливаю свойство SecureString в ViewModel только после нажатия кнопки «Вход в систему» ​​с использованием Code-Behind.После того, как пароль SecureString установлен, я хочу проверить.

Я сейчас пишу LoginBox, но у меня пока полностью не разработана модель.Как я должен хранить пароль в SQL Server?Должен ли я просто записать содержимое SecureString в SQL, а затем попытаться сравнить его, когда пользователь пытается войти?

Ответы [ 2 ]

4 голосов
/ 05 сентября 2011

Вы НИКОГДА не должны хранить пароль - даже не зашифрованный ...

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

Существуют стандарты для этого:

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

Вы можете сохранить результат либо как VARBINARY напрямую, либо как VARCHAR после Base64- или HEX-кодирования байтов... вам нужно будет хранить соль вместе с ней (что не представляет угрозы для безопасности, пока каждый пароль получает свою собственную отдельную криптографически безопасную сгенерированную случайную соль).

0 голосов
/ 05 сентября 2011

На моем предыдущем выступлении мы сохранили пароль как хешированное / зашифрованное / соленое значение (используя MD5 в то время) как VARBINARY(32).Чтобы сравнить пароль позже, вместо того, чтобы пытаться расшифровать пароль, мы сравнили бы зашифрованное + соленое значение, которое мы сохранили, с зашифрованным + соленым значением пароля, который пытался.Если они совпадали, они входили, если они не совпадали, они не входили.

Хеширование выполнялось на среднем уровне (как для первоначального сохранения пароля, так и для сравнения позже),но пример на основе SQL Server (, чтобы остановить ворчание @ Yahia, это не означает, что вы можете сказать самый безопасный способ, я просто иллюстрирую методологию на очень легком примере. MD5 недостаточно силен для вас?может использовать другой и более сложный алгоритм наряду с более продвинутыми методами посола, особенно если вы выполняете хеширование на уровне приложения ):

CREATE TABLE dbo.Users
(
    UserID INT IDENTITY(1,1) PRIMARY KEY,
    Username NVARCHAR(255) NOT NULL UNIQUE,
    PasswordHash VARBINARY(32) NOT NULL
);

Процедура создания пользователя (без обработки ошибок илипредотвращение дублирования, просто псевдо).

CREATE PROCEDURE dbo.User_Create
    @Username NVARCHAR(255),
    @Password NVARCHAR(16)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @salt NVARCHAR(16) = '$w0rdf1$h';

    INSERT dbo.Users(Username, Password)
        SELECT @Username, 
          CONVERT(VARBINARY(32), HASHBYTES('MD5', @Password + @Salt));
END
GO

Теперь процедура аутентификации пользователя.

CREATE PROCEDURE dbo.User_Authenticate
    @Username NVARCHAR(255),
    @Password NVARCHAR(16)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @salt NVARCHAR(16) = '$w0rdf1$h';

    IF EXISTS 
    (
      SELECT 1 FROM dbo.Users
        WHERE Username = @Username AND 
        PasswordHash = CONVERT(VARBINARY(32), HASHBYTES('MD5', @Password + @salt))
    )
    BEGIN
        PRINT 'Please, come on in!';
    END
    ELSE
    BEGIN
        PRINT 'You can keep knocking but you cannot come in.';
    END
END
GO

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

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

...