Raketenstartberechtigter: Ein Experiment mit sha512 ... -> hash() vers. hash_file(), Zeit, Speicher

Beitrag lesen

Wenn man den hash eines Dateinhalts als Dateiname benutzt sollte man die PHP-Funktionen md5_file() bzw. sha1_file() benutzen.

Will man den hash als Dateiname (oder nur ermitteln) und soll es ein SHA512-Hash sein, dann ist es definitiv unvorteilhaft, hash( 'sha512', file_get_contents( datei ); zu benutzen. Besser ist es, hier, die Rückgabe des Shell-Befehls openssl sha512 datei zu verwerten.

Das Experiment:

<?php

function myFileHashSHA512( $file ) {

	$openssl = '/usr/bin/openssl';

	if ( is_executable( $openssl ) ) {

		$cmd = $openssl . ' SHA512 < "' . str_replace( '"', '\"', $file ) . '"';
		return trim( str_replace ( '(stdin)= ', '', `$cmd` ) );

	} else {

		trigger_error( "$openssl ist nicht installiert, hash_file('sha512') wurde benutzt", E_USER_NOTICE );
		echo "PHP: hash_file( 'sha512', ${file} )" . PHP_EOL;
		#return hash( 'sha512', file_get_contents( $file ) );
		return hash_file( 'sha512', $file );

	}
}

# 1GB große Datei:
$file = "/home/fastix/vmware/Andere/TrueNAS12/TrueNAS12-s001.vmdk";

echo myFileHashSHA512( $file ) , PHP_EOL;

echo memory_get_peak_usage() , " Bytes benutzt." , PHP_EOL;

Erstes Ergebnis - mit korrektem pfad zu openssl:

time php test.php 
fc5796bf3eb413e54bdf12c3feec6a8733d29487385dd36f5a5cf1600167836a8078d3d588ef6ecb209967e0f7126c763d294e4d32736537f84a97706473bdb1
433560 Bytes benutzt.

real  0m1,708s
user  0m1,557s
sys	  0m0,140s

Zweites Ergebnis - falscher Pfad zu openssl, hash_file() wird benutzt:

fastix@trainer:/tmp$ time php test.php 
PHP Notice:  foo/usr/bin/openssl ist nicht installiert, hash_file('sha512') wurde benutzt in /tmp/test.php on line 14
PHP: hash_file( 'sha512', /home/fastix/vmware/Andere/TrueNAS12/TrueNAS12-s001.vmdk )
fc5796bf3eb413e54bdf12c3feec6a8733d29487385dd36f5a5cf1600167836a8078d3d588ef6ecb209967e0f7126c763d294e4d32736537f84a97706473bdb1
432344 Bytes benutzt.

real  0m3,241s
user  0m3,065s
sys   0m0,164s

Der Hash ist (natürlich) der gleiche - aber die benötigte Zeit unterscheidet sich erheblich: Zumindest derzeit ist das Linux-Programm openssl deutlich schneller als das sehr aktuelle PHP 8.0.5 (cli) (built: May 3 2021 11:30:57) ( NTS ).

Benutzt man die Funktionen

  • md5( file_get_contents( $file ) ),
  • sha1( file_get_contents( $file ) ),
  • hash('sha512', file_get_contents( $file ) )

wird man anhand derAusgaben von memory_get_peak_usage() sehr genau sehen, was man falsch gemacht hat… Damit habe ich es auf bis zu 1109154016 (1.109.154.016 ~ 1 GB statt 430KB) gebracht.

Wer will kann ja auch md5_file() vers. openssl MD5 bzw. openssl SHA1 vers. sha1_file() testen…