microledger

A single file ledger with crypto features for append only objects

Usage no npm install needed!

<script type="module">
  import microledger from 'https://cdn.skypack.dev/microledger';
</script>

README

Microledger

alt node alt version alt size alt gzipped

A single file ledger with crypto features for append only objects

Why

I needed a way to store Append Only Objects history, and i used other of my libraries (Faythe to add some crypto and encoding features. The main idea is to have all the the data in only one file (Easy to store anywhere)

Features

  • Uses random access storage and works in memory, file and browser (automatically choose the fastest option)
  • Can encrypt the content with a secretKey
  • Can sign the nodes with a ed25519 keypair
  • Can use SGL to manage authorization
  • Each node have the current state (append->state)

Installation

Available through the npm registry. It can be installed using the npm or yarn command line tools.

npm install microledger --save

Usage

import Microledger from 'microledger'

const log = new Microledger({ genesis: { me: 'Javi' }})
log.append({ wife: { name: 'Sam' } }).then((result) => {
  console.log('result', result)
  log.last().then((node) => {
    console.log(node)
  })
})

API

new Microledger([filename],[options])

This class creates an append only object, where you can only append and "delete".

filename if is a string, a filename is created in node. In the browser uses chrome filesystem api, creates an idb database, or uses localstorage. Can send any random local storage implementation as a function. If filename doesn't exist, uses ram.

Note: I'm normally use .mlg extension './myledger.mlg'

options includes:

{
  genesis: {}, // The initial object.
  keyPair: null, // set an object with publicKey and privateKey to sign the appended nodes.
  secretKey: null // set a secretKey to encrypt each node.
  sgl: null, // set an object to manage authorization (more info above)
  cache: 65536, // cache gets ands sets to improve performance
}

append(delta, [options])

This method appends the delta to the previos status AppendOnlyObject.

options check AppendOnlyObject

get(seq)

Returns the node in the seq sequence/index. Number incremented on each append.

last()

Returns the last node in the microledger.

verify(seq)

Verifies the hash related with the previos node (verifies the signature if exist). Returns true or false.

verified()

Verifies all the nodes from the beginning. Returns true or false.

Tests

npm install
npm run test

SGL (Simple Grant Language)

SGL is a simple but flexible DSL for granting and testing privileges (authorization). It is like XACML but simpler and JSON-oriented. You can use it to write rules about who should be able to do what, and then to compare circumstances to the rules to enforce custom logic. This lets you create your own Role-Based Access Control mechanisms, as well as authorizations based on other criteria.

To add this functionality you need to pass an object to verify each append:

Example:

sgl = [{
  path: '/publicKey',
  grant: 'key_admin'
},
{
  path: '/authorization/profiles',
  grant: 'key_admin'
},
{
  path: '/authorization/rules',
  grant: 'rule_admin'
},

{
  path: '/services',
  grant: 'se_admin'
},
{
  path: '/authentication',
  grant: 'key_admin'
}]

This verifies the grant privileges for each path

Your microledger genesis MUST have publicKey and authorization properties:

Example:

const genesis = {
  publicKey: [keyPair.toJson()],
  authorization: {
    profiles: [
      {
        key: `#${keyPair.toJson().id}`,
        roles: ['edge']
      }
    ],
    rules: [
      {
        grant: ['register', 'key_admin', 'se_admin', 'rule_admin'],
        when: { id: `#${keyPair.toJson().id}` }
      },
      {
        grant: ['authcrypt', 'plaintext', 'sign'],
        when: { roles: 'edge' }
      },
      {
        grant: ['route', 'authcrypt'],
        when: { roles: 'cloud' }
      }
    ]
  }
}

See sgl.js for more information. (Example Note: keyPair uses Faythe identity class,and is exposed by Microledger.Identity)

Protocol

Microledger is created to allow manage appends only objects in one single file. The header of the file:

version 2 bytes | mode 2 bytes | genesislength 8 bytes

and then sequencially:

CBOR(Node) | nodelength | CBOR(Node) | nodelength ... etc

version is 01

mode can be:

00 no encryption | no signatures

10 encryption | no signature

01 no encryption | signature

02 no encryption | signature and sgl

12 encryption | signature and sgl

The length of each node is an uint64be 8 bytes representation of Buffer length.

Dependencies

  • append-only-object: A way to append objects (deltas) to objects
  • buffer: Node.js Buffer API, for the browser
  • esm: Tomorrow's ECMAScript modules today!
  • faythe: An easy crypto library to send messages using key encapsulation. A courier for Alice and Bob.
  • quick-lru: Simple “Least Recently Used” (LRU) cache
  • random-access-file: Continuous reading or writing to a file using random offsets and lengths
  • random-access-memory: Exposes the same interface as random-access-file but instead of writing/reading data to a file it maintains it in memory
  • random-access-web: Chooses the fastest random access backend based on the user's browser
  • simple-grant-lang: Simple Grant Language (SGL)
  • uint64be: Encode / decode big endian unsigned 64 bit integers
  • util.promisify: Polyfill/shim for util.promisify in node versions < v8

Dev Dependencies

License

MIT

Copyright (c) 2020 Javi Santos

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.