tags:

views:

664

answers:

7

I have a series of hex bytes. Theoretically, the last 20 bytes are the sha1 hash of the first part:

3F F4 E5 25 98 20 52 70 01 63 00 68 00 75 00 79 00 69 00 00 00 74 28 96 10 09 9D C9 01 00 74 A0 D7 DB 0B 9D C9 01 4D 00 79 00 47 00 72 00 6F 00 75 00 70 00 00 00 2F 00 00 00 BD 0D EA 71 BE 0B 25 75 E7 5C 58 20 31 57 F3 9A EF 69 1B FD

If I apply sha1 to them in PHP like this:

echo sha1("3FF4E525982052700163006800750079006900000074289610099DC9010074A0D7DB0B9DC9014D007900470072006F007500700000002F000000");

I get back:

d68ca0839df6e5ac7069cc548d82f249752f3acb

But I'm looking for this value:

bd0dea71be0b2575e75c58203157f39aef691bfd  

(BD 0D EA 71 BE 0B 25 75 E7 5C 58 20 31 57 F3 9A EF 69 1B FD)

Is it because I'm treating the hex values as a string? What do I need to do?

Edit:

Here's the original information I am working from:

ticketBytes {byte[0x0000003a]} [0x00000000]: 0x3f [0x00000001]: 0xf4 [0x00000002]: 0xe5 [0x00000003]: 0x25 [0x00000004]: 0x98 [0x00000005]: 0x20 [0x00000006]: 0x52 [0x00000007]: 0x70 [0x00000008]: 0x01 [0x00000009]: 0x63 [0x0000000a]: 0x00 [0x0000000b]: 0x68 [0x0000000c]: 0x00 [0x0000000d]: 0x75 [0x0000000e]: 0x00 [0x0000000f]: 0x79 [0x00000010]: 0x00 [0x00000011]: 0x69 [0x00000012]: 0x00 [0x00000013]: 0x00 [0x00000014]: 0x00 [0x00000015]: 0x74 [0x00000016]: 0x28 [0x00000017]: 0x96 [0x00000018]: 0x10 [0x00000019]: 0x09 [0x0000001a]: 0x9d [0x0000001b]: 0xc9 [0x0000001c]: 0x01 [0x0000001d]: 0x00 [0x0000001e]: 0x74 [0x0000001f]: 0xa0 [0x00000020]: 0xd7 [0x00000021]: 0xdb [0x00000022]: 0x0b [0x00000023]: 0x9d [0x00000024]: 0xc9 [0x00000025]: 0x01 [0x00000026]: 0x4d [0x00000027]: 0x00 [0x00000028]: 0x79 [0x00000029]: 0x00 [0x0000002a]: 0x47 [0x0000002b]: 0x00 [0x0000002c]: 0x72 [0x0000002d]: 0x00 [0x0000002e]: 0x6f [0x0000002f]: 0x00 [0x00000030]: 0x75 [0x00000031]: 0x00 [0x00000032]: 0x70 [0x00000033]: 0x00 [0x00000034]: 0x00 [0x00000035]: 0x00 [0x00000036]: 0x2f [0x00000037]: 0x00 [0x00000038]: 0x00 [0x00000039]: 0x00

hashed {byte[0x00000014]} [0x00000000]: 0xbd [0x00000001]: 0x0d [0x00000002]: 0xea [0x00000003]: 0x71 [0x00000004]: 0xbe [0x00000005]: 0x0b [0x00000006]: 0x25 [0x00000007]: 0x75 [0x00000008]: 0xe7 [0x00000009]: 0x5c [0x0000000a]: 0x58 [0x0000000b]: 0x20 [0x0000000c]: 0x31 [0x0000000d]: 0x57 [0x0000000e]: 0xf3 [0x0000000f]: 0x9a [0x00000010]: 0xef [0x00000011]: 0x69 [0x00000012]: 0x1b [0x00000013]: 0xfd

A: 

This works:

function strToHex($string)
{
    $hex='';
    for ($i=0; $i < strlen($string); $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return $hex;
}
echo sha1(strToHex("3FF4E525982052700163006800750079006900000074289610099DC9010074A0D7DB0B9DC9014D007900470072006F007500700000002F000000"));

>> 5b102a482247fef726843f214f8a81b1627bb634
ryeguy
i am not sure here, but wouldn't you want to iterate the string in reverse order from your example code? something more like: for ($i = strlen($string); $i> 0 ; $i++)
popcnt
No... infinite loop. i will always be larger than 0.
lynn
I think this example is the strangest of all the suggestions. dechex(ord()) seems totally unlogical in this case. ord() converts every single hexcharacter into ascii, which is then converted back to hex. what's the point of that, exactly?
Emil H
every single hexcharacter into the converting ascii code, that is. just to avoid any missunderstandings.
Emil H
+1  A: 
Yossarian
+2  A: 

Unfortunately this doesn't give you the correct value either, but it might point you in the right direction. Either way it's a much better idea to actually convert the hex code to a binary string before hashing it. Like this:

$str = "3F F4 E5 25 98 20 52 70 01 63 00 68 00 75 00 79 00 69 00 00 00 74 28 96 10 09 9D C9 01 00 74 A0 D7 DB 0B 9D C9 01 4D 00 79 00 47 00 72 00 6F 00 75 00 70 00 00 00 2F 00 00 00";

// Create an array where each entry represents a single byte in hex
$arr = explode(" ", $str);
// Convert the hex to decimal
$arr = array_map("hexdec", $arr);
// Convert the decimal number into the corresponding ASCII character
$arr = array_map("chr", $arr);

// Implode the array into a string, and hash the result
$result = sha1(implode($arr));

echo $result."\n";

The result is fa3ebc158305d09443b4315d35c0eee5aa72daef, which is what vartecs code produces as well. I think there's some aspect of how the correct reference is calculated that we don't know, because the approach used here and by vartec is definitely the most logical way to do it based on the facts that we do know.

Emil H
And? What's the output?
Welbog
+2  A: 
$hexes = "3F F4 E5 25 98 20 52 70 01 63 00 68 00 75 00 79 00 69 00 00 00 74 28 96 10 09 9D C9 01 00 74 A0 D7 DB 0B 9D C9 01 4D 00 79 00 47 00 72 00 6F 00 75 00 70 00 00 00 2F 00 00 00";
$hexes = split(' ',$hexes);
$hexes = array_map('hexdec',$hexes);
$hexes = call_user_func_array('pack',array_merge(array('C*'),$hexes));
echo sha1($hexes);

BTW. you can achieve same thing by passing it in another format:

$hexes = "\x3F\xF4\xE5\x25\x98\x20\x52\x70\x01\x63\x00\x68\x00\x75\x00\x79\x00\x69\x00\x00\x00\x74\x28\x96\x10\x09\x9D\xC9\x01\x00\x74\xA0\xD7\xDB\x0B\x9D\xC9\x01\x4D\x00\x79\x00\x47\x00\x72\x00\x6F\x00\x75\x00\x70\x00\x00\x00\x2F\x00\x00\x00";
echo sha1($hexes);
vartec
+2  A: 

Something is very wrong here. SHA1 digests are 160 bits, which is 20 hexadecimal numbers, which is represented by 40 characters. The value you're expecting is 32 characters, which means it's not a SHA1 digest - or something else is missing that I don't yet understand.

Peter Bailey
Sorry about the misinformation, edited question with correct "expected" value.
lynn
+1  A: 

You can use the pack function to convert the hexadecimal string into binary:

$bin = pack('H*', preg_replace('/[^0-9a-fA-F]+/', '', $hex));
Gumbo
This gives me the same results as emil's suggestion.
lynn
A: 

Turned out that I needed to use hash_hmac() with a validation key rather than sha1().

lynn