Skip to content

Instantly share code, notes, and snippets.

@ryanxcharles
Last active February 26, 2019 17:21
Show Gist options
  • Save ryanxcharles/c29fc94d31de7c8c89dc to your computer and use it in GitHub Desktop.
Save ryanxcharles/c29fc94d31de7c8c89dc to your computer and use it in GitHub Desktop.
Security Protocols for Wallet Creation and Communication in Copay

There are two communication phases for a Copay wallet: The wallet creation phase, which is when the copayers do not yet know the public keys of the other copayers. Then the wallet usage phase, where the copayers do know the public keys of the other copayers.

Each copayer independently generates a master extended public/private key pair before wallet creation which can be used to derive further public/private keys deterministically.

Wallet Creation

The author of the wallet derives a new public/private key pair for the communication purposes. This is the communication public/private key pair of the author.

The hash of the communication public key is used as the PeerJS id.

The wallet creation id is the communication public key of the author. The PeerJS id of the author can be found by hashing this public key.

The wallet creation id is shared with the other copayers so they can join the wallet. The other copayers use the PeerJS id to find the wallet author so they can communicate.

To encrypt messages, each copayer uses the communication public key of the author to find a shared secret that they use to encrypt messages to the wallet author using ECIES (elliptic curve integrated encryption scheme).

The copayer signs each encrypted message with their communication private key.

As each copayer joins the wallet, they add their communication public key to the wallet. Each copayer establishes a p2p connection to each other copayer. The PeerJS id for each copayer is found by hashing the communication public key for that copayer. Each message is encrypted using the communication public key of each other copayer and finding a shared secret that is different for each other copayer.

A separate shared secret is established for every outbound connection. If Peer A sends a message to Peer B, they use shared secret 1. If Peer B sends a message to Peer A, they use shared secret 2. It is not necessary for shared secret 1 to be equal to shared secret 2.

When all N copayers have joined the wallet, the wallet is complete, and normal wallet usage begins.

Wallet Usage

During wallet usage it is not necessary for all copayers to connect to the wallet author. They directly connect to all other copayers instead, and they only connect to the author if the author is online.

As during wallet creation, the copayer uses the communication public key of each of the other copayers in order to arrive at a shared secret that is used to encrypt messages to that copayer.

Each copayer always signs every message after it is encrypted with their communication private key.

Notes

  • During the wallet creation phase, MITM attacks are possible since the public keys of the copayers are not yet known by the other copayers. Each copayer should confirm the public key they receive for each copayer is accurate using an existing secure communications channel.
  • After the public keys are accurately shared to all other copayers, no MITM attacks are possible, and all communications are private and authenticated.
  • We do not rely on the authentication or encryption of Web RTC since it relies on self-signed certificates that are subject to MITM attacks.
@ryanxcharles
Copy link
Author

Yes, it is still necessary to confirm in an existing secure communications channel that the public keys are accurate in order to prevent MITM attacks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment