Graphsync and ACLs for blocks

First, not sure if this is the right forum but: https://github.com/ipfs/go-graphsync talks about IPLD a lot, so I thought I’d start here since my usecase is IPLD and not IPFS.

I read through this: https://medium.com/coinmonks/is-storing-encrypted-files-on-ipfs-good-enough-21e050d9de0 and I think the idea could be pretty useful for us in providing read access control lists (ACLs) for Tupelo.

The gist is to have an ACL available “somehow” (SmartContracts for them, ChainTrees for us) but then bitswap would take an ACL into account before returning blocks to the requesting peer.

I’m trying to figure out if there are ways to plugin to the decision engine of graphsync or whether it requires forking the repo to add this kind of decision making.

1 Like

Note: discuss.ipfs.io is probably the right place to have this conversation.

go-graphsync is getting request hooks:

I’m not sure if this is really the right integration point but it’s a good starting point.


I agree that ACLs are probably the right way to go (although encryption is still useful).

However, be careful: reconciling ACLs and deduplication is tricky. In a naive ACL system, I could:

  1. Trick you into downloading some A that you have access to but I don’t.
  2. Trick you into downloading some B that points to A where I have access to B (through my own ACL).
  3. Use B to convince you that I should have access to A.
1 Like

Thanks for the reply! This request hooks PR looks like exactly what we need. Is GraphSync ready for production?

And thanks for the tip on ACL. We were planning to implement by storing ACL in a separate storage and once any ACL is applied to a block then any of the ACLs applied to a block would have to pass in order for the node to send the block over. We have a pretty cool situation where the ACL will always get shared before the block, so there isn’t a race there.

Thanks for the reply! This request hooks PR looks like exactly what we need. Is GraphSync ready for production?

go-filecoin uses graphsync for syncing the chain so it should be.

However, unlike bitswap, it can’t currently:

  • Figuring out which peers have content. You need to tell it to fetch a specific selector from a specific peer.
  • Split requests between multiple peers. It will download everything from that single peer.

Topper Bowers via libp2p libp2p@discoursemail.com writes:

And thanks for the tip on ACL. We were planning to implement by storing ACL in a separate storage and once any ACL is applied to a block then any of the ACLs applied to a block would have to pass in order for the node to send the block over. We have a pretty cool situation where the ACL will always get shared before the block, so there isn’t a race there.

Just be careful. There are a few variants:

  • If Malory can trick Alice into downloading some content attached to an
    ACL, either:
    • Alice won’t share this content with anyone else, even if Alice later sees other ACLs pointing to the content.
    • Alice will have to re-download the content for every ACL.
  • If Eve can trick Alice into downloading an ACL and then downloading the attached content from a different peer, Eve can steal the content. This won’t work if Alice makes sure to download from the peer that originally supplied the ACL.

Possibly secure solutions include:

  1. Just re-downloading the content once per ACL.
  2. Encrypting the content with a shared-keys stored in parent object (i.e., encryption + ACLs).
  3. Inserting some random salt into file metadata then:
  4. Disabling bitswap so we don’t ask for files by hash.
  5. Always ask for files relative to an ACL.
  6. Make sure the party sending the ACL is included in the ACL (so we can trust the links).
  7. Somehow create authenticated links from blocks back up the merkledag to ACLs.
  • This could be as simple as including a secret in every object and putting it next to every link to that object. This effectively creates a public and a private link to the object.
  • If confirmation attacks are acceptable, objects can be hashed twice: once by themselves for the CID, once with some well-known string to prove knowledge of the data (call this CAP). Then, links to objects would include both hashes.
    • This second hash could also be used to download objects independent of ACLs through bitswap. Instead of asking for CID, one would ask for (CID, hash(my peer id || your peer id || nonce || CAP)).