Trying to reproduce PHP's pack(“H*”) function in C#

陌路散爱 提交于 2021-02-08 05:49:14

问题


this is my code in C# :

    public static String MD5Encrypt(String str, Boolean raw_output=false)
    {
        // Use input string to calculate MD5 hash
        String output;
        MD5 md5 = System.Security.Cryptography.MD5.Create();
        byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(str); 
        byte[] hashBytes = md5.ComputeHash(inputBytes);

        // Convert the byte array to hexadecimal string
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hashBytes.Length; i++)
        {
            sb.Append(hashBytes[i].ToString("x2"));
        }

        output = sb.ToString();

        if (raw_output)
        {
            output = pack(output);
        }

        return output;
    }

    public static String pack(String S)
    {
        string MultiByte = ""; 

        for (int i = 0; i <= S.Length - 1; i += 2)
        {
            MultiByte += Convert.ToChar(HexToDec(S.Substring(i, 2)));
        }

        return MultiByte;
    }

    private static int HexToDec(String hex)
    {
        //Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
        return Convert.ToInt32(hex, 16);
    }

To reproduce what is done in php by this way :

md5($str, true);

OR

pack('H*', md5( $str ));

I tried many things but can't get the same on the two sides in some cases of word. For example, Trying this test on the string "8tv7er5j"

PHP Side :

9c36ad446f83ca38619e12d9e1b3c39e <= md5("8tv7er5j");
œ6­DoƒÊ8ažÙá³Ãž <= md5("8tv7er5j", true) or pack("H*", md5("8tv7er5j"))

C# Side :

9c36ad446f83ca38619e12d9e1b3c39e <= MD5Encrypt("8tv7er5j")
6­DoÊ8aÙá³Ã <= MD5Encrypt("8tv7er5j", true) or pack( MD5Encrypt("8tv7er5j") )

Why ? Encoding problem ?

EDIT 1 : I have the good result, but bad encoded with this this function for pack() :

if ((hex.Length % 2) == 1) hex += '0';

byte[] bytes = new byte[hex.Length / 2];

for (int i = 0; i < hex.Length; i += 2)
{
    bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}

return bytes;

So, System.Text.Encoding.UTF8.GetString(bytes) give me : �6�Do��8a���Þ

And System.Text.Encoding.ASCII.GetString(bytes) ?6?Do??8a??????

...


回答1:


I encountered same scenario where I am in need of php's pack-unpack-md5 functions in C#. Most important was that I need to match out of all these 3 functions with php.

I created my own functions and then validated(verified) my output with functions at onlinephpfunctions.com. The output was same when I parsed with DefaultEncoding. FYI, I checked my application's encoding(Encoding.Default.ToString()) and it was System.Text.SBCSCodePageEncoding

Pack

    private static string pack(string input)
{
    //only for H32 & H*
    return Encoding.Default.GetString(FromHex(input));
}
public static byte[] FromHex(string hex)
{
    hex = hex.Replace("-", "");
    byte[] raw = new byte[hex.Length / 2];
    for (int i = 0; i < raw.Length; i++)
    {
        raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
    }
    return raw;
}

MD5

    private static string md5(string input)
{
    byte[] asciiBytes = Encoding.Default.GetBytes(input);
    byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
    string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
    return hashedString;
}

Unpack

private static string unpack(string p1, string input) { StringBuilder output = new StringBuilder();

    for (int i = 0; i < input.Length; i++)
    {
        string a = Convert.ToInt32(input[i]).ToString("X");
        output.Append(a);
    }

    return output.ToString();
}

PS: User can enhance these functions with other formats




回答2:


I guess that PHP defaults to Latin1 so the code should look like :

public static String PhpMd5Raw(string str)
{
    var md5 = System.Security.Cryptography.MD5.Create();
    var inputBytes = System.Text.Encoding.ASCII.GetBytes(str); 
    var hashBytes = md5.ComputeHash(inputBytes);

    var latin1Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
    return latin1Encoding.GetString(hashBytes);
}



回答3:


If you are going to feed the result as a key for HMAC-SHA1 hashing keep it as bytes[] and initialize the HMACSHA1 with the return value of this function: DO NOT convert it to a string and back to bytes, I have spent hours because of this mistake.

public static byte[] PackH(string hex)
{
    if ((hex.Length % 2) == 1) hex += '0';
    byte[] bytes = new byte[hex.Length / 2];
    for (int i = 0; i < hex.Length; i += 2)
    {
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    }
    return bytes;
}



回答4:


I know this is an old question. I am posting my answer for anyone who might reach this page searching for it. The following code is the full conversion of the pearl function pack("H*") to c#.

public static String Pack(String input)
{
    input = input.Replace("-", " ");
    byte[] hashBytes = new byte[input.Length / 2];
    for (int i = 0; i < hashBytes.Length; i++)
    {
        hashBytes[i] = Convert.ToByte(input.Substring(i * 2, 2), 16);
    }

    return Encoding.UTF7.GetString(hashBytes); // for perl/php
}



回答5:


I'm sorry. I didn't go with the questions completely. But if php code is as below,

$testpack = pack("H*" , "you value");

and if can't read the $testpack values(due to some non support format), then first do base64_encode as below and echo it.

echo base64_encode($testpack);

Then use Risky Pathak answer. For complete this answer I'll post his answer with some small modification like base 64 encoding etc.

            var hex = "you value";
            hex = hex.Replace("-", "");
            byte[] raw = new byte[hex.Length / 2];
            for (int i = 0; i < raw.Length; i++)
            {
                raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            }
            var res = Convert.ToBase64String(raw);
            Console.WriteLine(res);

Now if you compare both of values, those should be similar.

And all credit should go to the Risky Pathak answer.



来源:https://stackoverflow.com/questions/20508193/trying-to-reproduce-phps-packh-function-in-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!