cabal-club / cabal-core

Core database and replication for cabal.
GNU Affero General Public License v3.0
303 stars 43 forks source link

Private cabals #93

Open garbados opened 4 years ago

garbados commented 4 years ago

Related to password-protected cabals, it should be possible to create a cabal that has:

  1. Protected entry (admin must approve or pre-approve peers, or challenge peers to provide a password, or both)
  2. Protected reads (messages must be encrypted using a shared key issued by admin)

Such a cabal must have at least one or more admins to be protected in this way. It is important to protect entry as obscurity is not privacy, and important to protect reads in case the multifeed falls into hostile hands.

For example, consider this hypothetical scenario:

  1. Peer creates a cabal and designates themselves as an admin. They enter or generate a challenge key -- a password -- and an encryption key. A sync-only key is also generated that can be used in place of the challenge key.
  2. Additional peer joins. They present the correct challenge key, and the admin passes them the encryption key as part of the handshake. (If the peer presented the sync-only key, the admin would NOT pass them the encryption key, but would begin sharing the multifeed. This enables sync-only peers, such as relays, without compromising the integrity of the cabal.)
  3. Admin publishes the message "hello friendo", which is written to the multifeed as:
{
  "type": "chat/encrypted",
  "content": "..."
}

The value of the content field can then be decrypted into a normal message:

{
  type: 'chat/text',
  content: {
    text: 'default',
    channel: 'hello friendo'
  }
}

In this way the encryption key is never written to the log itself.

  1. Peer loses control of their machine and a hostile entity recovers the multifeed, but they are unable to read it because the encryption key is only shared during the handshake.
  2. Attacker, undaunted, cracks the discovery key and the challenge key. They connect to the swarm and retrieve a list of peers, but are unable to access the multifeed because the admin manually rejects them during the handshake. All other peers, recognizing the admin, also reject the attacker peer.

The end result is a private, encrypted cabal using public hyperswarm infrastructure.

garbados commented 4 years ago

If a challenge key or encryption key becomes compromised but no peer has lost control of their machine, an admin should be able to rotate it, even if only through some formalized process of starting a new cabal. For example, an admin might execute code like this to regenerate a cabal with the same allow-list and settings, but with a new challenge and/or encryption key:

cabal.regenerate((err, newCabal) => { ... }) // default settings, regenerates challenge and encryption keys
cabal.regenerate({ challenge: false }, (err, newCabal) => { ... }) // generate new encryption key, keep challenge key

When an admin regenerates the cabal, they post a final message to the old cabal that allows peers to follow them:

{
  "type": "cabal/regenerate",
  "content": {
    "key": "${discoveryKey}"
  }
}

The new encryption key is shared during handshaking and so should not be included in this regeneration message. A compliant client could then automatically switch over to the new cabal, prompting the user for a new challenge key if it has been rotated.

okdistribute commented 4 years ago

This is so awesome! Great job explaining it thoroughly as well. I can see this being immensely useful.