123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- <?php
- class Ppcl {
- public $identifier;
- public $serial;
- public $domains = array();
- public $members = array();
- public $last_modified;
- public $signature;
- public $shared_signature_key;
- public $shared_signature;
- public $publications = array();
- public function from_string($str) {
- $lines = explode("\n", $str);
- $header = explode(" ", $lines[0]);
- if($header[0] != "PPCL") {
- throw new Exception("Header does not start with PPCL magic number", 1);
- }
- $this->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;
- }
- }
- ?>
|