Hello Tor-Dev!
We've almost completed the implementation [1] for prop#250 so we've reviewed part of the proposal to correct part of it to reflect reality (because you know a proposal is just wishful thinking until you implement it :).
Attached is the new version that we've been working on. We would like feedback from the community before at least calling it "ACCEPTED" and updated in tor-spec.git [2].
Here is a small summary of the big changes and also we need feedback on something that we are not fully in agreement.
First, period have been changed from 12:00 -> 12:00 (24 hour) to 00:00 -> 24:00 so the protocol run is not over two days. Seemed more logical and less confusing :).
Second, we've removed the need of having majority for a commit to be considered for the shared random computation. Yes this sounds intense!! so it needs your attention. We think that majority concept was only protecting us against was a partition attack during commit phase but it turns out that having a conflict detection mechanism (see COMMITCONFLICT section) already protect us of most of them during the commit phase except maybe one that is described in Section 5.3.1. With this proposal change, an authority only keeps commits that are authoritative that is a commit coming directly from an authority.
We've added section 5.3 on Partition Attack. Choosing commit by majority was protecting us against a partition attack in the commit phase but not all so with or without it, we still need an external monitoring party that makes sure attack are not ongoing (or bugs). DocTor is the obvious candidate so we'll work on a partition attacks detection since all of them are noisy and detectable.
A sub-section (4.1.7) has also been added which address the need of a shared random key that signs the commit values so they can be verified by other authorities [3].
Finally, we would like your opinion also on if we should keep the conflict mechanism or not?. Since those partition attacks are basically dumb, do not achive much result for an attacker and it's at a high cost of comprimising a directory authority, should we keep them? Keep in mind that it adds a layer of complexity in the code especially with shared random keys which rotates every 30 days and are only available in the vote of an authority. It gets difficult to validate a conflict of an authority if we haven't seen yet a vote from that authority. There are ways to fix that code wise but is this worth it considering that every partition attack will be detected anyway by DocTor? One argument to keep it is resilience of the protocol. With conflict line, if one dirauth does stupid things, it will get ignored for the rest of the protocol run so we can still compute a fresh random value in the end. Again, does it worth it?
Don't hesitate to ask about sections that are not clear or could be incorrect or you do not understand fully. Also, a ACK is a valid reply :).
Thanks to all! David
[1] https://trac.torproject.org/projects/tor/ticket/16943 [2] https://gitweb.torproject.org/torspec.git/tree/proposals/250-commit-reveal-c... [3] https://trac.torproject.org/projects/tor/ticket/17349
On 29 Oct 2015, at 05:26, David Goulet dgoulet@ev0ke.net wrote:
Finally, we would like your opinion also on if we should keep the conflict mechanism or not?. Since those partition attacks are basically dumb, do not achive much result for an attacker and it's at a high cost of comprimising a directory authority, should we keep them? Keep in mind that it adds a layer of complexity in the code especially with shared random keys which rotates every 30 days and are only available in the vote of an authority. It gets difficult to validate a conflict of an authority if we haven't seen yet a vote from that authority. There are ways to fix that code wise but is this worth it considering that every partition attack will be detected anyway by DocTor? One argument to keep it is resilience of the protocol. With conflict line, if one dirauth does stupid things, it will get ignored for the rest of the protocol run so we can still compute a fresh random value in the end. Again, does it worth it?
The protocol is already resilient because if there is a failure, it still produces a (predictable) value based on the previous value. As long as a misbehaving authority can't mess with this fallback behaviour, and as long as sufficient directory authority operators can react within 24 hours to remove a misbehaving authority, then this seems ok to me.
A few questions:
Do we expect 24 or 48 hours of shared random downtime in the event of an incident, taking into account response time to remove an authority?
What would an authority do when it detects a conflict under the new proposal? Ignore it (pick the numerically higher value?) and expect DocTor to detect it?
What if an authority changes shared random signing keys partway through a round?
Tim
Tim Wilson-Brown (teor)
teor2345 at gmail dot com PGP 968F094B
teor at blah dot im OTR CAD08081 9755866D 89E2A06F E3558B7F B5A9D14F
teor teor2345@gmail.com writes:
On 29 Oct 2015, at 05:26, David Goulet dgoulet@ev0ke.net wrote:
Finally, we would like your opinion also on if we should keep the conflict mechanism or not?. Since those partition attacks are basically dumb, do not achive much result for an attacker and it's at a high cost of comprimising a directory authority, should we keep them? Keep in mind that it adds a layer of complexity in the code especially with shared random keys which rotates every 30 days and are only available in the vote of an authority. It gets difficult to validate a conflict of an authority if we haven't seen yet a vote from that authority. There are ways to fix that code wise but is this worth it considering that every partition attack will be detected anyway by DocTor? One argument to keep it is resilience of the protocol. With conflict line, if one dirauth does stupid things, it will get ignored for the rest of the protocol run so we can still compute a fresh random value in the end. Again, does it worth it?
The protocol is already resilient because if there is a failure, it still produces a (predictable) value based on the previous value. As long as a misbehaving authority can't mess with this fallback behaviour, and as long as sufficient directory authority operators can react within 24 hours to remove a misbehaving authority, then this seems ok to me.
Thanks for the feedback teor!
A few questions:
Do we expect 24 or 48 hours of shared random downtime in the event of an incident, taking into account response time to remove an authority?
Hm, I admit I have not thought too much about the response procedure in case of an incident.
I've mainly been relying on the fact that these attacks are not worth doing, and no one is going to bother. However that sounds like a stupid thing to rely on so having an incident response procedure might be much smarter!!!
The obvious thing would be to remove the dirauth if we are sure that it was an attack. Of course, there will need to be some investigation of the "was this an attack or a bug" type that might take some time...
Maybe we should add a BadSharedRandomnessAuth flag that will block a dirauth from this protocol till the investigation is complete. Or maybe this is a stupid idea.
What would an authority do when it detects a conflict under the new proposal? Ignore it (pick the numerically higher value?) and expect DocTor to detect it?
The spec seems to say:
When a conflict line is seen in a vote, an authority should verify the commit values (see [VALIDATEVALUES]) that they are in fact coming from the authority identified by "identity" and if so, ignore that authority until the next protocol run. If the conflict line is invalid, ignore it.
More on conflict detection on my next point.
What if an authority changes shared random signing keys partway through a round?
Good question! Fortunately, I think we can handle this.
First, we include the shared randomness key in the votes of each dirauth, then we also mandate that the authoritative commitments in each vote are signed by the current shared randomness key. This means that other dirauths should always be able to verify the signatures of the commitments in a vote.
Here is a proposed procedure to handle key rotation:
1) When Alice receives a valid commitment from dirauth Bob, it saves the commitment values (timestamp, H(REVEAL), etc.) and the shared randomness public key in its state.
2) When Alice, later in the protocol run, receives another valid commitment from dirauth Bob, it needs to verify the new signature and check that the commitment values *did not change*.
If the signature is valid and the commitment values are the same, then we consider the commitment and authority trusted. How does that sound to you?
We should probably write this procedure down in the spec, maybe.
And we should also have tests to ensure that this works smoothly, because as you said it definitely happen eventually.
---
However, key rotation *does* make the commit conflict mechanism more complicated.
The reason is that when Alice receives a conflict line from dirauth Bob:
"shared-rand-conflict" SP identity SP commit1 SP commit2 NL
she doesn't know which shared randomness key to use for which commit.
If she already knows a shared randomness key for 'identity', then she can try to use that to verify both signatures. However, the conflicting attacker could have rotated shared randomness keys and could have signed 'commit2' using a different SR key than 'commit1'. In this case, if Alice does not know both SR keys, she is unable to verify the validity of the conflict line. In that case, should she trust the conflict line or not?
I guess not, otherwise Bob could just craft fake conflict lines and feed them to other auths. However, if we don't trust the conflict line, then the attacker can again partition the authorities by causing everyone to ignore Bob's conflict line, whereas Bob will of course trust his own judgement.
A way to work around that problem would be if instead of 'identity', we include both cert chains in the "shared-rand-conflict" line so that the shared randomness keys are always available for verification.
But this adds extra complexity and logic to the conflict mechanism which is kind of useless anyway, since it only defends against dumb attacks.
Does anyone have another procedure for validating shared-rand-conflict lines that makes more sense?
Thanks!
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
asn,
Is it possible to add a field called 'NOTARY' in the COMMIT and REVEAL values where we include the SR pubkey + certificates and everything we need so that we can validate each COMMIT / REVEAL value and tie it to the identity of a directory authority any time?
Directory authorities will save to disk each COMMIT and REVEAL including the data required for signature validation (NOTARY field). Each authorities will include it in their votes also, and so on.
This way an authority can even use a different SR key for each COMMIT value broadcasted in a single day, if it's properly chained to the identity of that authority at the timestamp of the usage which is also recorded and individually verified.
This is what I was trying to suggest in the last part of my comment on #17349 but written it kind of pour there - I was confused about your 'other authorities save the SR key to disk statement' initially but it made total sense after reading the final complete proposal.
What if an authority changes shared random signing keys partway through a round?
Good question! Fortunately, I think we can handle this.
First, we include the shared randomness key in the votes of each dirauth, then we also mandate that the authoritative commitments in each vote are signed by the current shared randomness key. This means that other dirauths should always be able to verify the signatures of the commitments in a vote.
Here is a proposed procedure to handle key rotation:
- When Alice receives a valid commitment from dirauth Bob, it
saves the commitment values (timestamp, H(REVEAL), etc.) and the shared randomness public key in its state.
- When Alice, later in the protocol run, receives another valid
commitment from dirauth Bob, it needs to verify the new signature and check that the commitment values *did not change*.
If the signature is valid and the commitment values are the same, then we consider the commitment and authority trusted. How does that sound to you?
We should probably write this procedure down in the spec, maybe.
And we should also have tests to ensure that this works smoothly, because as you said it definitely happen eventually.
However, key rotation *does* make the commit conflict mechanism more complicated.
The reason is that when Alice receives a conflict line from dirauth Bob:
"shared-rand-conflict" SP identity SP commit1 SP commit2 NL
she doesn't know which shared randomness key to use for which commit.
If she already knows a shared randomness key for 'identity', then she can try to use that to verify both signatures. However, the conflicting attacker could have rotated shared randomness keys and could have signed 'commit2' using a different SR key than 'commit1'. In this case, if Alice does not know both SR keys, she is unable to verify the validity of the conflict line. In that case, should she trust the conflict line or not?
I guess not, otherwise Bob could just craft fake conflict lines and feed them to other auths. However, if we don't trust the conflict line, then the attacker can again partition the authorities by causing everyone to ignore Bob's conflict line, whereas Bob will of course trust his own judgement.
A way to work around that problem would be if instead of 'identity', we include both cert chains in the "shared-rand-conflict" line so that the shared randomness keys are always available for verification.
But this adds extra complexity and logic to the conflict mechanism which is kind of useless anyway, since it only defends against dumb attacks.
Does anyone have another procedure for validating shared-rand-conflict lines that makes more sense?
Thanks!
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
Hello,
Epic work. I agree that the code enforcing commit majority was not making a difference in the partition attack. I also agree that the partition attack is (almost) useless, expensive and very noisy. An attacker can get the same result if, instead of a partition attack where he has two shared random values to choose from, he simply does not participate at all in the protocol run and there's no shared random value for that day (assuming it's an odd total number and his vote could be decisive). At least this won't be that noisy and get him blown out of the consensus.
The SRDISASTER shared random value can be deterministically calculated (based on previous consensus agreed SR value). This means 12 hours earlier instead of the two different SR values that could result from a successful partition attack (the attacker will have to know the reveal values from the other authorities, then try to partition them, etc.).
I am adding some parts of the proposal with comments, with some quotes from the text in the proposal. Comments start with *:
4.1.1. Computing commitments and reveals [COMMITREVEAL] "The value REVEAL is computed as follows:
REVEAL = base64-encode( TIMESTAMP || RN )"
* Maybe it is useful to also sign the REVEAL value with the SR key for broadcasting, besides keeping the unsigned one for computing COMMIT which obviously needs a separate signature. It provides some security against little effort. Useful for directory authorities who miss the commitment phase and only participate in the reveal phase. Something like this (switched TIMESTAMP's place at the end):
REVEAL = base64-encode( RN || TIMESTAMP ) SIGNATURE = ed25519-sign( privkey=PRIVKEY, msg=RN || TIMESTAMP ) REVEAL_BROADCAST = base64-encode( RN || TIMESTAMP || SIGNATURE )
where the signature is performed using a special shared randomness ed25519 key [SRKEY].
* Note for both REVEAL_BROADCAST and COMMIT values: Is it mandatory to have TIMESTAMP in both SIGNATURE and final REVEAL_BROADCAST or COMMIT values? If not, maybe we can avoid the latter and rely only on the signed TIMESTAMP within SIGNATURE. Is there any chance the TIMESTAMP value won't be an exact match? All TIMESTAMP values must match exactly (in case the ed25519 signature will take a fraction of a second or so, since we are talking about unix timestamps).
4.1.2. Validating commitments and reveals [VALIDATEVALUES] "TIMESTAMP_R must be equal to TIMESTAMP_C else REVEAL is an invalid value for COMMIT."
* To be more explicit when defining validation, we should include that after checking the signatures and timestamps, it must also check if H(REVEAL) extracted from COMMIT value is indeed the hash sum (sha256sum in present case) of RN extracted from the REVEAL value.
* If we will sign the REVEAL values with the SR key also, include the additional validation steps required also.
4.1.7. Including the ed25519 shared randomness key in votes [SRKEY]
* This is a good idea, I don't have a strong argument against maintaining a separate SharedRandomKeyLifetime and adding more logic to load_ed_keys() for the SR key, but I do have a suggestion which could simplify it and use the already existent logic and failure recovery rules, the existent SigningKeyLifetime and the existent need_new_signing_key and want_new_signing_key. Simple is good, plus there is no additional security for keeping different expiration dates for the medium term signing key and SR key. SR key is hierarchically below medium term signing key one way or another. If this is a bad idea and messes up other parts of the design, apologies - let me know and I'll try to think of a different logic for SharedRandomkeyLifetime.
I have detailed it here: https://trac.torproject.org/projects/tor/ticket/17349#comment:12
Also adding the comments here: These checks should apply in AFTER finishing the existent checks for ed25519 keys as they are fully compatible on them and actually rely on them. The additional rules below should only apply if Tor is running as a directory authority, and should be ignored on normal relays.
1. On fresh start or HUP signal, after doing all the existent checks for ed25519 identity keys, only if we are an authority: also check if ed25519_shared_random_secret_key and ed25519_shared_random_cert files exist in $datadirectory/keys.
2. If these files are missing (or just one of them is missing, doesn't matter): generate a new ed25519_shared_random_secret_key and an ed25519_shared_random_cert chained to ed25519_signing_secret_key. When generating the ed25519_shared_random_cert, also check the expiration timestamp of ed25519_signing_cert and copy/paste it. Since Tor will first do the checks for ed25519_signing_secret_key and ed25519_signing_cert, and only after this, in order, the checks for ed25519_shared_random*, this step cannot go wrong.
3. If ed25519_shared_random_secret_key and ed25519_shared_random_cert both exist in $datadirectory/keys: 3.1 First, check if expiration timestamp of ed25519_shared_random_cert == expiration timestamp of ed25519_signing_cert. If not, it means the ed25519_signing_secret_key has changed, so delete ed25519_shared_random_secret_key and ed25519_shared_random_cert entirely and fail back to step 2.
3.2 Second, if the expiration timestamps in both certificates match, check if ed25519_shared_random_cert is valid and properly chains ed25519_shared_random_secret_key to ed25519_signing_secret_key. If they somehow do not match, delete ed25519_shared_random_secret_key and ed25519_shared_random_cert entirely and fail back to step 2.
4. Proceed if all these went well as normally. Unlike ed25519_signing_secret_key - when the ed25519_master_id_secret_key is kept offline or encrypted, there is no excuse for not being able to automatically generate an ed25519_shared_random_secret_key and ed25519_shared_random_cert if we follow all the steps in the logic order, so the above checks should be sufficient and leave us with 0 risk to end up with a Tor process running on a directory authority with no (or invalid) SR key.
5.3 Partition attack 5.3.2 During reveal phase "Let's consider Alice, a malicious directory authority. Alice could wait until the last reveal round, and reveal its value to half of the authorities. That would partition the authorities into two sets: the ones who think that the shared random value should contain this new reveal, and the rest who don't know about it. This would result in a tie and two different shared random value."
* The last reveal round? Clarification needed (maybe I mixed terminology here -- round = one vote at :00). Do we allow directory authorities to participate only in the last reveal round? This sounds like something very unlikely to happen normally, so I think we shouldn't allow this. What if we require at least 2 or 3 rounds of the reveal phase before we accept a dirauth in the SR protocol? If a dirauth is missing for 23 hours in a day, I think it should not be a part of the SR protocol in that day. At least one round before the pre-last round (last round is the one when consensus is computed and there's no time to identify and validate potential conflicts).
This won't make the partition attack any harder, the directory authorities will detect if more than 1 reveal value is sent by Alice and ignore her, but this won't help if Alice will send one reveal value to some directory authorities and NO reveal value to others.
"A similar attack is possible. For example, two rounds before the end of the reveal phase, Alice could advertise her reveal value to only half of the dirauths. This way, in the last reveal phase round, half of the dirauths will include that reveal value in their votes and the others will not. In the end of the reveal phase, half of the dirauths will calculate a different shared randomness value than the others."
* Right, maybe we could do something like this here: Since all COMMIT and REVEAL values are signed by their issuer AND the voter (they are included in all votes) other authorities could follow a simple rule like :
if (~50% from total number of directory authorities participating in the SR protocol -1) vote the same REVEAL value for directory authority "Alice" (with Alice's proper signature) and Alice doesn't vote the same REVEAL value for her in the final vote, enforce the reveal value broadcasted to the (~50% from total no of authorities participating - -1) and use it to calculate the SR value as like Alice included it in her vote also. This way Alice can't have two consensuses with different SR values: - - If she sends more than 1 REVEAL value to other directory authorities, it will be detected as conflict and she will be ignored when computing the SR value (if we require more rounds from REVEAL phase to accept a dirauth in the protocol). - - If she sends just 1 REVEAL value to exactly half of other directory authorities, SR value will be calculated with that reveal value sent by her (alice + other 50% = proper majority = ONE valid consensus) regardless she doesn't vote it for herself in her final vote.
Simple view of the problem: hey Alice you voted something so much (to 50% of the dirauths) but you don't want to admit it? It's ok, we know how to validate crypto signatures so we voted for you in your final vote, thanks.
I don't know how complicated this would make the code (if it's simple, it may be worth it). I am not entirely sure if this is worth our time since it's agreed that this attack is noisy, expensive and with very little return to the attacker.
On 10/28/2015 8:26 PM, David Goulet wrote:
Hello Tor-Dev!
We've almost completed the implementation [1] for prop#250 so we've reviewed part of the proposal to correct part of it to reflect reality (because you know a proposal is just wishful thinking until you implement it :).
Attached is the new version that we've been working on. We would like feedback from the community before at least calling it "ACCEPTED" and updated in tor-spec.git [2].
Here is a small summary of the big changes and also we need feedback on something that we are not fully in agreement.
First, period have been changed from 12:00 -> 12:00 (24 hour) to 00:00 -> 24:00 so the protocol run is not over two days. Seemed more logical and less confusing :).
Second, we've removed the need of having majority for a commit to be considered for the shared random computation. Yes this sounds intense!! so it needs your attention. We think that majority concept was only protecting us against was a partition attack during commit phase but it turns out that having a conflict detection mechanism (see COMMITCONFLICT section) already protect us of most of them during the commit phase except maybe one that is described in Section 5.3.1. With this proposal change, an authority only keeps commits that are authoritative that is a commit coming directly from an authority.
We've added section 5.3 on Partition Attack. Choosing commit by majority was protecting us against a partition attack in the commit phase but not all so with or without it, we still need an external monitoring party that makes sure attack are not ongoing (or bugs). DocTor is the obvious candidate so we'll work on a partition attacks detection since all of them are noisy and detectable.
A sub-section (4.1.7) has also been added which address the need of a shared random key that signs the commit values so they can be verified by other authorities [3].
Finally, we would like your opinion also on if we should keep the conflict mechanism or not?. Since those partition attacks are basically dumb, do not achive much result for an attacker and it's at a high cost of comprimising a directory authority, should we keep them? Keep in mind that it adds a layer of complexity in the code especially with shared random keys which rotates every 30 days and are only available in the vote of an authority. It gets difficult to validate a conflict of an authority if we haven't seen yet a vote from that authority. There are ways to fix that code wise but is this worth it considering that every partition attack will be detected anyway by DocTor? One argument to keep it is resilience of the protocol. With conflict line, if one dirauth does stupid things, it will get ignored for the rest of the protocol run so we can still compute a fresh random value in the end. Again, does it worth it?
Don't hesitate to ask about sections that are not clear or could be incorrect or you do not understand fully. Also, a ACK is a valid reply :).
Thanks to all! David
[1] https://trac.torproject.org/projects/tor/ticket/16943 [2] https://gitweb.torproject.org/torspec.git/tree/proposals/250-commit-re
veal-consensus.txt
[3] https://trac.torproject.org/projects/tor/ticket/17349
s7r s7r@sky-ip.org writes:
Hello,
Epic work. I agree that the code enforcing commit majority was not making a difference in the partition attack. I also agree that the partition attack is (almost) useless, expensive and very noisy. An attacker can get the same result if, instead of a partition attack where he has two shared random values to choose from, he simply does not participate at all in the protocol run and there's no shared random value for that day (assuming it's an odd total number and his vote could be decisive). At least this won't be that noisy and get him blown out of the consensus.
Thanks for the comments.
FWIW, here is the latest version of the spec: https://gitweb.torproject.org/user/asn/torspec.git/log/?h=prop250-final-v1
The main change here is that we removed the conflict detection feature. The rationale is the same as for removing the majority voting: it doesn't fix the root cause of partition attacks and it adds complexity to the code.
The SRDISASTER shared random value can be deterministically calculated (based on previous consensus agreed SR value). This means 12 hours earlier instead of the two different SR values that could result from a successful partition attack (the attacker will have to know the reveal values from the other authorities, then try to partition them, etc.).
I am adding some parts of the proposal with comments, with some quotes from the text in the proposal. Comments start with *:
4.1.1. Computing commitments and reveals [COMMITREVEAL] "The value REVEAL is computed as follows:
REVEAL = base64-encode( TIMESTAMP || RN )"
- Maybe it is useful to also sign the REVEAL value with the SR key for
broadcasting, besides keeping the unsigned one for computing COMMIT which obviously needs a separate signature. It provides some security against little effort. Useful for directory authorities who miss the commitment phase and only participate in the reveal phase. Something like this (switched TIMESTAMP's place at the end):
REVEAL = base64-encode( RN || TIMESTAMP ) SIGNATURE = ed25519-sign( privkey=PRIVKEY, msg=RN || TIMESTAMP ) REVEAL_BROADCAST = base64-encode( RN || TIMESTAMP || SIGNATURE )
where the signature is performed using a special shared randomness ed25519 key [SRKEY].
To be honest now that we removed the conflict detection code, the SR keys are almost useless, since there is already origin proof for authoritative commits/reveals by listing them on the signed vote.
I'm kinda contemplating removing the SR keys altogether, since that would remove another good 500+ lines of code. It would also simplify considerably our commit/reveal generation and verification procedures. It would also speed up the code review procedure.
I'm kind of sad for us killing all that nice code, but hey we can keep it in a branch and use it when we actually need to.
Let me know what you think here. Maybe i'm crazy.
- Note for both REVEAL_BROADCAST and COMMIT values:
Is it mandatory to have TIMESTAMP in both SIGNATURE and final REVEAL_BROADCAST or COMMIT values? If not, maybe we can avoid the latter and rely only on the signed TIMESTAMP within SIGNATURE. Is there any chance the TIMESTAMP value won't be an exact match? All TIMESTAMP values must match exactly (in case the ed25519 signature will take a fraction of a second or so, since we are talking about unix timestamps).
Hm, I didn't understand entirely what's the problem here?
BTW, in the code the timestamp is placed in both commit/reveal at the same time, not after the ed25519 signature creation.
4.1.2. Validating commitments and reveals [VALIDATEVALUES] "TIMESTAMP_R must be equal to TIMESTAMP_C else REVEAL is an invalid value for COMMIT."
- To be more explicit when defining validation, we should include that
after checking the signatures and timestamps, it must also check if H(REVEAL) extracted from COMMIT value is indeed the hash sum (sha256sum in present case) of RN extracted from the REVEAL value.
- If we will sign the REVEAL values with the SR key also, include the
additional validation steps required also.
Yes indeed. Please see: https://gitweb.torproject.org/user/asn/torspec.git/commit/?h=prop250-final-v...
This will need to change if we decide to remove SR keys.
4.1.7. Including the ed25519 shared randomness key in votes [SRKEY]
- This is a good idea, I don't have a strong argument against
maintaining a separate SharedRandomKeyLifetime and adding more logic to load_ed_keys() for the SR key, but I do have a suggestion which could simplify it and use the already existent logic and failure recovery rules, the existent SigningKeyLifetime and the existent need_new_signing_key and want_new_signing_key. Simple is good, plus there is no additional security for keeping different expiration dates for the medium term signing key and SR key. SR key is hierarchically below medium term signing key one way or another. If this is a bad idea and messes up other parts of the design, apologies - let me know and I'll try to think of a different logic for SharedRandomkeyLifetime.
I think I like your idea for having the SR key share the lifetime of the signing key. We should do this if we decide to keep SR keys.
I have detailed it here: https://trac.torproject.org/projects/tor/ticket/17349#comment:12
Also adding the comments here: These checks should apply in AFTER finishing the existent checks for ed25519 keys as they are fully compatible on them and actually rely on them. The additional rules below should only apply if Tor is running as a directory authority, and should be ignored on normal relays.
- On fresh start or HUP signal, after doing all the existent checks
for ed25519 identity keys, only if we are an authority: also check if ed25519_shared_random_secret_key and ed25519_shared_random_cert files exist in $datadirectory/keys.
- If these files are missing (or just one of them is missing, doesn't
matter): generate a new ed25519_shared_random_secret_key and an ed25519_shared_random_cert chained to ed25519_signing_secret_key. When generating the ed25519_shared_random_cert, also check the expiration timestamp of ed25519_signing_cert and copy/paste it. Since Tor will first do the checks for ed25519_signing_secret_key and ed25519_signing_cert, and only after this, in order, the checks for ed25519_shared_random*, this step cannot go wrong.
- If ed25519_shared_random_secret_key and ed25519_shared_random_cert
both exist in $datadirectory/keys: 3.1 First, check if expiration timestamp of ed25519_shared_random_cert == expiration timestamp of ed25519_signing_cert. If not, it means the ed25519_signing_secret_key has changed, so delete ed25519_shared_random_secret_key and ed25519_shared_random_cert entirely and fail back to step 2.
3.2 Second, if the expiration timestamps in both certificates match, check if ed25519_shared_random_cert is valid and properly chains ed25519_shared_random_secret_key to ed25519_signing_secret_key. If they somehow do not match, delete ed25519_shared_random_secret_key and ed25519_shared_random_cert entirely and fail back to step 2.
- Proceed if all these went well as normally. Unlike
ed25519_signing_secret_key - when the ed25519_master_id_secret_key is kept offline or encrypted, there is no excuse for not being able to automatically generate an ed25519_shared_random_secret_key and ed25519_shared_random_cert if we follow all the steps in the logic order, so the above checks should be sufficient and leave us with 0 risk to end up with a Tor process running on a directory authority with no (or invalid) SR key.
George Kadianakis desnacked@riseup.net writes:
s7r s7r@sky-ip.org writes:
Hello,
<snip>
4.1.1. Computing commitments and reveals [COMMITREVEAL] "The value REVEAL is computed as follows:
REVEAL = base64-encode( TIMESTAMP || RN )"
- Maybe it is useful to also sign the REVEAL value with the SR key for
broadcasting, besides keeping the unsigned one for computing COMMIT which obviously needs a separate signature. It provides some security against little effort. Useful for directory authorities who miss the commitment phase and only participate in the reveal phase. Something like this (switched TIMESTAMP's place at the end):
REVEAL = base64-encode( RN || TIMESTAMP ) SIGNATURE = ed25519-sign( privkey=PRIVKEY, msg=RN || TIMESTAMP ) REVEAL_BROADCAST = base64-encode( RN || TIMESTAMP || SIGNATURE )
where the signature is performed using a special shared randomness ed25519 key [SRKEY].
To be honest now that we removed the conflict detection code, the SR keys are almost useless, since there is already origin proof for authoritative commits/reveals by listing them on the signed vote.
I'm kinda contemplating removing the SR keys altogether, since that would remove another good 500+ lines of code. It would also simplify considerably our commit/reveal generation and verification procedures. It would also speed up the code review procedure.
I'm kind of sad for us killing all that nice code, but hey we can keep it in a branch and use it when we actually need to.
Let me know what you think here. Maybe i'm crazy.
and here is a spec change for this suggestion:
https://gitweb.torproject.org/user/asn/torspec.git/commit/?h=prop250-nosrkey...
Let me know what you think.
On 06 Nov (15:35:50), George Kadianakis wrote:
George Kadianakis desnacked@riseup.net writes:
s7r s7r@sky-ip.org writes:
Hello,
<snip>
4.1.1. Computing commitments and reveals [COMMITREVEAL] "The value REVEAL is computed as follows:
REVEAL = base64-encode( TIMESTAMP || RN )"
- Maybe it is useful to also sign the REVEAL value with the SR key for
broadcasting, besides keeping the unsigned one for computing COMMIT which obviously needs a separate signature. It provides some security against little effort. Useful for directory authorities who miss the commitment phase and only participate in the reveal phase. Something like this (switched TIMESTAMP's place at the end):
REVEAL = base64-encode( RN || TIMESTAMP ) SIGNATURE = ed25519-sign( privkey=PRIVKEY, msg=RN || TIMESTAMP ) REVEAL_BROADCAST = base64-encode( RN || TIMESTAMP || SIGNATURE )
where the signature is performed using a special shared randomness ed25519 key [SRKEY].
To be honest now that we removed the conflict detection code, the SR keys are almost useless, since there is already origin proof for authoritative commits/reveals by listing them on the signed vote.
I'm kinda contemplating removing the SR keys altogether, since that would remove another good 500+ lines of code. It would also simplify considerably our commit/reveal generation and verification procedures. It would also speed up the code review procedure.
I'm kind of sad for us killing all that nice code, but hey we can keep it in a branch and use it when we actually need to.
Let me know what you think here. Maybe i'm crazy.
and here is a spec change for this suggestion:
https://gitweb.torproject.org/user/asn/torspec.git/commit/?h=prop250-nosrkeys-v1&id=4a799b3b5b7955a1b3b07475ae341c37b29c1f3b
Let me know what you think.
It's indeed weird to keep lots of code and a section in the proposal that actually is useless. The only argument I can see to keep it is for "future use" if we want to start addressing partition attack directly in the code for instance or other _unknown_ design flaw.
That being said, I think we can knife it. The code will still exists in a branch somewhere and we are starting to get quite a good understanding of the problem space here ;).
Now question about the commit above ^:
+ where the ID_a value is the identity key fingerprint of authority 'a' and R_a + is the corresponding reveal value of that authority for the current period.
We had this discussion before and also asked Nick about this. We should _NOT_ use the RSA key here of the authority and as far as I know we don't have the ed25519 key of an authority accessible in the vote?
Also, the TIMESTAMP was removed. Can you explain why? I like it even though it doesn't have a direct practical use in the protocol. With it we can know when the authority generated its commit and it's an extra nice check to match commit/reveal value (you know avoiding unknown crazy replay attack :P). I see it useful for debugging potential issues in the long run since in the vote (and sr-state) we'll have a data point on when the authority did generate that commitment.
Apart from that, I vote go on the removal of SR keys.
Cheers! David
tor-dev mailing list tor-dev@lists.torproject.org https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
Hi,
I am fine with that.There is no sense going only half way here. So, without the conflict code, there is no sense keeping a SR key. The only source of authentication will be the normal signature of the vote.
We should keep the older version of the proposal (with conflict code and SR key) and the code in a branch somewhere, and the design in our heads, so we can get back to it in the future if we need to do so.
For the old version of the proposal (with conflict code) I think we should add/change:
- - It is mandatory to sign with the SR key REVEAL in a separate REVEAL_BROADCAST saved to persistent. Only the signed REVEAL will be broadcasted in the reveal phase, so authorities can participate only in this phase of the protocol.
- - SR key should have the same lifetime as SigningKeyLifetime and use the need_new_signing_key and want_new_signing_key as per the logic described in my previous email on trac.
For all versions of the proposal, regardless if we use the conflict code or not, I think we should require authorities to participate for at least for 3 rounds of the reveal phase, otherwise not participate in the shared randomness calculation for the day.
This does not have a significant effect over the partitioning attack (which we agreed there's no sense addressing) but it may prevent consensus conflicts that could lead to SRDISASTER or accidental partitioning, in case an authority simply joins too late and for a reason or other doesn't catch up with the rest of the votes from other authorities. Plus, I don't see a reason for why we shouldn't require this - the probability for an authority to be genuinely available _only_ for the last reveal round is reasonably low. Also, if an authority was absent for > 23 hours in a day, not allowing it to participate in the shared randomness calculation for that day only is not an unusual or abusive punishment.
If an authority was present and voted in that protocol run before hour - -3, but missed hour -3, it should be allowed to participate. Basically require to have at least 3 reveal votes in the reveal phase of a single day to make sure it has quite low chances not to be in sync. Or we could only require the last 3 reveal rounds from 21:00 UTC or hour - -3 to hour 0.
This will be decided just by looking from code simplicity point of view, as in terms of security and followed goal both provide the same effect. I am equally fine with both approaches (but it's very much more unlikely to miss 3 rounds (votes) during ALL the reveal phase as opposite to missing the last 3 consecutive ones).
What do you think?
On 11/6/2015 3:35 PM, George Kadianakis wrote:
George Kadianakis desnacked@riseup.net writes:
s7r s7r@sky-ip.org writes:
Hello,
<snip>
4.1.1. Computing commitments and reveals [COMMITREVEAL] "The value REVEAL is computed as follows:
REVEAL = base64-encode( TIMESTAMP || RN )"
- Maybe it is useful to also sign the REVEAL value with the SR
key for broadcasting, besides keeping the unsigned one for computing COMMIT which obviously needs a separate signature. It provides some security against little effort. Useful for directory authorities who miss the commitment phase and only participate in the reveal phase. Something like this (switched TIMESTAMP's place at the end):
REVEAL = base64-encode( RN || TIMESTAMP ) SIGNATURE = ed25519-sign( privkey=PRIVKEY, msg=RN || TIMESTAMP ) REVEAL_BROADCAST = base64-encode( RN || TIMESTAMP || SIGNATURE )
where the signature is performed using a special shared randomness ed25519 key [SRKEY].
To be honest now that we removed the conflict detection code, the SR keys are almost useless, since there is already origin proof for authoritative commits/reveals by listing them on the signed vote.
I'm kinda contemplating removing the SR keys altogether, since that would remove another good 500+ lines of code. It would also simplify considerably our commit/reveal generation and verification procedures. It would also speed up the code review procedure.
I'm kind of sad for us killing all that nice code, but hey we can keep it in a branch and use it when we actually need to.
Let me know what you think here. Maybe i'm crazy.
and here is a spec change for this suggestion:
https://gitweb.torproject.org/user/asn/torspec.git/commit/?h=prop250-nosrkey...
Let me know what you think.
On 8 Nov 2015, at 05:39, s7r s7r@sky-ip.org wrote:
For all versions of the proposal, regardless if we use the conflict code or not, I think we should require authorities to participate for at least for 3 rounds of the reveal phase, otherwise not participate in the shared randomness calculation for the day.
This does not have a significant effect over the partitioning attack (which we agreed there's no sense addressing) but it may prevent consensus conflicts that could lead to SRDISASTER or accidental partitioning, in case an authority simply joins too late and for a reason or other doesn't catch up with the rest of the votes from other authorities. Plus, I don't see a reason for why we shouldn't require this - the probability for an authority to be genuinely available _only_ for the last reveal round is reasonably low. Also, if an authority was absent for > 23 hours in a day, not allowing it to participate in the shared randomness calculation for that day only is not an unusual or abusive punishment.
If an authority was present and voted in that protocol run before hour -3, but missed hour -3, it should be allowed to participate. Basically require to have at least 3 reveal votes in the reveal phase of a single day to make sure it has quite low chances not to be in sync. Or we could only require the last 3 reveal rounds from 21:00 UTC or hour -3 to hour 0.
This will be decided just by looking from code simplicity point of view, as in terms of security and followed goal both provide the same effect. I am equally fine with both approaches (but it's very much more unlikely to miss 3 rounds (votes) during ALL the reveal phase as opposite to missing the last 3 consecutive ones).
What do you think?
Whatever we decide, can we make it a torrc option? That way, authorities running the SR code can bootstrap relatively quickly in test networks. (The fastest possible bootstrap would have 1 SR commit round and 1 SR reveal round.)
Tim
Tim Wilson-Brown (teor)
teor2345 at gmail dot com PGP 968F094B
teor at blah dot im OTR CAD08081 9755866D 89E2A06F E3558B7F B5A9D14F