orbitdb-archive / ipfs-log

Append-only log CRDT on IPFS
https://orbitdb.github.io/ipfs-log/
MIT License
398 stars 55 forks source link

Key structure #132

Open coyotespike opened 6 years ago

coyotespike commented 6 years ago

First, a quick recap.

OrbitDB is progressing towards dynamic access, aka dynamic permissions. As part of this effort, multiple access controller types need to be supported. Currently OrbitDB uses an IPFS-based access controller, and we would like to support OrbitDB-based and smart-contract-based access controller.

So far so good. To support a smart contract ACL, we have a scheme like this: right now, every entry has a key, which is used to sign the contents of the entry. When a peer receives this update, they use the key to verify that the entry was properly signed.

A smart contract ACL would also like to include some piece of info signed by a key which is in the smart contract. For instance, the smart contract has a user's wallet public key. The user signs the OrbitDB (ODB) public key with that wallet, resulting in a chainSignature.

Just as we verify the entry's signature with the key, we also want to verify the chainSignature with the chainKey.

That was the recap, here is the problem. This chainSignature and chainKey have to be stored somewhere so that peers can use them. Where should we store them?

  1. My first proposal was to add them as properties directly to the entry. But this breaks the formal structure of the entry. Now our protocol must deal with different entry shapes. Sad.
  2. Another proposal is to store them in an IPFS object, and put the hash under the key property.
  3. And the proposal @shamb0t came up with in today's inaugural community call is to store them in an object structure under the key property. Optimally, the object would sort of be self-describing, in typical IPFS style. Multikey? Multisig?
coyotespike commented 6 years ago

One worry with (2) is that IPFS documents sometimes take a long time to retrieve, and doing so for every entry could add significant overhead.

For (3): Is this previous discussion relevant? https://github.com/ipfs/specs/issues/58

A naive (not necessarily wrong) approach is just:

   let entry = {
     key: { chainKey, key }, 
     sig: { sig, chainSig },
      hash,
      id,
      payload,
      next,
      v,
      clock,
    }

How can we make this more self-describing/universal?

coyotespike commented 6 years ago

One approach is to change the line here (working off the acl-refactor branch):

 const signature = await acl.sign(entry)
    entry.sig = signature
    entry.key = acl.getPublicSigningKey('hex')
    return entry

to

const entry = await acl.sign(entry, key)
return entry

Each ACL must add an appropriate key property. The acl-refactor branch already delegates all verification responsibility to the ACL.

This would allow for custom ACLs to easily add their own key properties as needed. In that case, maybe the naive approach I mentioned in my previous comment would work fine.

coyotespike commented 6 years ago

@thiagodelgado111 pointed out this XML signature format, and the JWT format seems relevant as well.

Also, a signature is a hash, no? Hence perhaps we could use the multihash format, in conjunction with custom properties (sig: { chainSig: <multihash>, sig: <multihash> }.

Just brainstorming here.