Como faço para sha1 valores de hash hexadecimais corretamente em PHP?
Pergunta
Eu tenho uma série de bytes hexadecimais. Teoricamente, os últimos 20 bytes são o hash SHA1 da primeira parte:
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
Se eu aplicar sha1 a eles em PHP como este:
echo sha1("3FF4E525982052700163006800750079006900000074289610099DC9010074A0D7DB0B9DC9014D007900470072006F007500700000002F000000");
eu voltar:
d68ca0839df6e5ac7069cc548d82f249752f3acb
Mas eu estou olhando para este valor:
bd0dea71be0b2575e75c58203157f39aef691bfd
(BD 0D EA 71 BE 0B 25 75 E7 5C 58 20 31 57 F3 9A EF 69 1B FD)
É porque eu estou tratando os valores hexadecimais como uma string? O que eu preciso fazer?
Editar:
Aqui está a informação original Eu estou trabalhando em:
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
Solução
Algo está muito errado aqui. são 160 bits, que é de 20 números hexadecimais, que é representado pela 40 caracteres. O valor que você está esperando é de 32 caracteres, o que significa que não é um SHA1 -. Ou qualquer outra coisa está faltando que eu ainda não entendo
Outras dicas
Infelizmente, isso não lhe dá o valor correto seja, mas pode apontar na direção certa. De qualquer maneira é uma idéia muito melhor para realmente converter o código hexadecimal para uma cadeia binária antes de hash-lo. Como esta:
$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";
O resultado é fa3ebc158305d09443b4315d35c0eee5aa72daef, que é o que vartecs código produz bem. Eu acho que há algum aspecto de como a referência correta calcula-se que nós não sabemos, porque a abordagem utilizada aqui e por vartec é definitivamente o caminho mais lógico para fazê-lo com base nos fatos que nós sabemos.
$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. você pode conseguir mesmo passando-o em outro formato:
$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);
Você pode usar o pack
função para converter a seqüência hexadecimal em binário:
$bin = pack('H*', preg_replace('/[^0-9a-fA-F]+/', '', $hex));
convertê-los em string usando chr()
..
$string = "3f ........"
$c = split(' ',$string);
$string2 = '';
foreach( $c as $char )
{
$string2 .= chr(hexdec($c));
}
echo sha1($string2);
Isso funciona:
function strToHex($string)
{
$hex='';
for ($i=0; $i < strlen($string); $i++)
{
$hex .= dechex(ord($string[$i]));
}
return $hex;
}
echo sha1(strToHex("3FF4E525982052700163006800750079006900000074289610099DC9010074A0D7DB0B9DC9014D007900470072006F007500700000002F000000"));
>> 5b102a482247fef726843f214f8a81b1627bb634
Acabou que eu precisava usar hash_hmac () com uma chave de validação ao invés de sha1 ().