pcp
- Peer Copy
Command line peer-to-peer data transfer tool based on libp2p.
Table of Contents
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.
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
you'll see four random words from a list of the Bitcoin improvement proposal BIP39.
There are lists in nine different languages of 2048 words each, currently only english
is supported.
The first word is interpreted as a channel ID in the range from 0 to 2047.
pcp
advertises the identifier /pcp/{unix-timestamp}/{channel-id}
in its local network via mDNS and a hashed version of this string in the DHT of IPFS.
The unix timestamp is the current time truncated to 5 minutes and the prefix /pcp
is the protocol prefix.
In the future: When you enter a new 5-minute interval while pcp send
is running it advertises an updated identifier.
To receive the file 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.
It also searches for an identifier of the previous 5-minute interval.
As soon as the peer is found, both do a password authenticated key exchange (PAKE) to authenticate each other.
In this procedure a comparably weak password (four-words-from-above
) gets replaced with a strong session key that is used to encrypt all future communication.
The default TLS encryption that libp2p provides is not sufficient in this case as we could still, in theory, talk to a wrong peer - just encrypted.
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 archive for
your platform.
From source
To compile it yourself run:
go install github.com/dennis-tra/pcp/cmd/pcp@latest # 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
brew install dennis-tra/homebrew-tap/pcp
It's on the roadmap to distribute pcp
via apt
, yum
, 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
:
- allows any two computers to transfer data (using a relay)
- provides end-to-end encryption (using PAKE)
- enables easy cross-platform transfers (Windows, Linux, Mac)
- ✅ Linux <-> Mac, ❌ Windows, but it's planned!
- allows multiple file transfers
- ✅ it allows transferring directories
- allows resuming transfers that are interrupted
- local server or port-forwarding not needed
- ipv6-first with ipv4 fallback
- can use proxy, like tor
You can find a project plan in the project tab of this page.
Some other ideas I would love to work on include:
- browser interop via the means of js-libp2p
- experimental decentralised NAT hole punching via DHT signaling servers - Project Flare
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 :)
Maintainers
@dennis-tra.
Acknowledgments
go-libp2p
- The Go implementation of the libp2p Networking Stack.
pake/v2
- PAKE library for generating a strong secret between parties over an insecure channel
progressbar
- A really basic thread-safe progress bar for Golang applications
Contributing
Feel free to dive in! Open an issue or submit PRs.
Support
It would really make my day if you supported it through Buy Me A Coffee.
Other Projects
You may be interested in one of my other projects:
image-stego
- A novel way to image manipulation detection. Steganography-based image integrity - Merkle tree nodes embedded into image chunks so that each chunk's integrity can be verified on its own.
License
Apache License Version 2.0 © Dennis Trautwein