Public append-only ledger microservice built with Slim Framework

Overview

Chronicle

Build Status Latest Stable Version Latest Unstable Version License

Chronicle is a self-hostable microservice, built with Slim Framework, which enables authorized users to commit arbitrary data to an immutable, append-only public ledger.

Chronicle is superior to "blockchain" solutions for most real-world technical problems that don't involve proofs-of-work or Byzantine fault tolerance.

More precisely, Chronicle is a self-hostable microservice exposing an append-only, cryptographically-secure hash chain data structure that accepts arbitrary data from authorized clients through an HTTP API, secured by Sapient, that can be used as a building block for building a cryptographic audit trail similar to Certificate Transparency.

Chronicle will make you question the need for blockchain technology.

Chronicle was developed by Paragon Initiative Enterprises as part of our continued efforts to make the Internet more secure.

Getting Started with Chronicle (Documentation)

Client-Side Software that Interacts with Chronicle

PHP

What does Chronicle do?

Chronicle allows trusted clients to send data to be included in an immutable, auditable, cryptographic permanent record.

Furthermore, Chronicle has cross-signing and many-to-one replication built-in, which, when used, greatly enhances the auditability and availability of the data written to your local Chronicle instance.

What problems do Chronicle solve?

Chain of Custody

If you have sensitive information, you can write metadata about client access times to a private Chronicle in order to have verifiable, tamper-resistant proof that specific records were accessed by specific user accounts at a specific time.

Proof of Knowledge

By inserting an encrypted message and then revealing the key at a later date, you can provide strong evidence of prior knowledge.

Userbase Consistency Verification

For building a secure code delivery system, committing some metadata and a SHA256 or BLAKE2 hash of each update file to a publicly verifiable Chronicle allows users to compile a whitelist of known update files to help block trojan horse malware (in the event of a compromised update server).

For best results, combine with cryptographic signatures (which may also be registered in the Chronicle) and reproducible builds.

Auditable Security Event Logging

Because of Chronicle's cryptographically assured append-only properties, and its use of modern elliptic curve digital signatures, Chronicle is a good fit for integrating with SIEM solutions and internal SOCs.

How does it work?

All communications are secured with Sapient. Sapient ensures that all published messages are signed with Ed25519. All messages are committed to a hash chain data structure backed by BLAKE2b, which we call Blakechain for short.

There are two hashes for each message:

  1. The hash of the current message, whose BLAKE2b key is the previous message's block. This is just called currhash internally.
  2. The summary hash, which is a BLAKE2b hash of all message hashes to date, concatenated together in order. This is called summaryhash internally.

The rationale for using the previous message's hash was to add a degree of domain separation in the event that a BLAKE2b collision attack is ever discovered. The keying should reduce the likelihood of any practical attacks, especially if the chain is updated rapidly.

Comments
  • Uncaught ParagonIE\EasyDB\Exception\ConstructorFailed: Could not create a PDO connection

    Uncaught ParagonIE\EasyDB\Exception\ConstructorFailed: Could not create a PDO connection

    Sorry, but am I missing something stupid here ?

    Fatal error: Uncaught ParagonIE\EasyDB\Exception\ConstructorFailed: Could not create a PDO connection. Please check your username and password. in /blah/chronicle/vendor/paragonie/easydb/src/Factory.php:65

    local/settings.json is as per your example:

        "database": {
            "dsn": "pgsql:host=myhost;port=5432;dbname=mydb",
            "username": "myuser",
            "password": "mypass"
        }
    

    and....

    psql -U myuser -d mydb -h myhost -W

    works just fine (i.e. pg_hba is correctly setup and reloaded, I can manipulate stuff as the user etc. ), and....

    No errors are recorded in the postgres logs.

    and .....

    I know postgres connections work just fine from this machine because I've got other PHP stuff on there accessing the same postgres server. So there's no firewalls or other stuff going on.

    This is postgres 9.6.8 and php 7.2.4.

    opened by udf2457 9
  • Replication failing

    Replication failing

    I'm back :)

    The replication is failing with the folowing error:

    PHP Notice:  Undefined index: summary in /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Process/Replicate.php on line 183
    PHP Warning:  hash_equals(): Expected known_string to be a string, null given in /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Process/Replicate.php on line 183
    PHP Notice:  Undefined index: summary in /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Process/Replicate.php on line 186
    PHP Fatal error:  Uncaught ParagonIE\Chronicle\Exception\SecurityViolation: Invalid summary hash. Expected , calculated g_uhhZBFE4iP-k9rPx_TyzdJz6NYfgZYQetvThhAo8M= in /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Process/Replicate.php:185
    Stack trace:
    #0 /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Process/Replicate.php(116): ParagonIE\Chronicle\Process\Replicate->appendToChain(Array)
    #1 /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Scheduled.php(129): ParagonIE\Chronicle\Process\Replicate->replicate()
    #2 /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Scheduled.php(86): ParagonIE\Chronicle\Scheduled->doReplication()
    #3 /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Scheduled.php(60): ParagonIE\Chronicle\Scheduled->runAll()
    #4 /var/www/vhosts/example.com/chronicle.example.com/bin/scheduled-tasks.php(36): ParagonIE\Chronicle\Scheduled->run()
    #5 {main}
      thrown in /var/www/vhosts/example.com/chronicle.example.com/src/Chronicle/Process/Replicate.php on line 185
    

    Possibly because of a missing signature in the second to last entry in the chain?

    Replicating: https://php-chronicle.pie-hosted.com/chronicle/export

    opened by stayallive 5
  • Unable to retrieve entry containing binary data

    Unable to retrieve entry containing binary data

    Hi,

    I added a new encrypted entry to the chain (data encrypted with Sapient\SealingPublicKey). When I try to retrieve the entry for that hash using the lookup api route or export the whole chain, I receive the following error response:

    { "version": "1.0.x", "datetime": "2018-10-19T15:36:07+02:00", "status": "ERROR", "message": "Cannot JSON-encode this message." }

    I checked the data stored in the chronicle_chain table for that hash and I found out that it is stored in binary form:

    grafik

    I think the data should either be stored in an encoded form or appropriate encoding should applied to ensure retrieval via REST API is possible.

    Best regards, Ben

    bug 
    opened by beeare 4
  • [Use Case] Multiple Chains - Company Agreements

    [Use Case] Multiple Chains - Company Agreements

    Hi,

    I have an idea to use chronicle in which is any company has many agreements with their customers, agreements like (TOS, privacy & many more). The company is a very transparent company with their customers and it does want every customer to agree on every change for their business model. After some time design some considerations I come up with this structure:

    $block = [
        [
            'type' => 'tos',
            'hash' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
            'terms' => ' ... ',
            'effective_at' => '2019-06-09 00:00:00',
            'functions' => [
                'deprecated' => [
                    // ..
                ],
                'current' => [
                    // ..
                ],
                'new' => [
                    // ..
                ],
            ],
        ],
        [
            'type' => 'privacy',
            'hash' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
            'terms' => ' ... ',
            'effective_at' => '2018-06-09 00:00:00',
            'functions' => [
                'deprecated' => [
                    // ..
                ],
                'current' => [
                    // ..
                ],
                'new' => [
                    // ..
                ],
            ],
        ],
    
        // ...
    ];
    

    But, If just I want to update the privacy terms I will need to duplicate TOS and many others with it in order to be keep tracking last version for all agreements at /chronicle/lasthash , I feel current chronicle does not provide multiple chains, subjects or networks So, I think it will be a better if add the support for multiple networks, something like this /chronicle/{network}/lasthash. I prefer subject term over the network, because the url will be more fluent:

    • /chronicle/tos/lasthash
    • /chronicle/privacy/lasthash

    The update to APIs will be:

    [
    	{
    		uri: "/chronicle/{subject}/lasthash",
    		description: "Get information about the latest entry in this Chronicle at custom subject"
    	},
    	{
    		uri: "/chronicle/lasthash",
    		description: "Get information about the latest entry in this Chronicle at main subject"
    	},
    	{
    		uri: "/chronicle/lookup/{subject}/{hash}",
    		description: "Lookup the information for the given hash at custom subject"
    	},
    	{
    		uri: "/chronicle/lookup/{hash}",
    		description: "Lookup the information for the given hash at main subject"
    	},
    	{
    		uri: "/chronicle/since/{hash}",
    		description: "List all new entries since a given hash at custom subject"
    	},
    	{
    		uri: "/chronicle/since/{subject}/{hash}",
    		description: "List all new entries since a given hash at main subject"
    	},
    	{
    		uri: "/chronicle/{subject}/export",
    		description: "Export the entire Chronicle at custom subject"
    	},
    	{
    		uri: "/chronicle/export",
    		description: "Export the entire Chronicle at main subject"
    	},
    	{
    		uri: "/chronicle/replica",
    		description: "List of Chronicles being replicated onto this one (and other options)"
    	},
    	{
    		uri: "/chronicle",
    		description: "API method description"
    	}
    ]
    

    If chronicle will offer something like this, then it can be used in many other cases like:

    • News agency /chronicle/new-york/lasthash as a news feed.
    • Applications development Changelog /chronicle/changelog/lasthash.
    • Blog storage.

    Any suggestions are very welcome. <3

    opened by vzool 4
  • ISSUE: No client header provided

    ISSUE: No client header provided

    Hi,

    I did setup a two Chronicle instances which are Chronicle-A and Chronicle-B. I generated keypairs with php bin/keygin.php at Chronicle-A, then I took public key and create a new client with php bin/create-client.php at Chronicle-B which gave me a success result.

    ➜  php bin/create-client.php --publickey="N1DIRAN2XpXaIJpFx2IpDQpqF4j0bkGDhkmlNBI_NHU=" --comment="point-BB"
    	Client (VeVGBO9gThq_eTzCbAR3vgrhEHrUnRqL) created successfully!
    

    I try to test publish some data with the following code:

    <?php
    
    $root = \dirname(__DIR__);
    /** @psalm-suppress UnresolvableInclude */
    require_once $root . '/cli-autoload.php';
    
    use GuzzleHttp\Client;
    use ParagonIE\Sapient\Sapient;
    use ParagonIE\ConstantTime\Base64UrlSafe;
    use ParagonIE\Sapient\Adapter\Guzzle as GuzzleAdapter;
    use ParagonIE\Sapient\CryptographyKeys\SigningPublicKey;
    use ParagonIE\Sapient\CryptographyKeys\SigningSecretKey;
    use ParagonIE\Sapient\Exception\InvalidMessageException;
    
    $http = new Client([
        'base_uri' => 'http://localhost:8080'
    ]);
    $sapient = new Sapient(new GuzzleAdapter($http));
    
    // Keys
    $clientSigningKey = new SigningSecretKey(
        Base64UrlSafe::decode(
            'JblJ6oEbqA8pBQKbwX_gSb7wCP85--C9ANyRU-eYGUM3UMhEA3ZeldogmkXHYikNCmoXiPRuQYOGSaU0Ej80dQ=='
        )
    );
    $serverPublicKey = new SigningPublicKey(
        Base64UrlSafe::decode(
            'N1DIRAN2XpXaIJpFx2IpDQpqF4j0bkGDhkmlNBI_NHU='
        )
    );
    
    // We use an array to define our message
    $myMessage = [
        'date' => (new DateTime)->format(DateTime::ATOM),
        'body' => [
            'test' => 'hello world!'        
        ]
    ];
    
    // Create the signed request:
    $request = $sapient->createSignedJsonRequest(
        'POST',
         '/chronicle/publish',
         $myMessage,
         $clientSigningKey
    );
    
    $response = $http->send($request);
    try {
        /** @var array $verifiedResponse */
        $verifiedResponse = $sapient->decodeSignedJsonResponse(
            $response,
            $serverPublicKey
        );
    } catch (InvalidMessageException $ex) {
        echo $ex->getMessage();
        // \http_response_code(500);
        exit;
    }
    

    Then, I received this error:

    Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: `POST http://localhost:8080/chronicle/publish` resulted in a `403 Forbidden` response:
    {
        "version": "1.0.x",
        "datetime": "2018-07-06T19:57:36+00:00",
        "status": "ERROR",
        "message": "No client  (truncated...)
    in /Users/vzool/Workspace/chronicleA/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113
    Stack trace:
    #0 /Users/vzool/Workspace/chronicleA/vendor/guzzlehttp/guzzle/src/Middleware.php(66): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response))
    #1 /Users/vzool/Workspace/chronicleA/vendor/guzzlehttp/promises/src/Promise.php(203): GuzzleHttp\Middleware::GuzzleHttp\{closure}(Object(GuzzleHttp\Psr7\Response))
    #2 /Users/vzool/Workspace/chronicleA/vendor/guzzlehttp/promises/src/Promise.php(156): GuzzleHttp\Promise\Promise::callHandler(1, Object(GuzzleHttp\Psr7\Response), Array)
    #3 /Users/vzool/Workspace/chronicleA/vendor/guzzlehttp/promises/src/TaskQueue.php(47): Guzzl in /Users/vzool/Workspace/chronicleA/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php on line 113
    
    

    After I dig more into Publish Handler I found the truncated message, which is here:

    No client header provided 
    

    What I did miss here?

    Thanks

    opened by vzool 4
  • PHP Client Library

    PHP Client Library

    Is there a PHP client library yet, like something that lets you interact with a chronicle server by calling functions instead of creating POST requests yourself?

    opened by defuse 4
  • [Feature Request] API for available instances

    [Feature Request] API for available instances

    Hi, I'm looking forward to an API that lists all public instances in the chronicle app, then this will lead us to hide other instances for some use cases. By that in mind I suggest to update local/settings.json to support this feature like the following:

    {
      ...
    
      "instances": {
        "": {
          "name": "",
          "public": true,
          "desc": "Default public instance"
        }
      },
    
      ...
    }
    

    I mean by public if set to false is just to hide the instance in the suggested API result. Thanks

    opened by vzool 3
  • Invalid identifier: Invalid characters supplied.

    Invalid identifier: Invalid characters supplied.

    When running:

    php bin/scheduled-tasks.php
    

    Sometimes this is generated:

    PHP Fatal error:  Uncaught ParagonIE\EasyDB\Exception\InvalidIdentifier: Invalid identifier: Invalid characters supplied. in /var/www/vhosts/domain.com/vendor/paragonie/easydb/src/EasyDB.php:295
    Stack trace:
    #0 /var/www/vhosts/domain.com/vendor/paragonie/easydb/src/EasyDB.php(745): ParagonIE\EasyDB\EasyDB->escapeIdentifier('"chronicle_chai...')
    #1 /var/www/vhosts/domain.com/vendor/paragonie/easydb/src/EasyDB.php(512): ParagonIE\EasyDB\EasyDB->buildInsertQueryBoolSafe('"chronicle_chai...', Array)
    #2 /var/www/vhosts/domain.com/src/Chronicle/Chronicle.php(153): ParagonIE\EasyDB\EasyDB->insert('"chronicle_chai...', Array)
    #3 /var/www/vhosts/domain.com/src/Chronicle/Process/Attest.php(153): ParagonIE\Chronicle\Chronicle::extendBlakechain('{\n    "version"...', 'IryGC1_n2byTv9W...', Object(ParagonIE\Sapient\CryptographyKeys\SigningPublicKey))
    #4 /var/www/vhosts/domain.com/src/Chronicle in /var/www/vhosts/domain.com/vendor/paragonie/easydb/src/EasyDB.php on line 295
    

    I have no clue why... I'm running an empty Chronicle with the default sqlite db and a single replica (https://php-chronicle.pie-hosted.com/chronicle).

    The replica seems to be running fine but this error puzzles me and makes me think something is not going ok... any clue?

    opened by stayallive 3
  • Resolve all Chronicle issues in MySQL

    Resolve all Chronicle issues in MySQL

    Hi,

    I tested Chronicle in MySQL connection and I have some issues, I resolved two of them. But, there are many more needs to collaboration with some guidance.

    The current known issues are:

    • [x] issue mentioned here #32. Resolved by made datetime fields filled automatically by MySQL.
    • [x] issue ERROR 1048 (23000): Column 'prevhash' cannot be null. Resolved at database level by swapping foreign key rule prevhash with currhash.
    • [ ] When Chronicle use MySQL should ignore values for datetime fields. [Not-Resolved]
    • [ ] Revise replica functions. [Not-Resolved]

    Thanks

    opened by vzool 3
  • Public Test Server

    Public Test Server

    https://chronicle-public-test.paragonie.com/

    Post your public keys here, and I'll give you write access.

    • API: https://chronicle-public-test.paragonie.com/chronicle
    • Last hash: https://chronicle-public-test.paragonie.com/chronicle/lasthash
    • Full export: https://chronicle-public-test.paragonie.com/chronicle/export
    opened by paragonie-scott 3
  • Code Review

    Code Review

    Do not pass around $app

    • https://github.com/paragonie/chronicle/blob/master/src/Chronicle/Handlers/Lookup.php#L28 It's also never used in this class

    • https://github.com/paragonie/chronicle/blob/master/src/Chronicle/Handlers/Lookup.php#L191-L207 Resource based limitation.. I think this is a problem in the EasyDB package. The results of this sql query are buffered into RAM. So if there are 128MB of items, PHP will consume 128MB... There's a chance that the process will run OOM.

    Your route defintions are not ideal.

    $app->group('/chronicle', function () use ($app) {
        $app->post('/publish', new Register($app))
            ->add(new CheckAdminSignature());
        $app->post('/publish', new Revoke($app))
            ->add(new CheckAdminSignature());
        $app->post('/publish', new Publish($app))
            ->add(new CheckClientSignature());
        $app->get('/lasthash', new Lookup($app, 'lasthash'));
        $app->get('/lookup/[{hash}]', new Lookup($app, 'hash'));
        $app->get('/since/[{hash}]', new Lookup($app, 'since'));
        $app->get('/export', new Lookup($app, 'export'));
    });
    
    1. When inside the group the router is bound to the anom function allowing you to use $this instead of currying $app

    2. you can use an empty route group to apply middleware to multiple things

    3. With your current routes every request you are creating each of those Handlers when you do not need to. You may register handlers via a String in the container and then use the container key in the 2nd argument of the http method.

    4. Furthermore, 3 applies to middleware as well.

    //Routes
    $app->group('/chronicle', function () {
        $this->group('', function () {
            $this->post('/publish', Register::class);    //This is a bug <---
            $this->post('/publish', Revoke::class;      //This is a bug <---
            $this->post('/publish', Publish::class); 
        })->add(CheckAdminSignature::class);
    
        $this->get('/lasthash', 'lookup.lasthash');
        $this->get('/lookup/[{hash}]', 'lookup.hash');
        $this->get('/since/[{hash}]', 'lookup.since');
        $this->get('/export', 'lookup.export');
    });
    
    //Container Definitions
    $container[CheckAdminSignature::class] = function ($c) { ... };
    $container[Register::class] = function ($c) { ... };
    $container[Revoke::class] = function ($c) { ... };
    $container[Publish::class] = function ($c) { ... };
    $container['lookup.lasthash'] = function ($c) { ... };
    $container['lookup.hash'] = function ($c) { ... };
    $container['lookup.since'] = function ($c) { ... };
    $container['lookup.export'] = function ($c) { ... };
    
    opened by geggleto 3
  • Replication is failing

    Replication is failing

    Hi, cool project!

    I installed it and seems to work fine for the most part, but I am having issues with the replication.

    I follow the steps in the docs: installed the first Chronicle instance, configured it up to MySQL, built tables and such. Then added a client and published some data to it.

    Then I created a 2nd one, ran bin/replicate.php with a target of http://127.0.0.1:8080/chronicle and the first Chronicle's pub key. This seems to work well too, and adds an entry to the chronicle_replication_sources.

    However, the secondary Chronicle does not seem to be replicating the source. I modified the "scheduled-attestation": to 360 seconds but not seeing any hashes on the secondary instance. I tried to execute the scheduled-tasks.php script and got the following error:

    Fatal error: Uncaught ParagonIE\Chronicle\Exception\SecurityViolation: Invalid summary hash. Expected Pxqeejbjl-mAipyhtIDevQNmdpBHMN_-XBCZ6sQ1y7c=, calculated bpqrzUNnTsNg4aSHcBXOnn-qJzyUYB62MJtCSORr6bM= 
    
    in src\Chronicle\Process\Replicate.php:203
    

    I also truncated the chains and tried to replicate again, but no luck.

    Do you have any idea why this might be?

    opened by Exhibitioner 3
  • How to verify contents response?

    How to verify contents response?

    This project seems interesting and potentially something I'd like to use for a project, however not entirely sure how the design works on the verification side.

    I installed the Chronicle and a replica. How can the clients be sure that the contents returned from a Chronicle are intact? Do you have an pseudo code example of that?

    My understanding is that you'd query multiple replicas and compare the contents response? But I feel like I'm missing something.

    For example, is it required to compare the contents field against the currhash; if so how may the client compute that hash? Or is this only done as part of the Chronicle replication process?

    opened by catahax313 1
  • Enhancement suggestion: Cloud support

    Enhancement suggestion: Cloud support

    Hi,

    I realise its a possibly little "easier said than done" in terms of complexity. But in terms of enhancing the replication capability of chronicle, it might be nice to see cloud support.

    Support for "cheap & simple" variants such as AWS Dynamo or Azure Tables could provide a nice replication option.

    opened by udf2457 2
  • Instance Deployment - One-Click Setup

    Instance Deployment - One-Click Setup

    Whether this means selling AMIs on the AWS Marketplace (like we do with CMS Airship), or partnering with another provider (Digital Ocean, perhaps?).

    If we don't go the AMI route, this issue is up for grabs.

    opened by paragonie-scott 5
Releases(v1.3.1)
  • v1.3.1(Jan 17, 2022)

    • Version 1.3.0 added a SQL table but did not include a mechanism to run the associated SQL file.
    • To address this, update to v1.3.1 and then run php bin/make-tables.php 02-v1.3.0 and the new table will be created.
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Jan 17, 2022)

    • #43 - Support a public list of replica instances (optional)
    • Command line utility for changing the public key for a replication source (in replica instances)
    • Migrated from Travis CI to GitHub Actions
    • Requires PHP 7.1 or newer
    • Supports PHP 8.1
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Sep 27, 2019)

    • Implemented #53 -- You will now be warned if a public key doesn't match what you input (or, if you omit a public key for setting up replication, it will ask you to confirm it before proceeding)
    • There is now a /replica/{unique_id} endpoint, just to index each replica's contents. (Before: it was a 404.)
    • Implemented #34 -- You can now configure your Chronicle to paginate the /export and /since endpoints.
    • Implemented #61 -- You can now configure your Chronicle to cache HTTP responses for a short period of time, to help mitigate extreme load (i.e. what we've been experiencing in our public instances).
    Source code(tar.gz)
    Source code(zip)
  • v1.1.5(Sep 12, 2019)

  • v1.1.3(Jan 26, 2019)

  • v1.1.2(Dec 18, 2018)

  • v1.1.1(Dec 17, 2018)

  • v1.1.0(Oct 26, 2018)

    • The first record in a Chronicle now has a prevhash of NULL. This allows foreign key constraints to be added to the database table definition.
    • When publishing files to the Chronicle, anything that cannot be safely encoded in JSON will cause the write to fail.
      • This is preferable to causing the export API to break forever.
      • We recommend base64url-encoding any binary blobs before sending them to Chronicle.
    • We now have documentation for Chronicle's internals.
    • New feature: concurrent instances
    • Several command line scripts return JSON messages if you pass the -j flag, to make them more useful in automation scripting (without forcing users to parse the standard CLI output messages manually).
    Source code(tar.gz)
    Source code(zip)
  • v1.0.4(Oct 18, 2018)

    This is mostly a boyscouting release.

    • Updated the minimum version of dependencies (EasyDB, sodium_compat)
    • Removed duplicate code
    • Improved docblocks and comments
    • Chronicle is now 100% type-safe
    Source code(tar.gz)
    Source code(zip)
  • v1.0.3(Jan 19, 2018)

  • v1.0.2(Jul 18, 2017)

    • Fixed a bug in revocation identified by @lookyman in #17 caused by NULLs
    • Added bin/fix-nulls.php which will clean up the NULLs in the existing database (setting them to FALSE or 0, depending on the database driver).
    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Jul 17, 2017)

    • Fixed typos
    • Changed VERSION constant for API responses to reflect the API's 1.0 release status.
    • Typo fixes (mostly pull requests #14 and #16)
    • Began listing (chronicling, even) client-side implementations in the README file.
    • Made it easier to find the Chronicle API URL:
      • Added a hyperlink on the index page to the API.
      • If you send a Client ID header to the index page, you get redirected to the API.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jul 9, 2017)

    This is mostly a bugfix release from v0.5.1, thanks to our public testing server.

    • Fixed SQL definition inconsistencies.
    • Verified that replication works.
    • Verified that cross-signing works.
    • More unit tests.
    • Fixed documentation warts.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Jul 9, 2017)

  • v0.5.0(Jul 9, 2017)

    Two new optional features:

    1. Publish metadata when clients are added or removed.
    2. Request timeouts (to defeat replay attacks). This changes the register/revoke APIs to require a request-time parameter in the JSON body, which will be required to fall within a time interval.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jul 8, 2017)

    • Lots of whitespace/docblock improvements
    • Fixed typos that were causing SQL errors
    • Reworked our exceptions; we now don't throw any base Error or Exception objects
    • Chronicle now has a logo (an SVG image created with a text editor)

    This is probably the last pre-1.0.0 release.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Jul 7, 2017)

    • We now have some basic end user Documentation for installing and running a Chronicle
    • Replication improvements:
      • Chronicle now verifies the Ed25519 signature of each message when pulling from the source
      • Replication data is now publicly accessible via the new /chronicle/replica URI
      • On a regular time interval, Chronicle can publish the latest hashes for all of its replicas (we call this scheduled attestation)
    • Added a CLI testing apparatus for testing locally
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Jul 1, 2017)

    • Changed what goes into each link in the Blakechain
      • Old : H(data)
      • New: H(time || publickey || signature || data)
    • Implemented cross-signing
      • Publish your summary hash at a point in time to another Chronicle
    • Implemented replication
      • Mirror one (or more) other Chronicles to a separate database table, validating every new hash along the way.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Jun 27, 2017)

    This is the first unstable release of Chronicle, a Sapient-secured microservice that stores messages in a cryptographically verifiable append-only data structure.

    The goal of the first release was to get a rough HTTP API exposed. In the near future, we'll add features (including cross-signing; see #2) and support for various database backends.

    Source code(tar.gz)
    Source code(zip)
