From 1ed3fcf68e932c9d330b305462896b0dd3736331 Mon Sep 17 00:00:00 2001 From: Mike Macgirvin Date: Wed, 3 Jan 2024 11:17:40 +1100 Subject: [PATCH] Remove LD-signatures with extreme bias. --- .gitignore | 3 + Code/Daemon/Notifier.php | 4 +- Code/Lib/ActivityPub.php | 14 +-- Code/Lib/ActivityStreams.php | 49 +++++++-- Code/Lib/JcsEddsa2022.php | 2 + Code/Lib/LDSignatures.php | 98 ----------------- Code/Module/Activity.php | 4 +- Code/Module/Channel.php | 4 +- Code/Module/Dev/Ap_probe.php | 2 +- Code/Module/Directory.php | 4 +- Code/Module/Event.php | 2 +- Code/Module/Followers.php | 2 +- Code/Module/Following.php | 2 +- Code/Module/Home.php | 4 +- Code/Module/Inbox.php | 4 +- Code/Module/Item.php | 4 +- Code/Module/Search.php | 4 +- include/network.php | 162 +--------------------------- tests/bootstrap.php | 9 ++ tests/phpunit.xml | 27 +++++ tests/phpunit.xml.dist | 49 --------- tests/unit/Lib/JcsEddsa2022Test.php | 133 ++++++++++++++++++++++- 22 files changed, 241 insertions(+), 345 deletions(-) delete mode 100644 Code/Lib/LDSignatures.php create mode 100644 tests/bootstrap.php create mode 100644 tests/phpunit.xml delete mode 100644 tests/phpunit.xml.dist diff --git a/.gitignore b/.gitignore index 5e5e2ebc5..bf175b1f9 100755 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,9 @@ nbproject/ *.kdev4 # PHPStorm .idea/ +.phpunit.result.cache +tests/.phpunit.result.cache +tests/.phpunit.cache ## composer diff --git a/Code/Daemon/Notifier.php b/Code/Daemon/Notifier.php index f080313a0..838ca7e9e 100644 --- a/Code/Daemon/Notifier.php +++ b/Code/Daemon/Notifier.php @@ -4,13 +4,13 @@ namespace Code\Daemon; use Code\Lib\Config; use Code\Lib\IConfig; +use Code\Lib\JcsEddsa2022; use Code\Lib\Libzot; use Code\Lib\ObjCache; use Code\Lib\Queue; use Code\Lib\Activity; use Code\Lib\ActivityStreams; use Code\Lib\ActivityPub; -use Code\Lib\LDSignatures; use Code\Lib\Channel; use Code\Extend\Hook; @@ -377,7 +377,7 @@ class Notifier implements DaemonInterface } else { self::$encoded_item = array_merge(Activity::ap_context(), Activity::encode_activity($target_item, true)); - self::$encoded_item['signature'] = LDSignatures::sign(self::$encoded_item, self::$channel); + self::$encoded_item['proof'] = (new JcsEddsa2022)->sign(self::$encoded_item, self::$channel); } logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG); logger('encoded: ' . print_r(self::$encoded_item, true), LOGGER_DEBUG); diff --git a/Code/Lib/ActivityPub.php b/Code/Lib/ActivityPub.php index a4478f27b..6a4940991 100644 --- a/Code/Lib/ActivityPub.php +++ b/Code/Lib/ActivityPub.php @@ -71,7 +71,7 @@ class ActivityPub $msg = array_merge(Activity::ap_context(), $ti); - $msg['signature'] = LDSignatures::sign($msg, $arr['channel']); + $msg['proof'] = (new JcsEddsa2022)->sign($msg, $arr['channel']); logger('ActivityPub_encoded (purge_all): ' . json_encode($msg, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); @@ -106,7 +106,7 @@ class ActivityPub $msg = array_merge(Activity::ap_context(), $ti); - $msg['signature'] = LDSignatures::sign($msg, $arr['channel']); + $msg['proof'] = (new JcsEddsa2022)->sign($msg, $arr['channel']); logger('ActivityPub_encoded: ' . json_encode($msg, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); @@ -278,11 +278,11 @@ class ActivityPub if (intval($x['recipient']['xchan_type']) === XCHAN_TYPE_GROUP) { $join_msg = $msg; $join_msg['type'] = 'Join'; - $join_msg['signature'] = LDSignatures::sign($join_msg, $x['sender']); + $join_msg['proof'] = (new JcsEddsa2022)->sign($join_msg, $x['sender']); $jmsg2 = json_encode($join_msg, JSON_UNESCAPED_SLASHES); } - $msg['signature'] = LDSignatures::sign($msg, $x['sender']); + $msg['proof'] = (new JcsEddsa2022)->sign($msg, $x['sender']); $jmsg = json_encode($msg, JSON_UNESCAPED_SLASHES); $h = q( @@ -346,7 +346,7 @@ class ActivityPub ] ); - $msg['signature'] = LDSignatures::sign($msg, $x['sender']); + $msg['proof'] = (new JcsEddsa2022)->sign($msg, $x['sender']); $jmsg = json_encode($msg, JSON_UNESCAPED_SLASHES); @@ -386,7 +386,7 @@ class ActivityPub ] ); - $msg['signature'] = LDSignatures::sign($msg, $x['sender']); + $msg['proof'] = (new JcsEddsa2022)->sign($msg, $x['sender']); $jmsg = json_encode($msg, JSON_UNESCAPED_SLASHES); $r = q("select * from abook left join hubloc on abook_xchan = hubloc_hash @@ -473,7 +473,7 @@ class ActivityPub ); } - $msg['signature'] = LDSignatures::sign($msg, $channel); + $msg['proof'] = (new JcsEddsa2022)->sign($msg, $channel); $jmsg = json_encode($msg, JSON_UNESCAPED_SLASHES); diff --git a/Code/Lib/ActivityStreams.php b/Code/Lib/ActivityStreams.php index 294e449b7..cfb455699 100644 --- a/Code/Lib/ActivityStreams.php +++ b/Code/Lib/ActivityStreams.php @@ -27,7 +27,7 @@ class ActivityStreams public $origin = null; public $owner = null; public $signer = null; - public $ldsig = null; + public $edsig = null; public $sigok = false; public $recips = null; public $raw_recips = null; @@ -114,15 +114,9 @@ class ActivityStreams $this->replyto = $this->get_property_obj('replyTo'); } - $this->ldsig = $this->get_compound_property('signature'); - if ($this->ldsig) { - $this->signer = $this->get_compound_property('creator', $this->ldsig); - if ( - $this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) - && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem'] - ) { - $this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']); - } + $this->edsig = $this->get_compound_property('proof'); + if ($this->edsig) { + $this->checkEddsaSignature(); } // Implied create activity required by C2S specification if no object is present @@ -509,6 +503,41 @@ class ActivityStreams return $x; } + public function checkEddsaSignature() + { + $signer = $this->get_property_obj('verificationMethod', $this->edsig); + + $parseUrl = parse_url($signer); + if (!empty($parseUrl['fragment']) && str_starts_with($parseUrl['fragment'],'z6Mk')) { + $publicKey = $parseUrl['fragment']; + unset($parseUrl['fragment']); + unset($parseUrl['query']); + } + $url = unparse_url($parseUrl); + $this->signer = [ 'id' => $url ]; + $hublocs = Activity::get_actor_hublocs($url); + $hasStoredKey = false; + if ($hublocs) { + foreach ($hublocs as $hubloc) { + if ($publicKey && $hubloc['xchan_epubkey'] === $publicKey) { + $hasStoredKey = true; + break; + } + } + } + if (! $hasStoredKey) { + $this->signer = Activity::fetch($url); + if ($this->signer + && !empty($this->signer['assertionMethod']) + && !empty($this->signer['assertionMethod']['publicKeyMultibase'])) { + $publicKey = $this->signer['assertionMethod']['publicKeyMultibase']; + } + } + if ($publicKey) { + $this->sigok = (new JcsEddsa2022)->verify($this->data, $publicKey); + } + } + public function debug() : null | string { return var_export($this, true); diff --git a/Code/Lib/JcsEddsa2022.php b/Code/Lib/JcsEddsa2022.php index f8983a10d..0b0ea96f2 100644 --- a/Code/Lib/JcsEddsa2022.php +++ b/Code/Lib/JcsEddsa2022.php @@ -53,6 +53,8 @@ class JcsEddsa2022 logger('verify exception:' . $e->getMessage()); } + logger('SignatureVerify (eddsa-jcs-2022) ' . (($result) ? 'true' : 'false')); + return $result; } diff --git a/Code/Lib/LDSignatures.php b/Code/Lib/LDSignatures.php deleted file mode 100644 index 7e7a9ee44..000000000 --- a/Code/Lib/LDSignatures.php +++ /dev/null @@ -1,98 +0,0 @@ - 'RsaSignature2017', - 'nonce' => random_string(), - 'creator' => Channel::url($channel), - 'created' => datetime_convert('UTC', 'UTC', 'now', 'Y-m-d\TH:i:s\Z') - ]; - - $ohash = self::hash(self::signable_options($options)); - $dhash = self::hash(self::signable_data($data)); - $options['signatureValue'] = base64_encode(Crypto::sign($ohash . $dhash, $channel['channel_prvkey'])); - - return $options; - } - - - public static function signable_data($data): bool|string - { - - $newdata = []; - if ($data) { - foreach ($data as $k => $v) { - if ($k != 'signature') { - $newdata[$k] = $v; - } - } - } - return json_encode($newdata, JSON_UNESCAPED_SLASHES); - } - - - public static function signable_options($options): bool|string - { - - $newopts = ['@context' => 'https://w3id.org/identity/v1']; - if ($options) { - foreach ($options as $k => $v) { - if (!in_array($k, ['type', 'id', 'signatureValue'])) { - $newopts[$k] = $v; - } - } - } - return json_encode($newopts, JSON_UNESCAPED_SLASHES); - } - - public static function hash($obj): string - { - - return hash('sha256', self::normalise($obj)); - } - - public static function normalise($data) - { - if (is_string($data)) { - $data = json_decode($data); - } - - if (!is_object($data)) { - return ''; - } - $d = ''; - jsonld_set_document_loader('jsonld_document_loader'); - try { - $d = jsonld_normalize($data, ['algorithm' => 'URDNA2015', 'format' => 'application/nquads']); - } catch (Exception $e) { - logger('normalise error: ' . $e->getMessage()); - logger('normalise error: ' . print_r($data, true), LOGGER_DATA); - } - return $d; - } -} diff --git a/Code/Module/Activity.php b/Code/Module/Activity.php index 803c0daa3..5e5389235 100644 --- a/Code/Module/Activity.php +++ b/Code/Module/Activity.php @@ -9,7 +9,7 @@ use Code\Lib\ActivityStreams; use Code\Lib\Activity as ZlibActivity; use Code\Lib\Libzot; use Code\Web\HTTPSig; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\ThreadListener; use Code\Lib\Channel; use App; @@ -296,7 +296,7 @@ class Activity extends Controller $headers = []; $headers['Content-Type'] = 'application/x-nomad+json'; - $x['signature'] = LDSignatures::sign($x, $chan); + $x['signature'] = (new JcsEddsa2022)->sign($x, $chan); $ret = json_encode($x, JSON_UNESCAPED_SLASHES); $headers['Digest'] = HTTPSig::generate_digest_header($ret); $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; diff --git a/Code/Module/Channel.php b/Code/Module/Channel.php index 422467407..d144f73b4 100644 --- a/Code/Module/Channel.php +++ b/Code/Module/Channel.php @@ -8,7 +8,7 @@ use Code\Lib\Libzot; use Code\Lib\Activity; use Code\Lib\Libprofile; use Code\Lib\ActivityStreams; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\Crypto; use Code\Lib\PConfig; use Code\Lib as Zlib; @@ -153,7 +153,7 @@ class Channel extends Controller http_status_exit(403, 'Permission denied'); } - as_return_and_die(Activity::encode_person($channel, true, true), $channel, '',false); + as_return_and_die(Activity::encode_person($channel, true, true), $channel); } // handle zot6 channel discovery diff --git a/Code/Module/Dev/Ap_probe.php b/Code/Module/Dev/Ap_probe.php index 56e5b188b..8e546652f 100644 --- a/Code/Module/Dev/Ap_probe.php +++ b/Code/Module/Dev/Ap_probe.php @@ -43,7 +43,7 @@ class Ap_probe extends Controller if (isset($j['type'])) { $AS = new ActivityStreams($j, null, true); if ($AS->is_valid() && isset($AS->data['type'])) { - $html .= EOL . t('LD-Signature: ') . (($AS->sigok) ? 'true' : 'false') . EOL. EOL; + $html .= EOL . t('Eddsa-Signature: ') . (($AS->sigok) ? 'true' : 'false') . EOL. EOL; if (is_array($AS->obj) && isset($AS->obj['type']) && !str_contains($AS->obj['type'], 'Collection') diff --git a/Code/Module/Directory.php b/Code/Module/Directory.php index 07de67ee3..9764eda2c 100644 --- a/Code/Module/Directory.php +++ b/Code/Module/Directory.php @@ -13,7 +13,7 @@ use Code\Lib\Channel; use Code\Lib\Navbar; use Code\Lib\Socgraph; use Code\Lib\XConfig; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Web\HTTPSig; use Code\Extend\Hook; use Code\Render\Theme; @@ -305,7 +305,7 @@ class Directory extends Controller $headers = []; $headers['Content-Type'] = 'application/x-nomad+json'; - $x['signature'] = LDSignatures::sign($x, $chan); + $x['signature'] = (new JcsEddsa2022)->sign($x, $chan); $ret = json_encode($x, JSON_UNESCAPED_SLASHES); $headers['Digest'] = HTTPSig::generate_digest_header($ret); $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; diff --git a/Code/Module/Event.php b/Code/Module/Event.php index c64ecab38..a611315ac 100644 --- a/Code/Module/Event.php +++ b/Code/Module/Event.php @@ -5,7 +5,7 @@ namespace Code\Module; use Code\Web\Controller; use Code\Lib\ActivityStreams; use Code\Lib\Activity; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\Channel; use Code\Web\HTTPSig; diff --git a/Code/Module/Followers.php b/Code/Module/Followers.php index d19637f1b..6a112b953 100644 --- a/Code/Module/Followers.php +++ b/Code/Module/Followers.php @@ -4,7 +4,7 @@ namespace Code\Module; use App; use Code\Lib\ActivityStreams; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\Activity; use Code\Web\HTTPSig; use Code\Web\Controller; diff --git a/Code/Module/Following.php b/Code/Module/Following.php index 4968f8a9c..21927ca7d 100644 --- a/Code/Module/Following.php +++ b/Code/Module/Following.php @@ -4,7 +4,7 @@ namespace Code\Module; use App; use Code\Lib\ActivityStreams; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\Activity; use Code\Web\HTTPSig; use Code\Web\Controller; diff --git a/Code/Module/Home.php b/Code/Module/Home.php index d546407e0..d81bf8e5a 100644 --- a/Code/Module/Home.php +++ b/Code/Module/Home.php @@ -6,7 +6,7 @@ use App; use Code\Lib\Libzot; use Code\Lib\ActivityStreams; use Code\Lib\Activity; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\Crypto; use Code\Web\HTTPSig; use Code\Web\Controller; @@ -31,7 +31,7 @@ class Home extends Controller $headers = []; $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'; - $x['signature'] = LDSignatures::sign($x, ['channel_address' => z_root(), 'channel_prvkey' => get_config('system', 'prvkey')]); + $x['signature'] = (new JcsEddsa2022)->sign($x, ['channel_address' => z_root(), 'channel_prvkey' => get_config('system', 'prvkey')]); $ret = json_encode($x, JSON_UNESCAPED_SLASHES); logger('data: ' . jindent($ret), LOGGER_DATA); $headers['Date'] = datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T'); diff --git a/Code/Module/Inbox.php b/Code/Module/Inbox.php index 0cfa4837c..372a85b13 100644 --- a/Code/Module/Inbox.php +++ b/Code/Module/Inbox.php @@ -138,9 +138,7 @@ class Inbox extends Controller $v = Activity::get_actor_hublocs($AS->actor['id']); if ($v && $v[0]['hubloc_hash'] !== $hsig['portable_id']) { - // The sender is not actually the activity actor, so verify the LD signature. - // litepub activities (with no LD signature) will always have a matching actor and sender - + // The sender is not actually the activity actor, so verify the object signature. if ($AS->signer && is_array($AS->signer) && $AS->signer['id'] !== $AS->actor['id']) { // the activity wasn't signed by the activity actor return; diff --git a/Code/Module/Item.php b/Code/Module/Item.php index 392b726d7..ae0a2811b 100644 --- a/Code/Module/Item.php +++ b/Code/Module/Item.php @@ -22,7 +22,7 @@ namespace Code\Module; use Code\Lib\Libsync; use Code\Lib\Activity; use Code\Lib\ActivityStreams; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Web\HTTPSig; use Code\Web\Controller; use Code\Lib\Libzot; @@ -310,7 +310,7 @@ class Item extends Controller $headers = []; $headers['Content-Type'] = 'application/x-nomad+json'; - $x['signature'] = LDSignatures::sign($x, $chan); + $x['signature'] = (new JcsEddsa2022)->sign($x, $chan); $ret = json_encode($x, JSON_UNESCAPED_SLASHES); $headers['Digest'] = HTTPSig::generate_digest_header($ret); $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; diff --git a/Code/Module/Search.php b/Code/Module/Search.php index 1c4b265ac..2146bcb1d 100644 --- a/Code/Module/Search.php +++ b/Code/Module/Search.php @@ -8,7 +8,7 @@ use Code\Lib\Activity; use Code\Lib\ActivityStreams; use Code\Lib\ASCollection; use Code\Lib\Channel; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\Libprofile; use Code\Lib\Libzot; use Code\Lib\Navbar; @@ -369,7 +369,7 @@ class Search extends Controller $headers = []; $headers['Content-Type'] = 'application/x-nomad+json'; - $x['signature'] = LDSignatures::sign($x, $chan); + $x['signature'] = (new JcsEddsa2022)->sign($x, $chan); $ret = json_encode($x, JSON_UNESCAPED_SLASHES); $headers['Digest'] = HTTPSig::generate_digest_header($ret); $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; diff --git a/include/network.php b/include/network.php index 7969962cb..72c025e9f 100644 --- a/include/network.php +++ b/include/network.php @@ -9,7 +9,7 @@ use Code\Lib\Activity; use Code\Lib\ActivityPub; use Code\Lib\Queue; use Code\Lib\System; -use Code\Lib\LDSignatures; +use Code\Lib\JcsEddsa2022; use Code\Lib\Addon; use Code\Lib\Url; use Code\Web\HTTPSig; @@ -21,15 +21,11 @@ use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\Exception; - -require_once('library/jsonld/jsonld.php'); /** * @file include/network.php * @brief Network related functions. */ - - function json_return_and_die($x, $content_type = 'application/json', $debug = false) { header("Content-type: $content_type"); @@ -40,7 +36,7 @@ function json_return_and_die($x, $content_type = 'application/json', $debug = fa killme(); } -function as_return_and_die($obj, $channel, $contextType = null, $ldsign = true) +function as_return_and_die($obj, $channel, $contextType = null, $signObject = true) { if (! is_array($obj)) { @@ -52,8 +48,8 @@ function as_return_and_die($obj, $channel, $contextType = null, $ldsign = true) $headers = []; $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ; - if ($ldsign) { - $data['signature'] = LDSignatures::sign($data, $channel); + if ($signObject) { + $data['proof'] = (new JcsEddsa2022)->sign($data, $channel); } $json = json_encode($data, JSON_UNESCAPED_SLASHES); logger('data: ' . jindent($json), LOGGER_DATA); @@ -1436,156 +1432,6 @@ function getBestSupportedMimeType($mimeTypes = null, $acceptedTypes = false) return null; } -/** - * @brief Perform caching for jsonld normaliser. - * - * @param string $url - * @return mixed|bool|array - */ -function jsonld_document_loader($url) -{ - $doc = (object) [ 'contextUrl' => null, 'document' => null, 'documentUrl' => $url]; - $recursion = 0; - - $builtins = [ - 'https://www.w3.org/ns/activitystreams' => 'library/w3org/activitystreams.jsonld', - 'https://w3id.org/identity/v1' => 'library/w3org/identity-v1.jsonld', - 'https://w3id.org/security/v1' => 'library/w3org/security-v1.jsonld', - ]; - - $x = debug_backtrace(); - if ($x) { - foreach ($x as $n) { - if ($n['function'] === __FUNCTION__) { - $recursion++; - } - } - } - if ($recursion > 5) { - logger('jsonld bomb detected at: ' . $url); - killme(); - } - - $cachepath = 'cache/ldcache'; - if (! is_dir($cachepath)) { - Stdio::mkdir($cachepath, STORAGE_DEFAULT_PERMISSIONS, true); - } - - $filename = ''; - - foreach ($builtins as $key => $value) { - if ($url === $key) { - $doc->document = file_get_contents($value); - return $doc; - } - } - - if (! $filename) { - $filename = $cachepath . '/' . urlencode($url); - } - - if (file_exists($filename) && filemtime($filename) > time() - (12 * 60 * 60)) { - logger('loading ' . $filename . ' from recent cache'); - return file_get_contents($filename); - } - - $r = jsonld_default_document_loader($url); - if ($r) { - if (!in_array($url, $builtins)) { - file_put_contents($filename, json_encode($r)); - } - return $r; - } - - if (file_exists($filename)) { - logger('loading ' . $filename . ' from longterm cache'); - return file_get_contents($filename); - } - else { - logger($filename . ' does not exist and cannot be loaded'); - } - - return $doc; -} - - -/** - * @brief Perform caching for jsonld normaliser. - * - * @param string $url - * @return mixed|bool|array - */ -function hz_jsonld_document_loader($url) { - $doc = (object) [ - 'contextUrl' => null, - 'document' => null, - 'documentUrl' => $url - ]; - - $recursion = 0; - - $builtins = [ - 'https://www.w3.org/ns/activitystreams' => 'library/w3org/activitystreams.jsonld', - 'https://w3id.org/identity/v1' => 'library/w3org/identity-v1.jsonld', - 'https://w3id.org/security/v1' => 'library/w3org/security-v1.jsonld', - ]; - - $x = debug_backtrace(); - if ($x) { - foreach ($x as $n) { - if ($n['function'] === __FUNCTION__) { - $recursion++; - } - } - } - - if ($recursion > 5) { - logger('jsonld bomb detected at: ' . $url); - killme(); - } - - foreach ($builtins as $key => $value) { - if ($url === $key) { - $doc->document = file_get_contents($value); - return $doc; - } - } - - $cachepath = 'store/[data]/[jsonld]'; - if(!is_dir($cachepath)) { - os_mkdir($cachepath, STORAGE_DEFAULT_PERMISSIONS, true); - } - - $filename = $cachepath . '/' . urlencode($url); - - if (file_exists($filename) && filemtime($filename) > time() - (12 * 60 * 60)) { - logger('loading ' . $filename . ' from recent cache'); - return json_decode(file_get_contents($filename)); - } - - $r = jsonld_default_document_loader($url); - if ($r) { - if (!in_array($url, $builtins)) { - $cache_obj = $r; - // To prevent double encoding we need to decode $cache_obj->document - // before encoding the whole object for storage. - $cache_obj->document = json_decode($cache_obj->document); - file_put_contents($filename, json_encode($cache_obj)); - } - return $r; - } - - if (file_exists($filename)) { - logger('loading ' . $filename . ' from longterm cache'); - return json_decode(file_get_contents($filename)); - } - else { - logger($filename . ' does not exist and cannot be loaded'); - } - - return $doc; -} - function is_https_request() { diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 000000000..4f956795c --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,9 @@ + + + + + ../tests + + + + + + . + + + diff --git a/tests/phpunit.xml.dist b/tests/phpunit.xml.dist deleted file mode 100644 index 982607080..000000000 --- a/tests/phpunit.xml.dist +++ /dev/null @@ -1,49 +0,0 @@ - - - - ./unit/ - - - ./unit/ - - - - - - - postgresql - - - - - - ../Code/ - ../include/ - - - - - - - - - - - - - - - - - - diff --git a/tests/unit/Lib/JcsEddsa2022Test.php b/tests/unit/Lib/JcsEddsa2022Test.php index 1e4100766..ca6df1d2f 100644 --- a/tests/unit/Lib/JcsEddsa2022Test.php +++ b/tests/unit/Lib/JcsEddsa2022Test.php @@ -3,9 +3,10 @@ namespace Code\Tests\Unit\Lib; use Code\Lib\JcsEddsa2022; +use Code\Tests\Unit\UnitTestCase; -class JcsEddsa2022Test extends \Code\Tests\Unit\UnitTestCase +class JcsEddsa2022Test extends UnitTestCase { public function testVerifyFromSpec() @@ -46,4 +47,132 @@ class JcsEddsa2022Test extends \Code\Tests\Unit\UnitTestCase } -} \ No newline at end of file + public function testSignAndVerify() + { + $publicKey = 'z6MkfpucGTDbMZADwM6vEa8pS3s8Z9xqSEn6HihijZ4fVs9d'; + $channel = [ + 'channel_url' => 'https://example.com/channel/klingon', + 'channel_epubkey' => 'FGdbYgr526Swuyya3e8epCBdHahlWNg9I0sBhMKCzpw', + 'channel_eprvkey' => 'StLRo8xb7VJ5XdR10OUYQM/uooP7D7fMlgvQFa1wrZIUZ1tiCvnbpLC7LJrd7x6kIF0dqGVY2D0jSwGEwoLOnA', + 'channel_address' => 'klingon@example.com', + 'channel_system' => false, + ]; + + $document = '{ + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1", + { + "nomad": "https://example.com/apschema#", + "toot": "http://joinmastodon.org/ns#", + "litepub": "http://litepub.social/ns#", + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "oauthRegistrationEndpoint": "litepub:oauthRegistrationEndpoint", + "sensitive": "as:sensitive", + "movedTo": "as:movedTo", + "discoverable": "toot:discoverable", + "indexable": "toot:indexable", + "capabilities": "litepub:capabilities", + "acceptsJoins": "litepub:acceptsJoins", + "Hashtag": "as:Hashtag", + "canReply": "toot:canReply", + "canSearch": "nomad:canSearch", + "approval": "toot:approval", + "expires": "nomad:expires", + "directMessage": "nomad:directMessage", + "Category": "nomad:Category", + "copiedTo": "nomad:copiedTo", + "searchContent": "nomad:searchContent", + "searchTags": "nomad:searchTags" + } + ], + "type": "Person", + "id": "https://example.com/channel/klingon", + "preferredUsername": "klingon", + "name": "klingon", + "created": "2023-07-13T20:23:32Z", + "updated": "2023-07-13T20:23:32Z", + "icon": { + "type": "Image", + "mediaType": "image/png", + "updated": "2023-07-13T20:23:32Z", + "url": "https://example.com/photo/profile/l/2", + "height": 300, + "width": 300 + }, + "url": "https://example.com/channel/klingon", + "tag": [ + { + "type": "Note", + "name": "Protocol", + "content": "zot6" + }, + { + "type": "Note", + "name": "Protocol", + "content": "nomad" + }, + { + "type": "Note", + "name": "Protocol", + "content": "activitypub" + } + ], + "inbox": "https://example.com/inbox/klingon", + "outbox": "https://example.com/outbox/klingon", + "followers": "https://example.com/followers/klingon", + "following": "https://example.com/following/klingon", + "wall": "https://example.com/outbox/klingon", + "endpoints": { + "sharedInbox": "https://example.com/inbox", + "oauthRegistrationEndpoint": "https://example.com/api/client/register", + "oauthAuthorizationEndpoint": "https://example.com/authorize", + "oauthTokenEndpoint": "https://example.com/token", + "searchContent": "https://example.com/search/klingon?search={}", + "searchTags": "https://example.com/search/klingon?tag={}" + }, + "discoverable": true, + "canSearch": [], + "indexable": false, + "publicKey": { + "id": "https://example.com/channel/klingon?operation=rsakey", + "owner": "https://example.com/channel/klingon", + "signatureAlgorithm": "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + "publicKeyPem": "-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA+LXyOD/bzzVgM/nUOJ5m +c4WrQPMlhKqWJvKrumdQw9JJYcyaZp/jmMxDx/w/EwVw+wnV5wZcD0yBVhC7NPRa +nYc5OfNhS4MO74xgZrj+VWSTzNo3YooS/dEIIvsu6bhxfooHj17SA6pMRnZkkVpk +ykpPRYwJw+NvKcRwzpF06rxMqjZ+Bp0ea/X37j4cHaosRoQTJiHmMKKnpByKdImF +TR1juJ69ASh6nh8YVGcz6fz1jBQZPMx05tfNdyN5oZRTr8Nug2CiF3V7yKKS14HD +kE9eeFeTMt58Qi+8kprATYxKrlIuTZmI4YdIRgtM+tPQsosKTFmjzbef4dYooutv +T7XfrE+wYVZlx2pkaeFiKrJVacpmmFJe8zCIFXrofq1aOagU1kpwnXgjneCttA+M +OJ3Y+cPamdfRQDtsBcokJUD40RTwux6OGW9zqkJIpniVB+CZu4nTOHCzMJwbxF0p +JmGZd9kc3PR6Uf/IHAb1xeyTi4FyyYTbRDYuJyqRKbe880QUwgCBcogIbNy4xxsH +UTMy0ucWaDSBRahKUIHl3FRglvnI754NJSXBDIQOwC9oRRH27Vmm1Jy8sltmFLFr +ENJCGgOH8Bhpk+y1jtw1jpTig76wIvw+6zQtgNSfPnrNGIHt5mcoy4pFFXLv2lK2 +/u26hUGQAq71Ra0DwgXIWFECAwEAAQ== +-----END PUBLIC KEY----- +" + }, + "assertionMethod": [ + { + "id": "https://example.com/channel/klingon#z6MkfpucGTDbMZADwM6vEa8pS3s8Z9xqSEn6HihijZ4fVs9d", + "type": "Multikey", + "controller": "https://example.com/channel/klingon", + "publicKeyMultibase": "z6MkfpucGTDbMZADwM6vEa8pS3s8Z9xqSEn6HihijZ4fVs9d" + } + ], + "manuallyApprovesFollowers": true +}'; + + $algorithm = new JcsEddsa2022(); + $documentArray = json_decode($document,true); + $documentArray['proof'] = $algorithm->sign($documentArray, $channel); + + $verified = (new JcsEddsa2022())->verify($documentArray, $publicKey); + $this->assertTrue($verified, 'Verify encode and decode eddsa-jcs-2022'); + + } +}