identifier = base64_decode($header[1]); $this->serial = (int)$header[2]; foreach ($lines as $line) { $entry = explode(" ", $line); if($entry[0] == "PPCL") { continue; } if($entry[0] == "SSK") { $this->shared_signature_key = base64_decode($entry[1]); } else if($entry[0] == "DOM") { array_push($this->domains, $entry[1]); } else if($entry[0] == "MEM") { array_push($this->members, new CollectionMember($entry[1], base64_decode($entry[2]), base64_decode($entry[3]), base64_decode($entry[4]))); } else if($entry[0] == "SIG") { $this->signature = base64_decode($entry[1]); } else if($entry[0] == "MOD") { $this->last_modified = new DateTime($entry[1]); } else if($entry[0] == "PUB") { array_push($this->publications, new CollectionPublication($line, $this->members)); } else if($entry[0] == "SSG") { $this->shared_signature = base64_decode($entry[1]); } } // Verify authoritative signature $parts = explode("\nSIG ", $str, 2); $hash = hash("sha512", $parts[0], true); $sig_data = sodium_crypto_sign_open($this->signature, $this->identifier); if($hash != $sig_data) { throw new Exception("Invalid authoritative signature", 1); } // Verify shared signature $parts = explode("\nSSG ", $str, 2); $hash = hash("sha512", $parts[0], true); $sig_data = sodium_crypto_sign_open($this->shared_signature, $this->shared_signature_key); if($hash != $sig_data) { throw new Exception("Invalid shared signature", 1); } } } class CollectionMember { public $name; public $signing_public_key; public $sealing_public_key; public $collection_secret; public function __construct($name, $sign_key, $seal_key, $secret) { $this->name = $name; $this->signing_public_key = $sign_key; $this->sealing_public_key = $seal_key; $this->collection_secret = $secret; } } class CollectionPublication { public $name; public $member_name; public $timestamp; public $signature; public $checksum; public function __construct($line, $members) { $parts = explode(": ", $line, 2); $params = explode(" ", $parts[1]); $this->name = substr($parts[0], 4); $this->member_name = $params[0]; $this->timestamp = new DateTime($params[1]); $this->signature = base64_decode($params[2]); $member = null; foreach($members as $m) { if($m->name == $this->member_name) { $member = $m; break; } } if($member == null) { throw new Exception("PUB entry references member (" . $this->member_name . ") that is not present in the collection", 1); } $hash_data = $this->name . ": " . $this->member_name . " " . $params[1]; $hash = hash("sha512", $hash_data, true); $sig_data = sodium_crypto_sign_open($this->signature, $member->signing_public_key); if(substr($sig_data, 0, 64) != $hash) { throw new Exception("Invalid member signature on publication " . $this->name , 1); } $this->checksum = substr($sig_data, 64, 64); } public function verify_ppub() { $file_hash = hash_file("sha512", PUBLICATION_DIR . "/" . $this->name, true); return $file_hash == $this->checksum; } } ?>