English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Asp.netでMicrosoft.IdentityのIPasswordHasherの暗号化のデフォルト実装と使用

MS Identity認証体系について詳しい方は、UserManagerの役割を知っているでしょう。彼は全体の体系のスケジューラであり、ユーザ情報、役割情報、パスワードの管理を助けるユーザ行動を定義しています。その実装はUserStoreで行われ、IUserStore、IUserPasswordStore、IRoleStoreなど、私たちが定義したものを実現できます。一整套のユーザ行動に基づいて、独自のユーザ情報やデータ構造、データストレージをカスタマイズできます。PasswordのHasherに関しては、MSは完全な行動定義を提供しており、UserManagerがスケジュールしています。例えば、

UserManager.PasswordHasher.HashPassword(password)

PasswordHasherはUserManagerインターフェースで以下のように定義されています:

私はそのデフォルトの実装に興味がなかったため、複数のアプリケーションのログイン認証のために独立したユーザ認証プロジェクトが必要でした。これは認証サービスとして機能し、トークンを生成し、認証が成功すると、ユーザのHTTPリクエストヘッダのAuthorizationにトークンを付けてアプリケーションサーバ上のさまざまなリソースにアクセスします。

そのため、複数のアプリケーションのパスワード認証で以下のような問題が発生しました:

例えば、アプリケーションAはIPasswordHasherを実現してカスタム暗号化方法——MDを独自に使用しています。5+saltの形式で、アプリケーションBはIdentityのデフォルトのPasswordHasherを使用して実現しており、デコンパイルして以下のコードを得ることができます:

従って、複数のアプリケーションで異なる暗号化方法に対応するために、私はソースコードをデコンパイルして、デフォルトの暗号化方法を取得し、異なるアプリケーション名に基づいてパスワードの暗号化または解密を判断したり、データベースとユーザー入力のパスワードを直接比較する方法を通じて行う必要がありました。まず、MSのデフォルトのPasswordHasherの具体的な実装を示します。

// Decompiled with JetBrains decompiler
// Type: Microsoft.AspNet.Identity.Crypto
// Assembly: Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: E3A10FFD-023A-4BC3-AD53-32D145ABF1C9
// Assembly location: C:\Sport\NewProject\V2.0\Api\Fantasy.Sport\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
namespace Microsoft.AspNet.Identity
{
 internal static class Crypto
 {
 private const int PBKDF2IterCount = 1000;
 private const int PBKDF2SubkeyLength = 32;
 private const int SaltSize = 16;
 public static string HashPassword(string password)
 {
  if (password == null)
  throw new ArgumentNullException("password");
  byte[] salt;
  byte[] bytes;
  using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, 16, 1000))
  {
  salt = rfc2898DeriveBytes.Salt;
  bytes = rfc2898DeriveBytes.GetBytes(32);
  }
  byte[] inArray = new byte[49];
  Buffer.BlockCopy((Array) salt, 0, (Array) inArray, 1, 16);
  Buffer.BlockCopy((Array) bytes, 0, (Array) inArray, 17, 32);
  return Convert.ToBase64String(inArray);
 }
 public static bool VerifyHashedPassword(string hashedPassword, string password)
 {
  if (hashedPassword == null)
  return false;
  if (password == null)
  throw new ArgumentNullException("password");
  byte[] numArray = Convert.FromBase64String(hashedPassword);
  if (numArray.Length != 49 || (int) numArray[0] != 0)
  return false;
  byte[] salt = new byte[16];
  Buffer.BlockCopy((Array) numArray, 1, (Array) salt, 0, 16);
  byte[] a = new byte[32];
  Buffer.BlockCopy((Array) numArray, 17, (Array) a, 0, 32);
  byte[] bytes;
  using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, 1000))
  bytes = rfc2898DeriveBytes.GetBytes(32);
  return Crypto.ByteArraysEqual(a, bytes);
 }
 [MethodImpl(MethodImplOptions.NoOptimization)]
 private static bool ByteArraysEqual(byte[] a, byte[] b)
 {
  if (object.ReferenceEquals((object) a, (object) b))
  return true;
  if (a == null || b == null || a.Length != b.Length)
  return false;
  bool flag = true;
  for (int index = 0; index < a.Length; ++index)
  flag &= (int) a[index] == (int) b[index];
  return flag;
 }
 }
}

これらのソースコードをどう使うかを尋ねる人もいるかもしれません。以下では、その問題について簡単に説明します。

最初は、ただの暗号化であると単純に思って、詳しく見なくても使えると思っていました。

ユーザー登録やパスワードの変更時には、上記の HashPassword メソッドを使用してパスワードの暗号化が行われます。したがって、新しいカスタム PasswordHasher では、アプリケーションBがユーザーログインパスワードを比較する際に、ユーザー入力を直接 HashPassword で暗号化するだけで良いと思いました。したがって、私はカスタムの VerifyHashedPassword (Verify は確認を意味します)メソッドを、データベースの Pwd とハッシャー処理された結果が一致するかどうかを比較するために作成しました。しかし、結果として、同じ文字列でも、異なる暗号化結果が生成されます。これは以前に md5+salt が異なるため、私はデフォルトの実装である VerifyHashedPassword メソッドを思い出しました。

最後に言いたいのは、マイクロソフト Identity の暗号化方法(上記の Hasher)をそのまま使用することができます。ユーザー入力とデータベースに既にハッシュされた保存結果を比較する際には、VerifyHashedPassword() メソッドを使用します。Identity 認証を使用しなくても、この暗号化アルゴリズムを使用できます。

これで本文のすべてが終わります。本文の内容が皆様の学習や仕事に少しでも役立つことを願っています。また、ナイアラの教材を多くのサポートをお願いします。

声明:本文の内容はインターネットから取得しており、著作権者は所有者であり、インターネットユーザーにより自発的に貢献し、自己でアップロードされています。本サイトは所有権を持ちません。また、人工的な編集処理は行われておらず、関連する法的責任も負いません。著作権侵害を疑われる内容がある場合は、メールで notice#w までお知らせください。3codebox.com(メール送信時は、#を@に変更してください。通報を行い、関連する証拠を提供してください。一旦確認がとれましたら、本サイトは即座に侵害を疑われる内容を削除します。)

おすすめ