ASP.NETメンバーシップはどのようにソルトキーを生成し、次にそれをどのようにエンコードしますか(つまり、ソルト+パスワードまたはパスワード+ソルト)?
メンバーシップで SHA-1 を使用していますが、同じソルトを再作成して、組み込みのメンバーシップのものが私のものと同じ方法でハッシュできるようにしたいと思います。
編集2:気にしないでください。私はそれを読み間違えて、それがビットではなくバイトを言っていると思っていました。だから私は128ビットではなく128バイトを渡していた。
編集:私はそうしようとしていました。これは私が持っているものです、
public string EncodePassword(string password, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(password);
byte[] src = Encoding.Unicode.GetBytes(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
private byte[] createSalt(byte[] saltSize)
{
byte[] saltBytes = saltSize;
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetNonZeroBytes(saltBytes);
return saltBytes;
}
そのため、ASP.NETメンバーシップがこれを認識するかどうかを確認しようとはしていませんが、ハッシュ化されたパスワードは近いように見えます。ソルト用にbase64に変換する方法がわかりません。
これは私がしました
byte[] storeSalt = createSalt(new byte[128]);
string salt = Encoding.Unicode.GetString(storeSalt);
string base64Salt = Convert.ToBase64String(storeSalt);
int test = base64Salt.Length;
テストの長さは172で、128ビットをはるかに超えています。何が問題なのですか。
これは彼らの塩がどのように見えるかです
vkNj4EvbEPbk1HHW+K8y/A==
これは私の塩がどのように見えるかです
E9oEtqo0livLke9+csUkf2AOLzFsOvhkB/NocSQm33aySyNOphplx9yH2bgsHoEeR/aw/pMe4SkeDvNVfnemoB4PDNRUB9drFhzXOW5jypF9NQmBZaJDvJ+uK3mPXsWkEcxANn9mdRzYCEYCaVhgAZ5oQRnnT721mbFKpfc4kpI=
ASP.NETメンバーシップが使用するデフォルトのハッシュアルゴリズムとは何ですか?には、デフォルトのアルゴリズムについての適切な説明があります。
お役に立てば幸いです。
編集-私が言及していた答えは、一番上の投稿のコードです、
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
//byte[] src = Encoding.Unicode.GetBytes(salt); Corrected 5/15/2013
byte[] src = Convert.FromBase64String(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
彼らはBlockCopyを使用してUnicodeソルト+パスを組み合わせています
-あなたの質問への回答:
両方のアルゴリズムが必要であり、異なる役割を果たします...
RNG暗号は塩を生成するために使用されます。これは基本的にランダムデータの長い文字列です。これは、ユーザーごとに生成および保存されます。通常、これは、ユーザーが作成されたとき、またはパスワードが変更されたときに行われます。
BlockCopyは、ソルトとパスワードを組み合わせるために使用する方法にすぎません。上記のコードは、基本的にソルト+パスワードに相当します。
完全にランダムであるため、ソルト値を再作成することはできません。ただし、フレームワークによってユーザーごとに保存されます。
ソルトをパスワードと組み合わせ、上記の手法を使用してハッシュすると、フレームワークによって保存されたハッシュ値を使用してユーザーのパスワードを確認できます。
私たちはあなたの質問を異なって読んだと思います。私が投稿したコードではソルトは生成されませんが、ASP.NETメンバーシップと互換性のある方法で使用できます。
申し訳ありませんが、私の説明は最善ではありません-それはあなたの質問に答えますか?
SQLMembershipProviderがソルトを生成する方法は次のとおりです。
private string GenerateSalt() {
var buf = new byte[16];
(new RNGCryptoServiceProvider()).GetBytes(buf);
return Convert.ToBase64String(buf);
}
ASP.NETのSQLプロバイダーコードをダウンロードできます ここ 。
私が抱えていた問題は、IIS7で実行されている開発アプリケーションでした。 .NET 4.0は、.NET2.0のデフォルトのHashAlgorithmTypeとは異なるデフォルトのハッシュアルゴリズムを使用していました。
Microsoftの「EncodePassword」サンプルコードでは、Membership.HashAlgorithmType
を参照しています。これは、web.config
で指定されていない場合、フレームワークのデフォルトを返すと思います。
このGenerateSaltメソッドとEncodePasswordメソッドの両方をアプリケーションで機能させることができました。
私の結合されたコード:
internal string GenerateSalt()
{
byte[] buf = new byte[16];
(new RNGCryptoServiceProvider()).GetBytes(buf);
return Convert.ToBase64String(buf);
}
internal string EncodePassword(string pass, int passwordFormat, string salt)
{
if (passwordFormat == 0) // MembershipPasswordFormat.Clear
return pass;
byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(salt);
byte[] bAll = new byte[bSalt.Length + bIn.Length];
byte[] bRet = null;
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
if (passwordFormat == 1)
{ // MembershipPasswordFormat.Hashed
HashAlgorithm s = HashAlgorithm.Create("SHA1");
// Hardcoded "SHA1" instead of Membership.HashAlgorithmType
bRet = s.ComputeHash(bAll);
}
else
{
bRet = EncryptPassword(bAll);
}
return Convert.ToBase64String(bRet);
}
これを行う1つの方法があります。ソルトは単なる乱数です。フレームワークライブラリのRNGCryptoServiceProviderクラスを使用して、ソルトとして使用するのに適した乱数を生成できます。
private const int ITERATIONS = 10000;
private const int SALT_SIZE = 32;
private const int HASH_SIZE = 32;
public void SaltAndHashPassword(string password, out byte[] salt,
out byte[] hash)
{
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
password,
SALT_SIZE,
ITERATIONS);
salt = rdb.Salt;
hash = rdb.GetBytes(HASH_SIZE);
}