Closed Shadowfiend closed 5 years ago
sending the staking address to the bootstrap node, signed by the staking key, perhaps…
Shouldn't we send some random challenge instead of expecting the new node to sign always the same thing (address is constant, right?). If I were an adversary able to sniff the network, I'd use the same signature to prove my (false) identity.
I think that we should generate a random message (cryptographically strong)
After we know in the Go code that we have a real address we can ask the Geth server if the person is staked.
Am I understanding this - or - did I goof it up?
On Mon, Aug 20, 2018 at 8:19 AM pdyraga notifications@github.com wrote:
sending the staking address to the bootstrap node, signed by the staking key, perhaps…
Shouldn't we send some random challenge instead of expecting the new node to sign always the same thing (address is constant, right?). If I were an adversary able to sniff the network, I'd use the same signature to prove my (false) identity.
— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/keep-network/keep-core/issues/9#issuecomment-414332610, or mute the thread https://github.com/notifications/unsubscribe-auth/AAhMQa2Cbn-1xPqeU8vFr3G6MVGbe2qgks5uSsV3gaJpZM4Qg8FG .
-- Philip Schlump
If the signed data is not generated by the verifier and signature is not checked against the verifier-generated data, then the adversary may replicate some historical message.
Yah, replay attack is definitely a problem here, excellent point. Challenge seems like a reasonable solution, but the downside is it requires the bootstrap nodes to challenge all nodes that join, which feels like a potential bottleneck. We could have the connector sign their own multiaddr. The recipient should be able to compare the multiaddr in the message with the multiaddr that is connecting to verify that it's correct. Only question there is whether multiaddrs can be spoofed by a sender.
Is there a sequence number, timestamp, or other incrementing piece of data that can be used to prevent replays?
but the downside is it requires the bootstrap nodes to challenge all nodes that join, which feels like a potential bottleneck
I think it's even worse - the joining nodes should challenge the bootstrap one as well.
Is there a sequence number, timestamp, or other incrementing piece of data that can be used to prevent replays?
I've been thinking about using some data from the current block, but it's possible we'll have multiple threshold relay requests within a single block and then, an adversary can prepare attack under concurrent composition.
We could have the connector sign their own multiaddr.
But the connector we'll use the same multiaddr in several groups it participates in, right? So it's still vulnerable for a replay attack.
This isn't about authenticating during group join; that's handled by the group formation protocol we're working on for the yellowpaper (and does have an on-chain component). This is about proving a given node is allowed to access the Keep p2p network at all; it should ideally be one time per connection.
I've been thinking about using some data from the current block, but it's possible we'll have multiple threshold relay requests within a single block and then, an adversary can prepare attack under concurrent composition.
I was thinking about each message including a commitment to the last sent or received message, rather than relying on on-chain consensus. As long as we validate that commitment we'll have a replay mitigation.
If we need an initial signature, maybe the first message if always a response to a node's challenge?
by verifying a randomly generated message it will not be possible to have a re-play attack.
On Tue, Aug 21, 2018 at 8:33 AM Matt Luongo notifications@github.com wrote:
I've been thinking about using some data from the current block, but it's possible we'll have multiple threshold relay requests within a single block and then, an adversary can prepare attack under concurrent composition.
I was thinking about each message including a commitment to the last sent or received message, rather than relying on on-chain consensus.
If we need an initial signature, maybe the first message if always a response to a bootstrap node's challenge?
— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/keep-network/keep-core/issues/9#issuecomment-414695408, or mute the thread https://github.com/notifications/unsubscribe-auth/AAhMQWS-AxiKUKZ0d9M0hoFrv1bXgU05ks5uTBosgaJpZM4Qg8FG .
-- Philip Schlump
A new node (NN) makes a request to a bootstrap node (BB) to participate.
NN sends to BB - Hi - I want to talk to you :
BB verifies the signature to check that the address is correct
BB call HasMinimumStake ( address )
to verify that they are staked and can participate
If BB finds that the signature is valid and that they are staked then BB sends back to NN
1. Ok - I like you.
2. a signed random message using my key
3. my signature of the message
4. my address
NN then validates the signature from BB.
NN checks that they got back the expected address.
They are now connected and validated.
To prevent replaying the message BB saves the random message - and disallows the use of that random message in the future.
Couple of thoughts on this approach:
(I have made some adjustments to eliminate the possibility of a replay attack)
A new node (NN) makes a request to the bootstrap (BB). It gets back a random token. BB saves the random token for 1 minute or until the token has been used once. The one minute is the time window when the token is valid.
NN sends to BB - Hi - I want to talk to you :
0. The keccak256 hash of the random token and the message
1. my signed random message
2. my signature
3. my address
3. my message
BB deletes it copy of the random token that matches what was sent. The random token can never be used again.
BB verifies the signature to check that the address is correct
BB call HasMinimumStake ( address )
to verify that they are staked and can participate
If BB finds that the signature is valid and that they are staked then BB sends back to NN
1. Ok - I like you.
2. a signed random message using my key
3. my signature of the message
4. my address
NN then validates the signature from BB.
NN checks that they got back the expected address.
They are now connected and validated.
This is closer. Again, need a better understanding of how secure multiaddrs are (that is, given a message M signed with signature S from a multiaddr A that includes a peer ID P, can I verify that signature S was indeed signed by the key associated with peer ID P, and therefore that it was in fact multiaddr A that generated that signature?). If they're secure, I think the rest of this becomes a bit simpler.
@Shadowfiend It’s secure in the sense that if you tell me you’re at /ip4/127.0.0.1/udp/9090/quic/peerID
, and I can’t dial + challenge you back at that location, that’s a no go.
A peerID
has a 1:1 correspondence to a public key THOUGH we should explore all of the different encodings offered here.
To your example, given a message M
signed with signature S
from a multiaddr A
that includes a peer ID P
, I verify that signature S
was signed by the key associated with peer ID P
by calling the method that goes from peer.ID
-> publicKey
and then pubKey.Verify(message, sig)
. Lastly, I ensure that multiAddr A
is indeed a valid location by either confirming that I did indeed receive a message M
from that multiaddr A
OR pinging multiaddr A
. Is this what you were looking for?
The signing of the multiaddrs + nonce are great ideas, and adds layers where an adversary may try to mitm a challenge - response cycle.
This is covered in #302, #304, #311 . Closing to avoid duplicates.
This will be done in a bootstrap node.
Proving stake here can start with sending the staking address to the bootstrap node, signed by the staking key, perhaps… This should allow the bootstrap node to verify that the signature on the staking address is correct for that address, and then check the network to ensure the address in question is staked.
We need to figure out whether the above approach is correct and implementable, or if we need a different one instead.
Let's use this issue to discuss implementation, and then spin up separate issues for proving stake and blocking unproven clients when we're ready to start working on them.