SQL Serverにパスワード(SecureString)を保存、取得、検証する
-
26-10-2019 - |
質問
ユーザーからユーザー名とパスワードを取得するログインウィンドウがあり、パスワードを処理する最良の方法を知りたいと思います。ユーザー名は通常のテキストボックスですが、パスワードはPasswordBoxです。ユーザー名をViewModelに直接渡しますが、Code-Behindを使用してログインボタンをクリックした場合にのみ、viewModelにセキュリストリングプロパティを設定します。パスワードSecUreStringが設定された後、検証したい。
私は今ログインボックスを書いていますが、モデルがまだ完全に解決されていません。パスワードをSQL Serverに保存するにはどうすればよいですか? SecureStringのコンテンツをSQLに書いてから、ユーザーがログインしようとしたときに比較してみますか?
解決
パスワードを保存しないでください - 暗号化さえしません...
パスワードのハッシュを保存するだけ(ハッシュが安全な方法で実装されている限りPASWordが取得されるのを防ぎます)、検証のために、ユーザーはパスワードを同じ方法で提供し、結果を比較しました...
そうするための基準があります:
- http://en.wikipedia.org/wiki/pbkdf2
- http://www.ietf.org/rfc/rfc2898.txt
- http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx
上記の標準では、虹のテーブルなどを使用するのが難しくなります。塩に加えて数ラウンドを使用するため計算を非常に高価にするため、ハッシュはたとえば1000倍遅い(1000ラウンド)ですが、これはまさにこれですあなたが望む - 攻撃者は同じ計算を行う必要があるため、ブルートフォースによって目標を達成するために、圧倒的な力または時間を1000倍必要とします...
結果を直接varbinaryとして、またはbase64またはhexをエンコードした後のVarcharとして保存できます...それと一緒に塩を保存する必要があります(すべてのパスワードが独自の暗号化されている限り、セキュリティリスクはありません。安全な生成されたランダム塩)。
他のヒント
私の以前のギグでは、パスワードをハッシュ/暗号化/塩分値として保存しました(その時点でMD5を使用) VARBINARY(32)
. 。後でパスワードを比較するために、パスワードを解読しようとするのではなく、格納された暗号化された暗号化 +塩漬け値を、試行されるパスワードの塩分値と比較しました。彼らが一致した場合、彼らは入りました、彼らが一致しなかった場合、彼らは入りませんでした。
ハッシュ作業は中間層で行われました(最初はパスワードを保存することと後で比較するために)が、SQLサーバーベースの例(@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)として渡す可能性があります。そして、あなたはおそらくコードで塩を平易なテキストに保存しないかもしれませんが、他の場所からそれを取得します。
これは、暗号化されていないパスワードを保存するよりも間違いなく安全ですが、パスワードを取得する機能を削除します。私の意見ではwin-win。