验证 C# 应用程序在 php 中加密的密码

Verify password encrypted in php by C# application

在我的网站上有一个页面,客户可以在其中存储用于他们购买的应用程序的密码(为了方便起见,通常所有应用程序都使用一个密码)。使用 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 );
}

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

BCryptHelper.CheckPassword(passwordbox.Password, hashFromDb)

然而 returns 错误代码:

An unhandled exception of type 'System.ArgumentException' occurred in DevOne.Security.Cryptography.BCrypt.dll

Additional information: Invalid salt revision

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

BCrypt source code 开始,System.ArgumentException 被这个逻辑抛出:

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

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

From the PHP docspassword_hashPASSWORD_BCRYPT 参数 returns 以 y$ 开头的散列,而 BCrypt 使用的实现C# 期望一个以 a$ 开头的。

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

编辑:this Github thread 有一些关于为什么会发生这种情况的有用信息

扩展方法

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