[Ethereum] How to implement role-based access control to user’s private data


We have this application scenario and try to see if Ethereum, or blockchain in general, is a good solution for this.

The basic idea is the user controls a small amount of private sensitive data (e.g., individual profile change history, transaction history). The user can control who has access to that data. When user A toggles on the access for another user B, B can see the whole transaction history. Obviously other users without access shouldn't see A's data.

We are thinking of storing user's encrypted data in the public blockchain. Ethereum is one of the options we are considering. The advantages of doing so is:

  • De-centralized, or zero downtime

  • Any user with access see the un-alterable transaction trail (good for auditing purpose)


  • How would you implement the role based access control to the content encryption key?

Obviously we can't encrypt the content with the user's own private key, otherwise when user wants to share data, he/she would have to give away the private key in order to decrypt the content.

So each unit of private data should have a unique encryption key. And we have to change the encryption key and re-encrypt the content every time the user revokes someone else's access.

So that leads to another question:

  • Where should we store these encryption keys?

Should we store them in a privately owned database? A more general question is, since blockchain achieves tracking the ownership in a public shared ledger, can it implement role-based access control completely with everything (except user's private keys) in public chain as well?


Thanks for the answer of Rob Hitchens. I read Vitalik's blog post and found that it's difficult to implement obfuscated computing on chain. So it's impossible to store everything on the public chain while keeping user's data privacy.

That mandates we need some kind of private storage to realize the privacy. One idea is to use the public chain for permissions record keeping only. e.g., we declare

mapping (address => bool) permissions;

And only sender can assign set any account's permission to true or false. Our private authentication server respects this permission mapping (stored in public chain) and only allows an authenticated user (i.e., the user that owns the private key to an authorized account) to access the content encryption key.

If we use the above design, to authenticate herself, the account owner needs to use the private key to compute a signature, and the auth server needs to verify that. That seems to similar to the way how identity is verified in ethereum transactions.

Will the above approach work? or more importantly, is there a better design?

Best Answer

Agree with Sanchit about using modifiers to control access to functions.

However, the example implementation is misleading. I would flag that for a redesign.

A couple of things to consider.

As far a data storage is concerned, you might want to consider off-chain serialization with encryption. This, to reduce the overall storage cost without compromising the distributed nature of the app.

For privacy, I see you're aware that information in Ethereum is visible to all parties. Consider using multi-party encryption with a smart contract to help distribute the "secret" to multiple authorized parties.

For scalability, @Sanchit's modifier needs to eliminate the unbounded for loop. Put simply, for(i=0;i<n;i++) is an anti-pattern. At a certain n the cost of execution will exceed the block gasLimit meaning it will fail in all cases. In other words, implemented that way guarantees a successful application will eventually fail, possibly in a way that can't be repaired.

What's shown is perfectly logical in a server-centric world. In Ethereum, all functions need an (approximately) fixed gas cost at any scale. A solution is to refactor with 1-step lookups using mapping.

Just mentioning this because this error exists in a lot of contracts and I hope the answer (I generally agree) doesn't lead coders to replicate that sort of defect.

Hope it helps.

Related Topic