为什么比.NET / C#实现不同的输出hash_pbkdf2(PHP) [英] Why is the output for hash_pbkdf2 (PHP) different than the .NET / C# implementation

查看:359
本文介绍了为什么比.NET / C#实现不同的输出hash_pbkdf2(PHP)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的一个小项目,我需要计算一个函数的哈希值。

我有PHP哈希的工作示例

  $通=123456;
$ mysalt = strrev($通行证);
回声hash_pbkdf2(SHA1,$传球,$ mysalt,1000,32); //使用PHP内置函数

回声< / BR>中;
include_once('PasswordHash.php');
回声PBKDF2(SHA1,$传球,$ mysalt,1000,16); //使用外部code
 

他们都具有相同的输出: 523d​​904c8f2df96634d9eed3b444838e

现在我需要我的code是落后与生成的密码将通过PHP服务器进行验证C#兼容。并且请求是由一个C#应用程序来发送。

下面是我的尝试:输出= 8e59ead5f90c6af11cf80641d51c241c

 公共静态类节目
{
    公共静态字符串ReverseString(这个字符串s)
    {
        的char [] ARR = s.ToCharArray();
        Array.Reverse(ARR);
        返回新的字符串(ARR);
    }

    静态无效的主要(字串[] args)
    {
        变种通=123456;
        byte []的盐= Encoding.ASCII.GetBytes(pass.ReverseString());


        //https://github.com/defuse/password-hashing/blob/master/PasswordHash.cs
        //越来越错误的盐不是8个字节,
        //http://stackoverflow.com/questions/1647481/what-is-the-c-sharp-equivalent-of-the-php-pack-function
        盐=包(pass.ReverseString());
        VAR哈希= PasswordHash.PBKDF2(通,盐,1000,16);
        Console.WriteLine(BitConverter.ToString(散).Replace( - ,的String.Empty).ToLower());

        Console.ReadKey();

    }

    公共静态byte []的包(字符串盐)
    {
        使用(VAR毫秒=新的MemoryStream())
        {
            使用(VAR体重=新的BinaryWriter(MS))
            {
                VAR数据= Encoding.ASCII.GetBytes(盐);
                bw.Write(data.Length + 4); // ASCII字符串+长度尺寸(4字节INT)
                bw.Write(数据);
            }

            返回ms.ToArray();
        }
    }
}
 

解决方案

这里的问题是与你的盐。只有6个字节长, PHP 处理这种不同,那么你的 C# code。如果您更新code以下内容:

 < PHP
$传球=1234567890;
$ mysalt = strrev($通行证);
回声hash_pbkdf2(SHA1,$传球,$ mysalt,1000,32);
?>
 

你的输出是:42e8bfc7fc5fd4686915d49d5a29bc1e

然后调整 C# code到:

  VAR通=1234567890;
byte []的盐= Encoding.ASCII.GetBytes(pass.ReverseString());

//禁用压缩方法
//盐=包(pass.ReverseString());

VAR哈希= PasswordHash.PBKDF2(通,盐,1000,16);
Console.WriteLine(BitConverter.ToString(散).Replace( - ,的String.Empty).ToLower());

Console.ReadKey();
 

输出结果是:42e8bfc7fc5fd4686915d49d5a29bc1e

的差别来自于你的方法,它随机增加了4个字节的盐。你可以看到,很容易在VS的检查。

所以简单的解决方法是使用这是由你的 C# Rfc2898DeriveBytes $ C> code)和不使用你的方法

如果你看一下 的PHP文档 有一个请求征求意见是提到,盐必须是ATLEAST 8个字节(64位)。因此,使用更少的操作将导致冲突,像你已经遇到过。

更新

现在,如果你真的想使用以&lt安全性较低的盐,8个字节,你可以看看下面的计算器问题 PBKDF2执行在C#与Rfc2898DeriveBytes 了解,这并不需要的最小长度C#版本。

In a small project of mine i need to calculate the hash of a function.

I have a working example of PHP hash

$pass = "123456";
$mysalt = strrev($pass);
echo hash_pbkdf2('sha1', $pass, $mysalt, 1000, 32); //using the PHP inbuilt function

echo "</br>";
include_once('PasswordHash.php');
echo pbkdf2('sha1', $pass, $mysalt, 1000, 16);  //using external code

Both of them has same output : 523d904c8f2df96634d9eed3b444838e

Now i need my code to be backward be compatible with C# generated as the password has will be verified by a PHP server. and the Request is to be sent by a C# application.

Here is what i tried : output = 8e59ead5f90c6af11cf80641d51c241c

public static class Program
{
    public static string ReverseString(this string s)
    {
        char[] arr = s.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }

    static void Main(string[] args)
    {
        var pass = "123456";
        byte[] salt = Encoding.ASCII.GetBytes(pass.ReverseString());


        //https://github.com/defuse/password-hashing/blob/master/PasswordHash.cs
        //was getting error salt not 8 byte,
        //http://stackoverflow.com/questions/1647481/what-is-the-c-sharp-equivalent-of-the-php-pack-function
        salt = Pack(pass.ReverseString());
        var hash = PasswordHash.PBKDF2(pass, salt, 1000, 16);
        Console.WriteLine(BitConverter.ToString(hash).Replace("-", string.Empty).ToLower());

        Console.ReadKey();

    }

    public static byte[] Pack(string salt)
    {
        using (var ms = new MemoryStream())
        {
            using (var bw = new BinaryWriter(ms))
            {
                var data = Encoding.ASCII.GetBytes(salt);
                bw.Write(data.Length + 4); // Size of ASCII string + length (4 byte int)
                bw.Write(data);
            }

            return ms.ToArray();
        }
    }
}

解决方案

The problem here is with your salt. It is only 6 bytes long and PHP handles this different then your c# code. If you update the code to the following:

<?php
$pass = "1234567890";
$mysalt = strrev($pass);
echo hash_pbkdf2('sha1', $pass, $mysalt, 1000, 32);
?>

your output is: 42e8bfc7fc5fd4686915d49d5a29bc1e

Then adjust your c# code to:

var pass = "1234567890";
byte[] salt = Encoding.ASCII.GetBytes(pass.ReverseString());

//DISABLE YOUR PACK METHOD
//salt = Pack(pass.ReverseString());

var hash = PasswordHash.PBKDF2(pass, salt, 1000, 16);
Console.WriteLine(BitConverter.ToString(hash).Replace("-", string.Empty).ToLower());

Console.ReadKey();

The output is: 42e8bfc7fc5fd4686915d49d5a29bc1e

The difference comes from your Pack method, it randomly adds 4 bytes to the salt. You can see that easily in the inspector in VS.

So the easy fix is to use a salt that has atleast 8 chars (minimum for Rfc2898DeriveBytes which is used by your C# code) and dont use your Pack method

If you look at the php docs there is a "Request for comments" that mentions that the salt must be atleast 8bytes (64bit). So using less leads to conflicts, like you already encountered.

UPDATE

Now if you realy want to use the less secure salt with <8 bytes, you can look at the following stackoverflow question PBKDF2 implementation in C# with Rfc2898DeriveBytes for a c# version that doesnt require a minimum length.

这篇关于为什么比.NET / C#实现不同的输出hash_pbkdf2(PHP)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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