Status: Draft
Authors:
Contents:
- Read Access
- Read AccessControllers
- Protocol for Requesting and granting access to an entry
- Modifications to the ipfs-log
Currently OrbitDB's AccessControllers allow
for the control of write
access to a data store, but
not the control of read access.
This is first of all due to the fact, that IPFS Objects can be read by anyone, which means, that encryption is the scheme to use to control read access while still using IPFS.
In this SCP, I propose the development of an Access control mechanic, that will fulfill these criteria:
- All the data in the store is stored in an encrypted form
- Every entry is individually encrypted and decrypted
- Read Access can be granted for each entry individually and to each identity individually.
Let's first define, how read access may be granted from the point of view of an OrbitDB user.
I propose adding a canRead(entry, identity)
method to the AccessController
class,
which is passed the plaintext entry and the identity of the machine, that is requesting
access to the entry.
If the method returns true, access may be granted to the identity for the entry. But only for this entry and only to this identity!
With such an API, it is comparatively simple to implement even very complicated read permissions in JS.
But any user has to remember, that once somebody is given read access to some data, this access may not be revoked and that they could possibly grant access to the data to other identities or the public in whichever way they might choose.
For this reason I decided against using a single key to encrypt the entire store, since that would not make it possible to differentiate between entries and increases the risk of leaking data.
In order to securely implement this API, a simple PubSub based protocol may be implemented.
- It starts by the requesting node publishing a signed request for an entry into a pubsub channel.
- Then some node, that has access to the entry in plaintext, checks via
canRead
whether or not the request should be granted. - If the request was granted the data is encrypted using a one-time key (that was shared using the Diffie-Hellman Key Exchange) and the CID of the encrypted content published on PubSub.
After this, both the requesting as well as the providing node have read access to the data, but nobody else observing the PubSub channel has any information, except that the requesting node requested some data and the providing node provided said data. (Which might be a leak of information in some use cases, especially concerning meta data).
Sources: Computerphile video on this and the Wikipedia Page.
The Diffie-Hellman key exchange is one of the first public key cryptography systems proposed and has the goal of exchanging a private key over a public medium, without leaking the private key to anyone but the intended participants of the exchange. It was implemented and tested for a long time (being proposed in 1976, one year earlier than RSA) and is very computationally expensive to break, even for supercomputers.
After a key has been shared with Diffie-Hellman, it can be used to seed a PRG or directly be used as a key for AES, Chacha or some other symmetric cipher.
In this scheme the ipfs-log
no longer stores the data of an
entry directly, instead it stores the CID generated from the plaintext
of the entry.
This means that no trust between the node granting access and the node receiving access has to be established, since the node receiving data can decrypt it with the generated key and verify the CID with the one in the entry.
Because the encryption of some data D
and the data D
are
different, CID(D)
and CID(E(D))
are not the same.
Thus, the ipfs-log
has to be modified.
Instead of storing an encrypted Object directly in the graph,
each node in the graph stores the CID of the Object in plaintext.
(Which is generated, but the object itself is not added to IPFS)
Then the encrypted objects refer to this object using links.
And after somebody receives a version of the
object, they can decrypt (Through the above described protocol) and
verify it with the CID stored in the ipfs-log
node.
It is theoretically possible to create an OrbitDB Store, that has some read access control, that fulfills all the criteria named above.
But it is complicated and requires reworking the
ipfs-log
and creating a private store for the Diffie-Hellman one time keys.
Implementing this would thus require:
- Modifying
ipfs-log
to allow for objects, that only store the CIDs of the plaintext entry. - Modifiying the key store to store the lot of Diffie-Hellman Keys or some key, that is used to encrypt all my entries, but is never shared with anybody. (To reduce the amount of keys, that have to be managed.)
I would propose to first create an implementation
as a custom store to verify and test the system
and then to implement in the Store
type itself.
I would like it if it would be as easy as passing
an option to the orbitdb.create
function to create
a read protected, encrypted database.