near / mpc

40 stars 15 forks source link

Secure p2p communication #329

Closed itegulov closed 10 months ago

itegulov commented 12 months ago

Description

As per the security requirements of the protocol, communication between nodes should be private (i.e. the contents of communication between each pair of nodes cannot be open to any other party).

This means we need one of the two approaches explored below. Regardless of which one the assignee chooses, make sure to communicate your choice as it might impact other multichain efforts (extra state in the contract, networking etc).

(Option 1) Asymmetric cryptography

Each node manages one HPKE keypair and one EDDSA keypair to encrypt all outgoing messages and then sign them. Recommended libraries: ed25519-dalek and hpke-rs/rust-hpke

Theoretically, it is possible to use one key for both signing and encryption, but usually, it is not a good idea as it exposes us to many vectors of attacks. There is little reason to sacrifice that for the slight inconvenience of having to manage one more key.

Nodes have to make the two public keys known to everyone else, so it probably makes sense to put that information in the multichain consensus smart contract.

(Option 2) Symmetric cryptography

All pairs of nodes maintain a key for both the encryption of plaintext and the decryption of ciphertext. Meaning that each node has to manage $N - 1$ keys. Recommended library: AES-GCM.

I have not explored this option very well, but my layman's perspective is that you would use some sort of key-agreement protocol to establish a common symmetric-key cipher. You might have to redo the protocol each time the connection is severed.

ChaoticTempest commented 11 months ago

I believe option 1 is best, since the key-agreement protocol AFAIU would require us to do key-exchange over asymmetric cryptography anyways. The downside of redoing the protocol each time the connection gets severed makes option 1 preferred for stability, since adding extra complexity for key-agreement over storing the public keys on the contract doesn't seem worth it.

The only benefit of option 2 I see is being able to transmit large amounts of data more efficiently, but then I can see us just doing a hybrid version of this where we utilize option 1 as the key exchange, and then switch symmetric when it comes to larger messages that needs to be passed on later. In which case, option 2 is just an optimization and we can defer this to later