Owner
Paragon Initiative Enterprises
Technology should support your ambitions, not hinder them. We are a team of technology consultants that specialize in application security.
Paragon Initiative Enterprises
Slim 3 PHP micro framework MVC application boilerplate

Slim 3 PHP micro framework MVC application boilerplate

Jim Frenette 24 Oct 8, 2022
A Blogging Platform with a built-in Feed Aggregator. Built with AngularJS and Laravel.

ReMark ReMark is an open source publishing platform built with the informed content creator in mind. It works as: A blogging platform A feed aggregato

Ren 4 Nov 1, 2019
Centreon is a network, system and application monitoring tool. Centreon is the only AIOps Platform Providing Holistic Visibility to Complex IT Workflows from Cloud to Edge.

Centreon - IT and Application monitoring software Introduction Centreon is one of the most flexible and powerful monitoring softwares on the market;

Centreon 14 Dec 16, 2022
HiDomainer One-File Domain Portfolio Script, is a PHP script of only 8kb.

HiDomainer One-File Domain Portfolio Script, is a PHP script of only 8kb. Download Feature 1. PC and Mobile Friendly 2. Data management without page r

HiDomainer.com 1 Mar 2, 2022
Infopanel is a simple tool getting some information from source. It works basically like a slider that shows only title, image, a little bit description and QR-Code for links.

