mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-24 22:32:15 +00:00
docs: Update secure-p2p doc to match the spec + current implementation
Closes #2421. I am of the opinion that the spec is easier to read than this though, and we shouldn't really explain this here other than that we use a variant of station to station protocol, with X25519 for the diffie hellman, and we describe the related security properties.
This commit is contained in:
parent
8aad09d9d4
commit
f76312ffe6
@ -8,41 +8,43 @@ Each peer generates an ED25519 key-pair to use as a persistent
|
||||
(long-term) id.
|
||||
|
||||
When two peers establish a TCP connection, they first each generate an
|
||||
ephemeral ED25519 key-pair to use for this session, and send each other
|
||||
ephemeral X25519 key-pair to use for this session, and send each other
|
||||
their respective ephemeral public keys. This happens in the clear.
|
||||
|
||||
They then each compute the shared secret. The shared secret is the
|
||||
multiplication of the peer's ephemeral private key by the other peer's
|
||||
ephemeral public key. The result is the same for both peers by the magic
|
||||
of [elliptic
|
||||
curves](https://en.wikipedia.org/wiki/Elliptic_curve_cryptography). The
|
||||
shared secret is used as the symmetric key for the encryption algorithm.
|
||||
They then each compute the shared secret, as done in a [diffie hellman
|
||||
key exhange](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange).
|
||||
The shared secret is used as the symmetric key for the encryption algorithm.
|
||||
|
||||
The two ephemeral public keys are sorted to establish a canonical order.
|
||||
Then a 24-byte nonce is generated by concatenating the public keys and
|
||||
hashing them with Ripemd160. Note Ripemd160 produces 20byte hashes, so
|
||||
the nonce ends with four 0s.
|
||||
We then run [hkdf-sha256](https://en.wikipedia.org/wiki/HKDF) to expand the
|
||||
shared secret to generate a symmetric key for sending data,
|
||||
a symmetric key for receiving data,
|
||||
a challenge to authenticate the other party.
|
||||
One peer will send data with their sending key, and the other peer
|
||||
would decode it using their own receiving key.
|
||||
We must ensure that both parties don't try to use the same key as the sending
|
||||
key, and the same key as the receiving key, as in that case nothing can be
|
||||
decoded.
|
||||
To ensure this, the peer with the canonically smaller ephemeral pubkey
|
||||
uses the first key as their receiving key, and the second key as their sending key.
|
||||
If the peer has the canonically larger ephemeral pubkey, they do the reverse.
|
||||
|
||||
The nonce is used to seed the encryption - it is critical that the same
|
||||
nonce never be used twice with the same private key. For convenience,
|
||||
the last bit of the nonce is flipped, giving us two nonces: one for
|
||||
encrypting our own messages, one for decrypting our peer's. Which ever
|
||||
peer has the higher public key uses the "bit-flipped" nonce for
|
||||
encryption.
|
||||
Each peer also keeps a received message counter and sent message counter, both
|
||||
are initialized to zero.
|
||||
All future communication is encrypted using chacha20poly1305.
|
||||
The key used to send the message is the sending key, and the key used to decode
|
||||
the message is the receiving key.
|
||||
The nonce for chacha20poly1305 is the relevant message counter.
|
||||
It is critical that the message counter is incremented every time you send a
|
||||
message and every time you receive a message that decodes correctly.
|
||||
|
||||
Now, a challenge is generated by concatenating the ephemeral public keys
|
||||
and taking the SHA256 hash.
|
||||
|
||||
Each peer signs the challenge with their persistent private key, and
|
||||
Each peer now signs the challenge with their persistent private key, and
|
||||
sends the other peer an AuthSigMsg, containing their persistent public
|
||||
key and the signature. On receiving an AuthSigMsg, the peer verifies the
|
||||
signature.
|
||||
|
||||
The peers are now authenticated.
|
||||
|
||||
All future communications can now be encrypted using the shared secret
|
||||
and the generated nonces, where each nonce is incremented by one each
|
||||
time it is used. The communications maintain Perfect Forward Secrecy, as
|
||||
The communication maintains Perfect Forward Secrecy, as
|
||||
the persistent key pair was not used for generating secrets - only for
|
||||
authenticating.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user