private function readSignature()
{
fseek($this->fd, -8, SEEK_END);
$sig = $this->readFormat("Vflags/Z4magic", $this->fd, 8);
$end = ftell($this->fd);
if ($sig["magic"] !== "GBMB") {
throw new Exception("Invalid signature magic value '{$sig["magic"]}");
}
switch ($sig["flags"]) {
case self::SIG_OPENSSL:
fseek($this->fd, -12, SEEK_END);
if ($hash = $this->readSingleFormat("V", $this->fd, 4)) {
$offset = 4 + $hash;
fseek($this->fd, -$offset, SEEK_CUR);
$hash = $this->readVerified($this->fd, $hash);
fseek($this->fd, 0, SEEK_SET);
$valid = openssl_verify($this->readVerified($this->fd, $end - $offset - 8), $hash, @file_get_contents($this->file . ".pubkey")) === 1;
}
break;
case self::SIG_MD5:
case self::SIG_SHA1:
case self::SIG_SHA256:
case self::SIG_SHA512:
$offset = 8 + self::$siglen[$sig["flags"]];
fseek($this->fd, -$offset, SEEK_END);
$hash = $this->readVerified($this->fd, self::$siglen[$sig["flags"]]);
$algo = hash_init(self::$sigalg[$sig["flags"]]);
fseek($this->fd, 0, SEEK_SET);
hash_update_stream($algo, $this->fd, $end - $offset);
$valid = hash_final($algo, true) === $hash;
break;
default:
throw new Exception("Invalid signature type '{$sig["flags"]}");
}
return $sig + compact("hash", "valid");
}