ASP.NET MVC 3应用程序,BCrypt.CheckPassword失败 [英] ASP.NET MVC 3 app, BCrypt.CheckPassword failing

查看:165
本文介绍了ASP.NET MVC 3应用程序,BCrypt.CheckPassword失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作在ASP.NET MVC 3应用程序中实现安全性,现在用的是BCrypt实施<一个href=\"http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx\"相对=nofollow>这里找到的处理密码加密和验证。用户注册屏幕加密用户提供了就好了密码,哈希密码被保存到数据库中。我在使用登录页上的密码验证的一个问题,虽然,我似乎无法找出原因。

我的注册控制器动作包含以下内容:

  [HttpPost]
[RequireHttps]
公众的ActionResult注册(注​​册登记)
{
    //验证逻辑?    尝试
    {
        VAR用户=新用户
        {
            用户名= registration.Username,
            密码= Password.Hash(HttpUtility.HtmlDe code(registration.Password))
            EmailAddress的= registration.EmailAddress,
            名字= registration.FirstName,
            MiddleInitial = registration.MiddleInitial,
            姓氏= registration.LastName,
            dateCreated会= DateTime.Now,
            DateModified = DateTime.Now,
            LastLogin = DateTime.Now
        };        VAR用户id = _repository.CreateUser(用户);
    }
    赶上(异常前)
    {
        ModelState.AddModelError(用户,创建用户时出错,请再试一次。);
        返回查看(注册);
    }    //做一些其他的东西...
}

这是Password.Hash:

 公共静态字符串哈希(字符​​串密码)
{
    返回BCrypt.HashPassword(密码,BCrypt.GenerateSalt(12));
}

这是我如何处理登录:

  [HttpPost]
[RequireHttps]
公众的ActionResult登录(登录凭据)
{
    //验证逻辑?    VAR授权= _repository.CredentialsAreValid(HttpUtility.HtmlDe code(login.username),login.password);
    如果(授权)
    {
        //登录的用户...
    }
    其他
    {
        ModelState.AddModelError(AuthFail,验证失败,请重试);
        返回查看(登录);
    }
}

CredentialsAreValid包装调用BCrypt.CheckPassword:

 公共BOOL CredentialsAreValid(用户名字符串,字符串密码)
{
    VAR用户=的getUser(用户名);
    如果(用户== NULL)
        返回false;    返回Password.Compare(密码,user.password的);
}

Password.Compare:

 公共静态布尔比较(字符串密码,串哈希)
{
    返回BCrypt.CheckPassword(密码哈希);
}

最后,这就是BCrypt.CheckPassword做:

 公共静态布尔CheckPassword(明文字符串,字符串哈希)
{
    返回StringComparer.Ordinal.Compare(散列,HashPassword(明文散列))== 0;
}

所以,是的......我不知道这是怎么回事,但我知道,是我的布尔在我登录控制器动作授权变量的总是的出于某种原因返回false。

我已经在过去使用上至少几个其他项目的此相同BCrypt类,从来没有与它在所有出现任何问题。是ASP.NET MVC 3做一些奇怪的,不同的编码给我丢失或需要处理不同的东西或发布的数据?如果不是这样,或者SQL CE 4做(这是我目前使用数据存储)?一切似乎是为了从我可以告诉我的code,但由于某些原因,密码校验失败每次。任何人有什么想法?

感谢。

更新:这是包含与实例BCrypt类code注释如何使用它和作品

  ///&LT;总结&gt; BCrypt实现OpenBSD的风格河豚密码哈希
使用面向未来的适应密码方案中描述的方案///
///由尼尔斯Provos和大卫Mazieres&LT; /总结&gt;
///&LT;&言论GT;
///&LT;段&gt;这密码哈希系统试图阻挠离线
使用计算密集型哈希///密码破解
///算法的基础上,布鲁斯的Blowfish密码。工作
///算法的因子parametized,因此它可以作为增加
///电脑获得更快的&LT; /对&GT;
///&LT;段&gt;向散列首次密码,请致电
///&所述c取代; HashPassword&下; / c取代;方法用随机盐,就像这样:LT; /对&GT;
///&LT; code&GT;
///串散列= BCrypt.HashPassword(plainPassword,BCrypt.GenerateSalt());
///&LT; / code&GT;
///&LT;段&gt;向检查明文密码是否匹配一个有
///被散列previously,使用的&lt; C&GT; CheckPassword&LT; / c取代;方法:其中; /段&GT;
///&LT; code&GT;
///如果(BCrypt.CheckPassword(candidatePassword,storedHash)){
/// Console.WriteLine(它匹配);
///}其他{
/// Console.WriteLine(它不匹配);
///}
///&LT; / code&GT;
///&所述;段&gt;将&所述c取代; GenerateSalt&下; / c取代;方法接受一个可选的参数
///(logRounds)确定的计算复杂
///散列:或其可/段&GT;
///&LT; code&GT;
///串strongSalt = BCrypt.GenerateSalt(10);
///串strongerSalt = BCrypt.GenerateSalt(12);
///&LT; / code&GT;
///&LT;&款GT;
///的工作成倍增加(2 ** log_rounds),所以该量
///每个增量是两倍的工作。默认log_rounds是
/// 10,并且有效范围是4至31。
///&LT; /对&GT;
///&LT; /言论&GT;