Infopanel is a simple tool getting some information from source. It works basically like a slider that shows only title, image, a little bit description and QR-Code for links. It has its own GUI for the editing. The GUI provides a very simple role concept. This tool can be used for digital signage, Information panels, News or Events or similar.

null 4 Aug 22, 2022
Twitter clone - This project is conducted for learning purposes only

Twitter clone - This project is conducted for learning purposes only

Wanderson Renê 2 Jun 24, 2022
Subscriptify - a simple subscription platform(only RESTful APIs with MySQL)

Create a simple subscription platform(only RESTful APIs with MySQL) in which users can subscribe to a website (there can be multiple websites in the system). Whenever a new post is published on a particular website, all it's subscribers shall receive an email with the post title and description in it. (no authentication of any kind is required)

Md Rafsan Jani Rafin 2 Mar 24, 2022
A slim, lean forum package designed for quick and easy integration in Laravel projects

Complete documentation is available on teamteatime.net. Installation Requires Laravel 6+ and PHP 7.4+. Step 1: Install the package Install the package

TeamTeaTime 486 Dec 31, 2022
This is a simple Slim 3 application that manages a list of books

Slim Bookshelf This is a simple Slim 3 application that manages a list of books Composer This project uses Composer. Run composer install to install t

Rob Allen 124 Aug 22, 2022
Krayin CRM is a hand tailored CRM framework built on Laravel and Vue.js

Krayin CRM is a hand tailored CRM framework built on some of the hottest opensource technologies such as Laravel (a PHP framework) and Vue.js a progressive Javascript framework.

Krayin CRM 1.1k Jan 3, 2023
This is the source code to my website built with the Laravel framework.

About This is the source code to my website built with the Laravel framework. Set-up Simply clone this repository, install composer and node dependenc

Octanna 6 Dec 29, 2021
A simple web application for seeing a store's books. Built with Laravel 8 (a PHP Framework).

HappyBookStore Happy Book Store is a simple web application for seeing a store's books. As a user, you can look what book is available in the store by

Ananda Bilal 0 Jan 31, 2022
ZAP CRM is Customer Relationship Management portal built using PHP Codeigniter 4 & Tailwind CSS framework.

ZAP CRM ZAP CRM is Customer Relationship Management portal built using PHP Codeigniter 4 & Tailwind CSS framework. Screenshots User (Dashboard) Admin

Dawood Khan Masood 5 Feb 2, 2022
A complete open source hotel management system built with Laravel Framework.

Hotelio : Hotel Management System Hotelio is a open source hotel management system that manages your hotel operations, smoothly, effortless. Hotelio i

Mehedi Jaman 10 Dec 6, 2022
A platform to create documentation/wiki content built with PHP & Laravel

BookStack A platform for storing and organising information and documentation. Details for BookStack can be found on the official website at https://w

BookStackApp 10.6k Jan 3, 2023
mTube is a simple video sharing platform built with Laravel.

mTube is a simple video sharing platform built with Laravel. Create personal channel share videos online with friends and family.

Nyi Nyi Lwin 115 Dec 28, 2022
A web application for a school, facilitating the registration of students. Built using HTML/CSS, PHP and Oracle.

Student Registration System A web application for a school, facilitating the registration of students. Built using HTML/CSS, PHP and Oracle. Included

Sana Khan 4 Oct 2, 2021
A much faster alternative to youtube-dl built for PHP applications.

youtube-downloader This project was inspired by a very popular youtube-dl python package: https://github.com/rg3/youtube-dl Yes, there are multiple ot

null 668 Jan 3, 2023