Start · Sprachen · PHP · Referenz · hash_copy

hash_copy

Funktion

Erstellt eine exakte Kopie eines bestehenden <code>HashContext</code>-Objekts, sodass der aktuelle Hashing-Zwischenzustand unabhängig weiterverwendet werden kann.

seit PHP 5.3.0 Kategorie: crypto

Signatur

hash_copy(HashContext $context): HashContext

Beschreibung

hash_copy() dupliziert einen mit hash_init() erzeugten Hash-Kontext vollständig, einschließlich aller bisher über hash_update() eingespiesenen Daten. Das Ergebnis ist ein neues, unabhängiges HashContext-Objekt, dessen Weiterbearbeitung den Original-Kontext nicht beeinflusst.

Typischer Einsatzfall ist das sogenannte Merkle-Damgård-Pattern: Man verarbeitet zunächst einen gemeinsamen Daten-Prefix (z. B. einen Protokoll-Header), kopiert den Kontext und berechnet danach für verschiedene Nachrichten-Suffixe jeweils den finalen Hash – ohne den Prefix erneut hashen zu müssen. Das spart Rechenzeit bei wiederholten Hashing-Vorgängen mit gleichem Anfang.

Beide Kontexte (Original und Kopie) sind nach hash_copy() völlig unabhängig voneinander und können separat mit hash_update(), hash_update_stream() oder hash_final() weiterverwendet werden.

Seit PHP 7.2 ist HashContext ein echtes Objekt; davor war es eine interne Ressource. hash_copy() funktioniert in beiden Varianten korrekt und war die einzige zuverlässige Methode, einen Ressource-Kontext zu duplizieren, da einfaches Kopieren einer Ressource keinen tiefen Klon erzeugte.

Parameter

Name Typ Default Beschreibung
$context Pflicht HashContext Ein aktiver Hash-Kontext, der zuvor mit hash_init() erzeugt wurde. Der Kontext darf sich in einem beliebigen Zwischenzustand befinden (auch ohne bisher eingespiesene Daten).

Rückgabewert

Typ
HashContext
Beschreibung
Gibt ein neues HashContext-Objekt zurück, das eine vollständige, unabhängige Kopie des übergebenen Kontexts darstellt – inklusive aller bisher verarbeiteten Daten und des aktuellen internen Zustands.

Beispiele

Gemeinsamen Prefix einmal hashen, dann verschiedene Suffixe anhängen

<?php
// Gemeinsamen Prefix vorbereiten
$context = hash_init('sha256');
hash_update($context, 'Gemeinsamer-Prefix:');

// Kontext für zwei verschiedene Nachrichten kopieren
$contextA = hash_copy($context);
$contextB = hash_copy($context);

hash_update($contextA, 'NachrichtA');
hash_update($contextB, 'NachrichtB');

$hashA = hash_final($contextA);
$hashB = hash_final($contextB);

echo 'Hash A: ' . $hashA . PHP_EOL;
echo 'Hash B: ' . $hashB . PHP_EOL;

// Zur Kontrolle: direkter Hash ohne Kontext
$direct = hash('sha256', 'Gemeinsamer-Prefix:NachrichtA');
echo 'Direkt: ' . $direct . PHP_EOL;
echo 'Gleich: ' . ($hashA === $direct ? 'ja' : 'nein') . PHP_EOL;
Hash A: d1e3e6b2f4e... (SHA-256-Hex-String) Hash B: 8a7c3f91a2c... (SHA-256-Hex-String) Direkt: d1e3e6b2f4e... (identisch mit Hash A) Gleich: ja

HMAC-Kontext duplizieren und parallel auswerten

<?php
$secret = 'geheimer-schluessel';

// HMAC-Kontext mit gemeinsamem Datenstück aufbauen
$ctx = hash_init('sha512', HASH_HMAC, $secret);
hash_update($ctx, 'Basis-Payload:');

// Kopie anlegen, bevor sich die Kontexte unterscheiden
$ctx1 = hash_copy($ctx);
$ctx2 = hash_copy($ctx);

hash_update($ctx1, 'Anfrage-1');
hash_update($ctx2, 'Anfrage-2');

$mac1 = hash_final($ctx1);
$mac2 = hash_final($ctx2);

var_dump($mac1 !== $mac2); // true — unterschiedliche MACs
bool(true)

// Wichtig · Fallstricke

Sicherheitshinweis: Das Kopieren eines HMAC-Kontexts ist sicher, solange der geheime Schlüssel niemals direkt exponiert wird. Die Kopie enthält zwar den internen Zustand (inklusive HMAC-Schlüsselverarbeitung), gibt den Schlüssel aber nicht über die PHP-API preis.

Ressourcen vs. Objekte: Vor PHP 7.2 war der Hash-Kontext eine resource. Ein einfaches Zuweisen ($b = $a;) kopierte lediglich den Ressource-Handle, nicht den Zustand. hash_copy() war und ist die einzig korrekte Methode zur Duplizierung.

Kein Rückgabefehler: Die Funktion wirft intern einen ValueError (PHP 8+) oder einen fatalen Fehler (PHP 7), wenn ein ungültiger Kontext übergeben wird. Es gibt keinen false-Rückgabewert – eine Fehlerbehandlung sollte daher per Exception-Handling oder vorheriger Validierung erfolgen.