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.
@matiu
Copy link

matiu commented May 30, 2014

Given that H:

  • has control of the PeerJS server,
  • and access to the share secret
  • and can setup a MIMA for webRTC

the problem with the current schema is:

  1. H has control over the PeerJS server.
  2. Alice shares the secret with Bob
  3. H(acker) intercepts the message and extract Alice's Copayer ID, derives
    Alice's PeerId and extract network key.
  4. When Bob tries to connect with Alice, H detects that someone is trying to connect
    to Alice's PeerID, so it setup a man-in-the-middle (MIMA) attack, and setup the connection,
    while having access to all communication.
  5. Since communications are signed and encrypted using the shared network key, H can
    what all communications, so H can obtain Alice and Bob's extended public keys, so
    once the wallet start been use, we will be able to see transactions and balances, but
    not spend wallet's funds. H can even forge messages, and send them to the wallet members,
    but at a higher level the messages will be rejected: He cannot create transaction proposals
    (he cannot sign them).

Using ECIES, with the same H:

  1. Alice shares 'wallet creation id' with Bob
  2. H(acker) intercepts the message and extract Alice's Copayer ID, derives
    Alice's PeerId and Alice's Public key.
  3. When Bob tries to connect with Alice, H detects that someone is trying to connect
    to Alice's PeerID, so it setup a man-in-the-middle (MIMA) attack:
    • H can sends encrypted messages to Alice using Alice pub key, but sign them with his own pubkey. Alice can not distinguish from Bob and H, so she assumes she is communication with Bob.
  - H cannot forge Alice messages to Bob: H cannot sign them, since he hasn't Alice Private key, but
  we can forward and decrypt Alice's messages to Bob. And H can forge messages from Bob.

So, given an attacker with the same power, we can:
- eve-drop all wallet messages
- forge messages from all copayers but the creator of the wallet.
- stay unnoticed

@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