2013-12-09 3 views
0

Мне нужен PHP-эквивалент для Java MD5-функциональности, который принимает байтовый массив и возвращает хеш в качестве 16-байтового массива. Мне не нужен Java-эквивалент для функции md5 PHP. Проблема в том, что функция PHP md5 принимает только строки, а не массивы байтов.PHP MD5, эквивалентный Java

Heres ожидаемый результат в Java:

// input byte array 
// for short: 123456 
final byte[] data = new byte[] { (byte) 0x12, (byte) 0x34, (byte) 0x56 }; 

// expected 16 hash bytes 
// for short: ae1fa6209a246b8b2f2cd2d21be8f2e1 
final byte[] expectedHash = new byte[] { 
     (byte) 0xae, (byte) 0x1f, (byte) 0xa6, (byte) 0x20, 
     (byte) 0x9a, (byte) 0x24, (byte) 0x6b, (byte) 0x8b, 
     (byte) 0x2f, (byte) 0x2c, (byte) 0xd2, (byte) 0xd2, 
     (byte) 0x1b, (byte) 0xe8, (byte) 0xf2, (byte) 0xe1 }; 

Моя попытка в РНР:

<?php 
// input byte array 
$data = array(0x12, 0x34, 0x56); 

// pack data in a string, becouse md5 can only 
// compute a hash for a string 
$dataString = pack('C*', $data); // is it the right way? 
var_dump($dataString); 

// compute the hash and get a string back 
$hash = md5($dataString, true); 

// expected 16 hash bytes 
// for short: ae1fa6209a246b8b2f2cd2d21be8f2e1 
$expected = array(
    0xae, 0x1f, 0xa6, 0x20, 
    0x9a, 0x24, 0x6b, 0x8b, 
    0x2f, 0x2c, 0xd2, 0xd2, 
    0x1b, 0xe8, 0xf2, 0xe1); 
var_dump($expected); 

// convert the string back to a byte array 
$actual = unpack('C*', $hash); // is it the right way? 
var_dump($actual); 

assert($expected == $actual); 
?> 

$dataString имеет длину 0. Таким образом, первая ошибка должна быть в pack. Но я не знаю, как упаковать произвольный массив байтов в строку. Можете ли вы дать мне правильный аргумент format?

+0

Вы пытались использовать 'implode'? – christopher

+0

@Chris: Спасибо за подсказку, но implode не возвращает правильную строку: 'implode ('', array (12, 34, 56))' возвращает '123456'. Он преобразует только целочисленные значения в десятичное представление и объединяет их. – Vertex

+0

Вы понимаете, что в PHP «\ x12» - это байт, что означает то же самое, что и Java 0x12, не так ли? Следовательно, «\ x12 \ x34 \ x56» является байтовым массивом, а также является строкой. – SirDarius

ответ

0

Я получил его :)

<?php 
function javaMd5($data) { 
    assert(is_array($data)); 

    $dataString = byteArrayToString($data); 

    $hashString = md5($dataString, true); 
    assert(strlen($hashString) == 16); 

    $hash = stringToByteArray($hashString); 

    assert(count($hash) == 16); 
    return $hash; 
} 

function stringToByteArray($s) { 
    assert(is_string($s)); 

    $result = array_fill(0, strlen($s), 0); 
    for ($i = 0; $i < strlen($s); $i++) { 
     $result[$i] = ord($s[$i]); 
    } 
    return $result; 
} 

function byteArrayToString($b) { 
    assert(is_array($b)); 

    $asciiString = ''; 
    for ($i = 0; $i < count($b); $i++) { 
     assert($b[$i] >= 0 && $b[$i] <= 255); 
     $asciiString .= chr($b[$i]); 
    } 

    $utf8String = utf8_encode($asciiString); 

    return $utf8String; 
} 

$data = array(0x12, 0x34, 0x56); 

$expected = array(
    0xae, 0x1f, 0xa6, 0x20, 
    0x9a, 0x24, 0x6b, 0x8b, 
    0x2f, 0x2c, 0xd2, 0xd2, 
    0x1b, 0xe8, 0xf2, 0xe1); 

$actual = javaMd5($data); 

assert($expected == $actual); 
?> 

I'am не уверен строки кодирования, но это работает. У меня нет объяснений для того, что PHP использует неявную строку, закодированную в xyz, вместо массива explizit byte, такого как Java. Мануэль не говорит о кодировании символов. Это может быть причиной того, что существует так много вопросов о том, как вычислить md5 строки, совместимой с PHP, на языке XYZ.

Смежные вопросы