【问题标题】:Verify password encrypted in php by C# application验证 C# 应用程序在 php 中加密的密码
【发布时间】:2015-12-07 04:12:27
【问题描述】:

在我的网站上有一个页面,客户可以在其中存储用于他们购买的应用程序的密码(为了方便起见,通常所有应用程序都使用一个密码)。使用 PHP 代码使用 bcrypt 对密码进行哈希处理:

if ( $app_pass != '' ){
  $mysalt= mcrypt_create_iv(22, MCRYPT_DEV_URANDOM);
  $options = [ 'cost' => 10, 'salt' => $mysalt,];
  $app_pass = password_hash( $app_pass, PASSWORD_BCRYPT, $options );
}
  • if 语句中的$app_pass 是纯文本
  • 后来变成bcrypted hash
  • 然后将该哈希值存储在 MySQL 数据库中

当客户在他的 PC 上开始购买应用程序,输入登录名和密码,应用程序连接到 MySQL 数据库,检索 hashFromDb 并尝试使用BCryptHelper 类验证输入的密码:

BCryptHelper.CheckPassword(passwordbox.Password, hashFromDb)

但它返回错误代码:

在 DevOne.Security.Cryptography.BCrypt.dll 中发生“System.ArgumentException”类型的未处理异常

附加信息:无效的盐修订版

在 WPF 应用程序中根据 PHP 加密密码哈希验证用户输入的密码是否正确?

【问题讨论】:

  • 请不要定义盐。让password_hash() 为您生成它。此参数在 PHP 7 中已弃用。

标签: c# php wpf encryption bcrypt


【解决方案1】:

BCrypt source codeSystem.ArgumentException 被这个逻辑抛出:

  if (salt[1] != '$') {
        minor = salt[2];
        if (minor != 'a' || salt[3] != '$') {
            throw new ArgumentException("Invalid salt revision");
        }

因此,似乎抛出异常是因为哈希不是BCrypt 支持的格式。

From the PHP docs, password_hashPASSWORD_BCRYPT 参数返回一个以$2y$ 开头的哈希,而C# 使用的BCrypt 实现期望以$2a$ 开头。

我建议使用不同的方法来生成哈希。

编辑:this Github thread 有一些很好的信息说明为什么会发生这种情况

【讨论】:

  • 谢谢,这说明了很多。在您编辑的 Github 线程之后,我将 C# 应用程序 $2y$ 中的 password_hash 更改为 $2a$,它给出了 TRUE。因此,为了避免在 C# 中硬编码哈希前缀替换,我应该只在服务器端或客户端机器上设置和验证 password_hash,对吧?
  • 理想情况下,您会希望在客户端生成哈希,并仅在服务器端进行验证。
  • 如果你在客户端和 webui 上都有注册,PHP 和 C# 会生成不同的 BCrypt 哈希。在 C# 中,只需将 $2y$ 替换为 $2a$ 即可验证哈希值。或者反过来发送密码和验证。
  • @KalebKlein 是的,我可以看到替换前缀有效,但它是正确的方法吗?
  • 这至少是一种工作方式。 PHP 实现生成具有不同前缀的哈希,因为早期版本(使用 $2a$ 前缀)有一个错误;修复错误后,他们更改了前缀以区分好哈希和错误哈希。然而,后端(C# 实现)从来没有这个错误,所以它仍然会寻找带有$2a$ 前缀的哈希。但是固定的 ($2y$) PHP 哈希与普通的 ($2a$) C# 哈希完全相同,因此替换前缀将解决兼容性问题。
【解决方案2】:

扩展方法

static class ExtentionMetsodString
{
    public static string ReplaceAt(this string str,int startIdx , string replaceStr)
    {
        StringBuilder strBuilder = new StringBuilder(str);
        int length = replaceStr.Length;

        strBuilder.Remove(startIdx, length);
        strBuilder.Insert(startIdx, replaceStr);
        return strBuilder.ToString();
    }
}

用法

string test = "0123456";
string output = test.ReplaceAt(2, "ab"); // ouput : 01ab456

【讨论】:

    猜你喜欢
    • 2020-03-04
    • 2012-01-22
    • 2011-08-29
    • 1970-01-01
    • 2015-05-18
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多