diff --git a/composer.json b/composer.json index e0b5708d..2ce16107 100644 --- a/composer.json +++ b/composer.json @@ -11,9 +11,15 @@ ], "require": { "daita/my-small-php-tools": "dev-master", - "digitalbazaar/json-ld": "0.4.7" + "friendica/json-ld": "^1.0" }, "require-dev": { "jakub-onderka/php-parallel-lint": "^1.0" - } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://git.friendi.ca/friendica/php-json-ld" + } + ] } diff --git a/composer.lock b/composer.lock index cbc4c3a8..39503f78 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "2c21b8c338f3d2f929f349df19edbc0e", + "content-hash": "1fa362334ed7efc57377a715b00b640d", "packages": [ { "name": "daita/my-small-php-tools", @@ -43,22 +43,16 @@ "time": "2018-12-27T11:14:55+00:00" }, { - "name": "digitalbazaar/json-ld", - "version": "0.4.7", + "name": "friendica/json-ld", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/digitalbazaar/php-json-ld.git", - "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/digitalbazaar/php-json-ld/zipball/dc1bd23f0ee2efd27ccf636d32d2738dabcee182", - "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182", - "shasum": "" + "url": "https://git.friendi.ca/friendica/php-json-ld", + "reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1" }, "require": { "ext-json": "*", - "php": ">=5.3.0" + "php": ">=5.4.0" }, "type": "library", "autoload": { @@ -66,27 +60,31 @@ "jsonld.php" ] }, - "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Digital Bazaar, Inc.", - "email": "support@digitalbazaar.com" + "email": "support@digitalbazaar.com", + "homepage": "http://digitalbazaar.com/" + }, + { + "name": "Friendica Team", + "homepage": "https://friendi.ca/" } ], "description": "A JSON-LD Processor and API implementation in PHP.", - "homepage": "https://github.com/digitalbazaar/php-json-ld", + "homepage": "https://git.friendi.ca/friendica/php-json-ld", "keywords": [ + "JSON", "JSON-LD", "Linked Data", "RDF", "Semantic Web", - "json", "jsonld" ], - "time": "2016-04-25T04:17:52+00:00" + "time": "2018-10-08T20:41:00+00:00" } ], "packages-dev": [ diff --git a/lib/Migration/Version0001Date20190103000001.php b/lib/Migration/Version0001Date20190103000001.php new file mode 100644 index 00000000..16f12e3f --- /dev/null +++ b/lib/Migration/Version0001Date20190103000001.php @@ -0,0 +1,118 @@ + + * @copyright 2018, Maxence Lange + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\Social\Migration; + + +use Closure; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\SchemaException; +use Doctrine\DBAL\Types\Type; +use OCA\Social\Db\CoreRequestBuilder; +use OCP\DB\ISchemaWrapper; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + + +/** + * Class Version0001Date20190103000001 + * + * @package OCA\Social\Migration + */ +class Version0001Date20190103000001 extends SimpleMigrationStep { + + + /** @var IDBConnection */ + private $connection; + + + /** @var array */ + public static $editToChar2000 = [ + [CoreRequestBuilder::TABLE_CACHE_ACTORS, 'public_key'] + ]; + + + /** + * @param IDBConnection $connection + */ + public function __construct(IDBConnection $connection) { + $this->connection = $connection; + } + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + * @throws SchemaException + * @throws DBALException + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options + ): ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + foreach (self::$editToChar2000 as $edit) { + list($tableName, $field) = $edit; + + $table = $schema->getTable($tableName); + if ($table->hasColumn($field . '_copy')) { + continue; + } + + $table->addColumn($field . '_copy', Type::TEXT, ['notnull' => false]); + } + + return $schema; + } + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + */ + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { + + foreach (self::$editToChar2000 as $edit) { + list($tableName, $field) = $edit; + + $qb = $this->connection->getQueryBuilder(); + $qb->update($tableName) + ->set($field . '_copy', $field) + ->execute(); + } + } + +} + diff --git a/lib/Migration/Version0001Date20190103000002.php b/lib/Migration/Version0001Date20190103000002.php new file mode 100644 index 00000000..f5ffd60b --- /dev/null +++ b/lib/Migration/Version0001Date20190103000002.php @@ -0,0 +1,75 @@ + + * @copyright 2018, Maxence Lange + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\Social\Migration; + + +use Closure; +use Doctrine\DBAL\Schema\SchemaException; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + + +/** + * Class Version0001Date20190103000002 + * + * @package OCA\Social\Migration + */ +class Version0001Date20190103000002 extends SimpleMigrationStep { + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + * @throws SchemaException + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options + ): ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + foreach (Version0001Date20190103000001::$editToChar2000 as $edit) { + list($tableName, $field) = $edit; + + $table = $schema->getTable($tableName); + if ($table->hasColumn($field) && $table->hasColumn($field . '_copy')) { + $table->dropColumn($field); + } + } + + return $schema; + } + +} + diff --git a/lib/Migration/Version0001Date20190103000003.php b/lib/Migration/Version0001Date20190103000003.php new file mode 100644 index 00000000..06d7b10d --- /dev/null +++ b/lib/Migration/Version0001Date20190103000003.php @@ -0,0 +1,111 @@ + + * @copyright 2018, Maxence Lange + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\Social\Migration; + + +use Closure; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\SchemaException; +use Doctrine\DBAL\Types\Type; +use OCP\DB\ISchemaWrapper; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + + +/** + * Class Version0001Date20190103000003 + * + * @package OCA\Social\Migration + */ +class Version0001Date20190103000003 extends SimpleMigrationStep { + + + /** @var IDBConnection */ + private $connection; + + + /** + * @param IDBConnection $connection + */ + public function __construct(IDBConnection $connection) { + $this->connection = $connection; + } + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + * @throws SchemaException + * @throws DBALException + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options + ): ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + foreach (Version0001Date20190103000001::$editToChar2000 as $edit) { + list($tableName, $field) = $edit; + + $table = $schema->getTable($tableName); + if ($table->hasColumn($field)) { + continue; + } + + $table->addColumn($field, Type::STRING, ['notnull' => false, 'length' => 2000]); + } + + return $schema; + } + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + */ + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { + + foreach (Version0001Date20190103000001::$editToChar2000 as $edit) { + list($table, $field) = $edit; + + $qb = $this->connection->getQueryBuilder(); + $qb->update($table) + ->set($field, $field . '_copy') + ->execute(); + } + } + +} + diff --git a/lib/Migration/Version0001Date20190103000004.php b/lib/Migration/Version0001Date20190103000004.php new file mode 100644 index 00000000..1a51c6ac --- /dev/null +++ b/lib/Migration/Version0001Date20190103000004.php @@ -0,0 +1,77 @@ + + * @copyright 2018, Maxence Lange + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\Social\Migration; + + +use Closure; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\SchemaException; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + + +/** + * Class Version0001Date20190103000004 + * + * @package OCA\Social\Migration + */ +class Version0001Date20190103000004 extends SimpleMigrationStep { + + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + * @throws SchemaException + * @throws DBALException + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options + ): ISchemaWrapper { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + foreach (Version0001Date20190103000001::$editToChar2000 as $edit) { + list($tableName, $field) = $edit; + + $table = $schema->getTable($tableName); + if ($table->hasColumn($field) && $table->hasColumn($field . '_copy')) { + $table->dropColumn($field . '_copy'); + } + } + + return $schema; + } + +} + diff --git a/lib/Model/LinkedDataSignature.php b/lib/Model/LinkedDataSignature.php index 689a5091..abf4406d 100644 --- a/lib/Model/LinkedDataSignature.php +++ b/lib/Model/LinkedDataSignature.php @@ -56,6 +56,9 @@ class LinkedDataSignature implements JsonSerializable { /** @var string */ private $created = ''; + /** @var string */ + private $nonce = ''; + /** @var string */ private $signatureValue = ''; @@ -111,6 +114,26 @@ class LinkedDataSignature implements JsonSerializable { return $this; } + + /** + * @return string + */ + public function getNonce(): string { + return $this->nonce; + } + + /** + * @param string $nonce + * + * @return LinkedDataSignature + */ + public function setNonce(string $nonce): LinkedDataSignature { + $this->nonce = $nonce; + + return $this; + } + + /** * @return string */ @@ -237,19 +260,24 @@ class LinkedDataSignature implements JsonSerializable { $header = [ '@context' => 'https://w3id.org/identity/v1', + 'nonce' => $this->getNonce(), 'creator' => $this->getCreator(), 'created' => $this->getCreated() ]; - $hash = $this->hashedCanonicalize($header) . $this->hashedCanonicalize($this->getObject()); - $signed = base64_decode($this->getSignatureValue()); + $hashHeader = $this->hashedCanonicalize($header, true); + $hashObject = $this->hashedCanonicalize($this->getObject()); $algo = OPENSSL_ALGO_SHA256; if ($this->getType() === 'RsaSignature2017') { $algo = OPENSSL_ALGO_SHA256; } - if (openssl_verify($hash, $signed, $this->getPublicKey(), $algo) === 1) { + $signed = base64_decode($this->getSignatureValue()); + if ($signed !== false + && openssl_verify( + $hashHeader . $hashObject, $signed, $this->getPublicKey(), $algo + ) === 1) { return true; } @@ -259,10 +287,21 @@ class LinkedDataSignature implements JsonSerializable { /** * @param array $data * + * @param bool $removeEmptyValue + * * @return string */ - private function hashedCanonicalize(array $data): string { - $object = json_decode(json_encode($data), false); + private function hashedCanonicalize(array $data, bool $removeEmptyValue = false): string { + if ($removeEmptyValue) { + $data = array_filter( + $data, + function($v) { + return ($v !== ''); + } + ); + } + + $object = json_decode(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); $res = jsonld_normalize( $object, [ @@ -293,6 +332,7 @@ class LinkedDataSignature implements JsonSerializable { $this->setType($this->get('type', $signature, '')); $this->setCreator($this->get('creator', $signature, '')); + $this->setNonce($this->get('nonce', $signature, '')); $this->setCreated($this->get('created', $signature, '')); $this->setSignatureValue($this->get('signatureValue', $signature, ''));