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

验证C#应用程序在php中加密的密码,c#,php,wpf,encryption,bcrypt,C#,Php,Wpf,Encryption,Bcrypt,在我的网站上有一个页面,客户可以在其中存储密码,以便在他们购买的应用程序中使用(为了方便起见,通常为所有应用程序存储一个密码)。密码是使用PHP代码用bcrypt散列的: if ( $app_pass != '' ){ $mysalt= mcrypt_create_iv(22, MCRYPT_DEV_URANDOM); $options = [ 'cost' => 10, 'salt' => $mysalt,]; $app_pass = password_hash( $a

在我的网站上有一个页面,客户可以在其中存储密码,以便在他们购买的应用程序中使用(为了方便起见,通常为所有应用程序存储一个密码)。密码是使用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 );
}
  • 如果语句为纯文本,则在
    中的
    $app\u pass
  • 之后成为bcrypted散列
  • 然后该散列存储在MySQL数据库中
当客户端在其PC上启动购买的应用程序时,输入登录名和密码,应用程序连接到MySQL数据库,从数据库检索hashFromDb,并尝试使用
BCryptHelper
class验证输入的密码:

BCryptHelper.CheckPassword(passwordbox.Password, hashFromDb)
但它返回错误代码:

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

附加信息:无效的salt版本

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

从系统中,ArgumentException
由以下逻辑引发:

  if (salt[1] != '$') {
        minor = salt[2];
        if (minor != 'a' || salt[3] != '$') {
            throw new ArgumentException("Invalid salt revision");
        }
因此,引发异常的原因似乎是哈希不是
BCrypt
支持的格式

,带有
password\u BCRYPT
参数的
password\u hash
返回一个以
$2y$
开头的哈希值,而
C
使用的
BCRYPT
实现需要一个以
$2a$
开头的哈希值

我建议使用不同的方法来生成散列

编辑:从系统中获得了一些有关发生这种情况的原因的好信息。ArgumentException由以下逻辑引发:

  if (salt[1] != '$') {
        minor = salt[2];
        if (minor != 'a' || salt[3] != '$') {
            throw new ArgumentException("Invalid salt revision");
        }
因此,引发异常的原因似乎是哈希不是
BCrypt
支持的格式

,带有
password\u BCRYPT
参数的
password\u hash
返回一个以
$2y$
开头的哈希值,而
C
使用的
BCRYPT
实现需要一个以
$2a$
开头的哈希值

我建议使用不同的方法来生成散列

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

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();
    }
}
用法

扩展方法

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();
    }
}
用法


很酷

谢谢,这澄清了很多。在您编辑的Github线程之后,我将我的C#应用程序中的
password\u hash
更改为
$2y$
,结果为TRUE。因此,为了避免在C#中硬编码哈希前缀替换,我应该只在服务器端或客户端计算机上设置并验证
密码哈希
,对吗?理想情况下,您希望在客户端生成哈希,并只在服务器端验证。如果您在客户端和webui上都注册,PHP和C#将生成不同的BCrypt哈希。在C#中,只需将$2y$替换为$2a$,散列就可以验证。或者另一种发送密码和验证的方法。@KalebKlein是的,我可以看出替换前缀是有效的,但这是正确的方法吗?至少是有效的方法。
PHP
实现生成具有不同前缀的散列,因为早期版本(使用
$2a$
前缀)存在错误;一旦bug被修复,他们就改变前缀来区分好的和有bug的散列。但是,后端(C#实现)从未出现过此错误,因此它仍然会查找前缀为
$2a$
的哈希值。但是一个固定的(
$2y$
PHP
散列与普通(
$2a$
C#
散列完全相同,因此替换前缀将解决兼容性问题。谢谢,这澄清了很多问题。在您编辑的Github线程之后,我将我的C#应用程序中的
password\u hash
更改为
$2y$
,结果为TRUE。因此,为了避免在C#中硬编码哈希前缀替换,我应该只在服务器端或客户端计算机上设置并验证
密码哈希
,对吗?理想情况下,您希望在客户端生成哈希,并只在服务器端验证。如果您在客户端和webui上都注册,PHP和C#将生成不同的BCrypt哈希。在C#中,只需将$2y$替换为$2a$,散列就可以验证。或者另一种发送密码和验证的方法。@KalebKlein是的,我可以看出替换前缀是有效的,但这是正确的方法吗?至少是有效的方法。
PHP
实现生成具有不同前缀的散列,因为早期版本(使用
$2a$
前缀)存在错误;一旦bug被修复,他们就改变前缀来区分好的和有bug的散列。但是,后端(C#实现)从未出现过此错误,因此它仍然会查找前缀为
$2a$
的哈希值。但是固定的(
$2y$
PHP
散列与普通(
$2a$
C#
散列完全相同,因此替换前缀将解决兼容性问题。请不要定义salt。让
密码\u hash()
为您生成它。PHP7中不推荐使用此参数。请不要定义salt。让
密码\u hash()
为您生成它。PHP7中不推荐使用此参数。