pcp - Peer Copy

Command line peer-to-peer data transfer tool based on libp2p.

pcp-v

Motivation

There already exists a long list of file transfer tools (see Related Efforts), so why bother
building another one? The problem I had with the existing tools is that they rely on
a limited set of servers
to orchestrate peer matching and data relaying which poses a centralisation concern. Many of the usual centralisation
vs. decentralisation arguments apply here, e.g. the servers are single points of failures, the service operator has the
power over whom to serve and whom not, etc. Further, as
this recent issue in croc shows, this is a real risk for sustainable
operation of the provided service. A benevolent big player jumped in to sponsor the service.

Project Status

The tool is in a very early stage, and I'm aware of performance, usability and security issues. Don't use it for anything serious.
Although I criticised tools like magic-wormhole or croc above, they are amazing and way more mature.

There are also drawbacks with this approach: It's slower than established centralised methods if
you want to transmit data across network boundaries. A DHT query to find your peer can easily take several minutes.
Further, the bandwidth and geographic location of a potential relaying peer is not guaranteed which can lead to long transmission times.

How does it work?

When running pcp send a new peer identity is generated.
The first bytes of the public key are encoded in four words from the Bitcoin improvement proposal BIP39, so each word is basically random among the 2048 possible words. The first word is interpreted as a channel ID in the range from 0 to 2047.
pcp advertises in its local network via mDNS and in the DHT of IPFS the identifier /pcp/{unix-timestamp}/channel-id.
The unix timestamp is the current time truncated to 5 minutes and the prefix /pcp is the protocol prefix.

Your peer enters pcp receive four-words-from-above and pcp uses the first word together with the current time truncated to 5 minutes to find the sending peer in the DHT and in your local network via mDNS.
When the peer is found, its public key is checked against the three remaining words (as the words were derived from that key), and a password authenticated key exchange happens to authenticate each other.
The key exchange is not used for encryption as the connection uses TLS per default. After the peer is authenticated the receiver must confirm the file transfer, and the file gets transmitted.

Usage

The sending peer runs:

$ pcp send my_file
Code is:  bubble-enemy-result-increase
On the other machine run:
	pcp receive bubble-enemy-result-increase

The receiving peer runs:

$ pcp receive bubble-enemy-result-increase
Looking for peer bubble-enemy-result-increase...

If you're on different networks the lookup can take quite long (~ 2-3 minutes). Currently, there is no output while both parties are working on peer discovery, so just be very patient.

Install

Release download

Head over to the releases and download the latest binary for
your platform.

From source

To compile it yourself clone the repository:

git clone https://github.com/dennis-tra/pcp.git

Navigate into the pcp folder and run:

go install cmd/pcp/pcp.go # Go 1.13 or higher is required

Make sure the $GOPATH/bin is in your PATH variable to access the installed pcp executable.

Package managers

It's on the roadmap to distribute pcp via apt, yum, brew, scoop and more ...

Development

Protobuf definitions

First install the protoc compiler:

make tools # downloads gofumpt and protoc
make proto # generates protobuf

The current proto definitions were generated with libprotoc 3.14.0.

Feature Roadmap

Shamelessly copied from croc:

  • [x] allows any two computers to transfer data (using a relay)
  • [x] provides end-to-end encryption (using PAKE)
    • ✅ actually PAKE is only used for authentication TLS for end-to-end encryption
  • [x] enables easy cross-platform transfers (Windows, Linux, Mac)
    • 🤔✅ only tested Linux <-> Mac
  • [ ] allows multiple file transfers
    • ❌ not yet
  • [ ] allows resuming transfers that are interrupted
    • ❌ not yet
  • [x] local server or port-forwarding not needed
  • [ ] ipv6-first with ipv4 fallback
    • 🤔 I think that's the case, but I'm not sure about the libp2p internals
  • [ ] can use proxy, like tor
    • ❌ not yet

Related Efforts

  • croc - Easily and securely send things from one computer to another
  • magic-wormhole - get things from one computer to another, safely
  • dcp - Remote file copy, powered by the Dat protocol.
  • iwant - CLI based decentralized peer to peer file sharing
  • p2pcopy - Small command line application to do p2p file copy behind firewalls
    without a central server.
  • zget - Filename based peer to peer file transfer
  • sharedrop - Easy P2P file transfer powered by WebRTC - inspired by Apple
    AirDrop
  • filepizza - Peer-to-peer file transfers in your browser
  • toss - Dead simple LAN file transfers from the command line
  • Forgot yours? Open an issue or submit a PR :)

GitHub