解决方案

我有同样的问题。 <一href=\"http://stackoverflow.com/questions/22833610/bcrypthelper-checkpassword-always-returns-false\">BCryptHelper.CheckPassword始终返回false

我发现散列串被存储在数据库作为NCHAR()。这引起了检查总是失败。
我改变了这种为char()和它的作品。

I'm working on implementing security in an ASP.NET MVC 3 application, and am using the BCrypt implementation found here to handle encryption and verification of passwords. The user registration screen encrypts the password the user provides just fine, and the hashed password gets saved to the database. I'm having a problem with password verification on the login page though, and I can't seem to figure out why.

My registration controller action contains the following:

[HttpPost]
[RequireHttps]
public ActionResult Register(Registration registration)
{
    // Validation logic...

    try
    {
        var user = new User
        {
            Username = registration.Username,
            Password = Password.Hash(HttpUtility.HtmlDecode(registration.Password)),
            EmailAddress = registration.EmailAddress,
            FirstName = registration.FirstName,
            MiddleInitial = registration.MiddleInitial,
            LastName = registration.LastName,
            DateCreated = DateTime.Now,
            DateModified = DateTime.Now,
            LastLogin = DateTime.Now
        };

        var userId = _repository.CreateUser(user);
    }
    catch (Exception ex)
    {
        ModelState.AddModelError("User", "Error creating user, please try again.");
        return View(registration);
    }

    // Do some other stuff...
}

This is Password.Hash:

public static string Hash(string password)
{
    return BCrypt.HashPassword(password, BCrypt.GenerateSalt(12));
}

This is how I'm handling login:

[HttpPost]
[RequireHttps]
public ActionResult Login(Credentials login)
{
    // Validation logic...

    var authorized = _repository.CredentialsAreValid(HttpUtility.HtmlDecode(login.username), login.password);
    if (authorized)
    {
        // log the user in...
    }
    else
    {
        ModelState.AddModelError("AuthFail", "Authentication failed, please try again");
        return View(login);
    }
}

CredentialsAreValid wraps the call to BCrypt.CheckPassword:

public bool CredentialsAreValid(string username, string password)
{
    var user = GetUser(username);
    if (user == null)
        return false;

    return Password.Compare(password, user.Password);
}

Password.Compare:

public static bool Compare(string password, string hash)
{
    return BCrypt.CheckPassword(password, hash);
}

And finally, this is what BCrypt.CheckPassword is doing:

public static bool CheckPassword(string plaintext, string hashed)
{
    return StringComparer.Ordinal.Compare(hashed, HashPassword(plaintext, hashed)) == 0;
}

So, yeah...I dunno what's going on, but what I do know, is that my boolean authorized variable in my Login controller action always returns false for some reason.

I've used this exact same BCrypt class on at least a couple of other projects in the past, and never had any problems with it at all. Is ASP.NET MVC 3 doing some weird, different encoding to posted data that I'm missing or need to handle differently or something? Either that, or is SQL CE 4 doing it (that's the datastore I'm currently using)? Everything seems to be in order in my code from what I can tell, but for some reason, password checking is failing every time. Anyone have any ideas?

Thanks.

UPDATE: Here's the code comments included with the BCrypt class with examples of how it's used and works.

/// <summary>BCrypt implements OpenBSD-style Blowfish password hashing
/// using the scheme described in "A Future-Adaptable Password Scheme"
/// by Niels Provos and David Mazieres.</summary>
/// <remarks>
/// <para>This password hashing system tries to thwart offline
/// password cracking using a computationally-intensive hashing
/// algorithm, based on Bruce Schneier's Blowfish cipher. The work
/// factor of the algorithm is parametized, so it can be increased as
/// computers get faster.</para>
/// <para>To hash a password for the first time, call the
/// <c>HashPassword</c> method with a random salt, like this:</para>
/// <code>
/// string hashed = BCrypt.HashPassword(plainPassword, BCrypt.GenerateSalt());
/// </code>
/// <para>To check whether a plaintext password matches one that has
/// been hashed previously, use the <c>CheckPassword</c> method:</para>
/// <code>
/// if (BCrypt.CheckPassword(candidatePassword, storedHash)) {
///     Console.WriteLine("It matches");
/// } else {
///     Console.WriteLine("It does not match");
/// }
/// </code>
/// <para>The <c>GenerateSalt</c> method takes an optional parameter
/// (logRounds) that determines the computational complexity of the
/// hashing:</para>
/// <code>
/// string strongSalt = BCrypt.GenerateSalt(10);
/// string strongerSalt = BCrypt.GenerateSalt(12);
/// </code>
/// <para>
/// The amount of work increases exponentially (2**log_rounds), so
/// each increment is twice as much work. The default log_rounds is
/// 10, and the valid range is 4 to 31.
/// </para>
/// </remarks>

解决方案

I had the same problem. BCryptHelper.CheckPassword always returns false

I found that the the hashed string was stored in the db as a nchar(). This caused the check to always fail. I changed this to char() and it works.

这篇关于ASP.NET MVC 3应用程序,BCrypt.CheckPassword失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