Have you ever had to confront a villain with your discoveries, knowing that unless you take precautions they might just kill you? Or gone on a dangerous adventure, wanting to keep the details secret until you come back (or unless you don’t)? Or wanted your passwords to be shared with a friend if you became long-term unavailable?
I haven’t either, but who knows.
These problems can be solved with a single trusted secret-holder: You give your secret to someone, and tell them not to look at it or share it until some condition is triggered. (The trigger might be e.g. failure to receive an I’m-still-here message from you every week.)
But that’s error-prone. Even if you 100% trust their good intentions, it’s still easy for a single point of failure to make a mistake (in either direction: they might be compromised and release the secret too early, or they might disappear or lose the secret).
Can we achieve the same kind of triggered release without trusting a single interediary? I think so, and here’s the process I’m imagining:
- The secret-sharer gives (different) data to each of the secret-holders such that some subset of them could reconstruct the secret
- The secret-sharer makes public a condition under which the secret-holders should release the secret publicly
- If the condition is met, the secret-holders publish their parts of the secret.
- Now anyone1 can reconstruct the secret.
There are some incentives we need to get right in order for this to work:
- each secret-holder should be rewarded for participating in the process (regardless of whether the condition is triggered)
- each secret-holder should be punished if they release their part of the secret too early
- each secret-holder should be punished if they fail to release their part of the secret after the condition is triggered
- each secret-holder should be able to trust that no one else knows their part of the secret
The last condition rules out a straightforward application of Shamir’s secret sharing. We can’t have the secret-sharer compute the secret-holders’ shares of the secret, since then the secret-holders couldn’t trust that they won’t be wrongly punished (if the secret-holder accidentally or purposefully released some or all of the shares).
The punishments must be consist of significant losses for the secret-holders (not just failure to get paid), because a secret-holder who doesn’t follow the rules undermines the integrity of the whole system. We’ll require deposits which they lose if the punishment conditions are triggered.
I think we can use Ethereum to achieve these incentives. This procedure will require all
N secret-holders’ for the secret-reconstruction phase, but I think we can modify it later so only a proper subset of the
N are needed:
(For convenience, let’s say
p0 is the secret-sharer, and
pn are the secret-holders.)
- The secret-holders make a deposit to the contract.
- Each secret-holder
1≤i≤N) generates a random string
siof the same length as the secret.
- For convenience, let’s say the secret is s0.
- Everyone sends the hash of their si to the contract.
- Then everyone computes the sum
S = ∑i=0nsiwithout revealing anyone’s
si(see below for more on how to do this).
Sis now public, but doesn’t reveal anything about the secret.
- If the contract’s “release” condition is triggered, then the secret-sharers each release so.
This is pretty rough, but here’s a basic idea of the kinds of functions the Ethereum constract would need:
- (constructor) – should store the addresses of the secret-holders and secret-sharer; the contract should be created with enough funds to pay the secret-holders for their participation
picalls this with the
hash(si), which is stored.
- something to decide when the hash-collection phase is over
should_release()– this private function determines whether it’s time to release the secret, and can be written however we want – maybe it’s based on the date, or based on another function
pingnot receiving a call from the secret-holder for a certain period of time; I’ll assume that after 1 year from contract creation,
should_release()is guaranteed to return
punish_for_release(pi, si)(only callable before
should_release()is true) – anyone holding
pito lose their deposit for releasing too early (and receive a small reward for their trouble)
release(si)– (only callable after
s_i, we confirm that its hash matches the stored hash, and
pireceives their deposit payment, plus their payment for participating
How to Add
How do we compute the sum
S = ∑i=0nsi without revealing anyone’s
si? Here’s one way2: