Особенности вычисления хеш-функции crc32b

DeadMorozBLR

Новичок
Особенности вычисления хеш-функции crc32b

Добый день! У меня есть скрипт, который скачивает файлы, режет их на куски и складывает. Встала задача вычисления контрольной суммы CRC32 для того, чтобы ее впоследствии можно было контролировать при сборке файла с помощью Total Commander.

Для вычисления контрольной суммы я воспользовался функциями hash_* и алгоритмом crc32b (он соответствует тому алгоритму, по которому вычисляет CRC32 Total Commander). К моему удивлению, на разных серверах и на разных ОС эта контрольная сумма вычисляется по-разному, а именно, в некоторых случаях порядок байт — обратный тому, который получается при вычислении CRC32 в Total Commander.

Изначально я думал, что обратный порядок байт получается на всех Unix-системах, однако, как показала практика, на разных Linux’ах результаты разные.

Для наглядности я написал скрипт и запустил его на четырех серверах:
PHP:
function is_crc32b_reversed() {
	$hash = hash_init('crc32b');
	hash_update($hash, 'foo');
	$crc32b = hash_final($hash);
	switch ($crc32b) {
		case '8c736521':
			$reverted = false;
			break;
		case '2165738c':
			$reverted = true;
			break;
		default:
			$reverted = null;
			break;
	}
	return $reverted;
}

var_dump(PHP_OS);
var_dump(is_crc32b_reversed());
В итоге получил следующие результаты:

Код:
-- Windows 7
D:\usr\local\php\php.exe -f test-crc32b.php
string(5) "WINNT"
bool(false)

-- Linux (Debian)
$ php -f test-crc32b.php
string(5) "Linux"
bool(true)

-- Linux (Redhat наверное)
$ php -f test-crc32b.php
string(5) "Linux"
bool(false)

-- FreeBSD 6
$ /hsphere/shared/php5/bin/php -f test-crc32b.php
string(7) "FreeBSD"
bool(true)
Есть ли у кого-нибудь соображения, как можно определить по каким-то параметрам системы, какой порядок байт она выдаст в результате расчета? На настоящей момент я перед вычислением выполняю "калибровку" системы функцией выше и после вычисления хеша привожу его к нужному виду.
 

DeadMorozBLR

Новичок
Спасибо, я читал и мануал, и этот тред перед тем, как опубликовать вопрос. И все же: я имею дело не с разным количеством байт в результате и не с разной интерпретацией этих байт как целого числа (signed/unsigned), а с разным порядком байт. Насколько я понимаю, это не то же самое.

Вот здесь что-то похожее я нашел.

Если не сложно, объясните все-таки, в чем дело.

-~{}~ 29.09.09 18:14:

К слову, на обоих Линкусах `uname -m` возвращает "i686", а на FreeBSD —_"i386".

-~{}~ 29.09.09 19:53:

Решено: http://bugs.php.net/bug.php?id=45028
Итого имеем приблизительно:
PHP:
if (version_compare(phpversion(), '5.2.6', '<=')) {
    $crc = substr($crc, 6, 2) . substr($crc, 4, 2) . substr($crc, 2, 2) . substr($crc, 0, 2);
}
Проверил на всех четырёх — работает. Спасибо всем отозвавшимся.
 
Сверху