1
1
Fork 0
mirror of https://github.com/schollz/croc.git synced 2025-10-11 05:11:06 +02:00

update readme

This commit is contained in:
Zack Scholl 2018-06-26 21:41:59 -07:00
parent fc7dcc5e0a
commit af92a47450
2 changed files with 16 additions and 14 deletions

View file

@ -12,7 +12,7 @@
*croc* allows any two computers to directly and securely transfer files and folders. When sending a file, *croc* generates a random code phrase which must be shared with the recipient so they can receive the file. The code phrase encrypts all data and metadata and also serves to authorize the connection between the two computers in a intermediary relay. The relay connects the TCP ports between the two computers and does not store any information (and all information passing through it is encrypted).
## New version released June 24th, 2018 - please upgrade if you are using the public relay.
**New version released June 24th, 2018 - please upgrade if you are using the public relay.**
I hear you asking, *Why another open-source peer-to-peer file transfer utilities?* [There](https://github.com/cowbell/sharedrop) [are](https://github.com/webtorrent/instant.io) [great](https://github.com/kern/filepizza) [tools](https://github.com/warner/magic-wormhole) [that](https://github.com/zerotier/toss) [already](https://github.com/ipfs/go-ipfs) [do](https://github.com/zerotier/toss) [this](https://github.com/nils-werner/zget). But, after review, [I found it was useful to make another](https://schollz.github.io/sending-a-file/). Namely, *croc* has no dependencies (just [download a binary and run](https://github.com/schollz/croc/releases/latest)), it works on any operating system, and its blazingly fast because it does parallel transfer over multiple TCP ports.
@ -35,8 +35,9 @@ _These two gifs should run in sync if you force-reload (Ctl+F5)_
$ croc -send some-file-or-folder
Sending 4.4 MB file named 'some-file-or-folder'
Code is: cement-galaxy-alpha
Your public key: F9Ky3WU2yG4y7KKppF4KnEhrmtY9ZlTsEMkqXfC1
Send to public key: xHVRlQ2Yp6otQXBoLMcUJmmtNPXl7z8tOf019sGw
Your public key: ecad-bakery-cup-unlit-roam-fetid-arulo-updike
Recipient public key: bike-cokery-casina-donut-field-farrow-mega-shine
ok? (y/n): y
Sending (->[1]63982)..
@ -48,10 +49,11 @@ File sent (2.6 MB/s)
```
$ croc
Your public key: xHVRlQ2Yp6otQXBoLMcUJmmtNPXl7z8tOf019sGw
Enter receive code: cement-galaxy-alpha
Receiving file (4.4 MB) into: some-file-or-folder
from public key: F9Ky3WU2yG4y7KKppF4KnEhrmtY9ZlTsEMkqXfC1
Your public key: bike-cokery-casina-donut-field-farrow-mega-shine
Recipient public key: ecad-bakery-cup-unlit-roam-fetid-arulo-updike
ok? (y/n): y
Receiving (<-[1]63975)..
@ -91,17 +93,17 @@ Or, you can [install Go](https://golang.org/dl/) and build from source with `go
# How does it work?
*croc* is similar to [magic-wormhole](https://github.com/warner/magic-wormhole#design) in spirit and design. Like *magic-wormhole*, *croc* generates a code phrase for you to share with your friend which allows secure end-to-end transfering of files and folders through a intermediary relay that connects the TCP ports between the two computers. The standard relay is on a public IP address (default `cowyo.com`), but before transmitting the file the two instances of *croc* send out UDP broadcasts to determine if they are both on the local network, and use a local relay instead of the cloud relay in the case that they are both local.
*croc* is similar to [magic-wormhole](https://github.com/warner/magic-wormhole#design) in spirit. Like *magic-wormhole*, *croc* generates a code phrase for you to share with your friend which allows secure end-to-end transfering of files and folders through a intermediary relay that connects the TCP ports between the two computers. The standard relay is on a public IP address (default `cowyo.com`), but before transmitting the file the two instances of *croc* send out UDP broadcasts to determine if they are both on the local network, and use a local relay instead of the cloud relay in the case that they are both local.
The code phrase for transfering files is just three words which are 16 random bits that are [menemonic encoded](http://web.archive.org/web/20101031205747/http://www.tothink.com/mnemonic/). This code phrase is hashed using sha256 and sent to the relay which maps that hashed code phrase to that connection. When the relay finds a matching code phrase hash for both the receiver and the sender (i.e. they both have the same code phrase), then the sender transmits the encrypted metadata to the receiver through the relay. Then the receiver decrypts and reviews the metadata (file name, size), and chooses whether to consent to the transfer.
The code phrase allows the relay to match the receiver and the sender. Once matched, the relay shares the public keys so that the sender and recipient can further authenticate whether or not they have the right person. Once both sides verify and consent to the transfer, then the sender will encrypt the data using the recipient's public key, so that only they can decrypt the data. After a succesful transfer, the public key is stored and next time it is not prompted and automatically trusted (TOFU).
After the receiver consents to the transfer, the sender transmits encrypted data through the relay. The relay setups up [Go channels](https://golang.org/doc/effective_go.html?h=chan#channels) for each connection which pipes all the data incoming from that sender's connection out to the receiver's connection. After the transmission the channels are destroyed and all the connection and meta data information is wiped from the relay server. The encrypted file data never is stored on the relay.
The transfer uses [Go channels](https://golang.org/doc/effective_go.html?h=chan#channels) and parallel connections to pipe all the data. After the transmission the channels are destroyed and all the connection and meta data information is wiped from the relay server. The encrypted file data never is stored on the relay.
**Encryption**
**Security**
Encryption uses AES-256 with a pbkdf2 derived key (see [RFC2898](http://www.ietf.org/rfc/rfc2898.txt)) where the code phrase shared between the sender and receiver is used as the passphrase. For each of the two encrypted data blocks (metadata stored on relay server, and file data transmitted), a random 8-byte salt is used and a IV is generated according to [NIST Recommendation for Block ciphers, Section 8.2](http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf).
The first time you use croc you will generate a unique NaCl box keypair (which uses Curve25519, XSalsa20 and Poly1305) that is unique to your computer. This keypair is used to transfer the encryption key to the recipient, and gaurantees that only the recipient can decrypt the encryption key to decrypt the file data. The encryption key is a cryptographically generated random 20 characters. The file data is encrypted using the encryption key with AES-256. This method gaurantees that all the file data going over the wire is secure, and that the only person who can decrypt it is the recipient (i.e. a MITM attacker cannot decrypt it without the keypair on the recipient's computer).
**Decryption**
The keypair also serves as a second method of authentication. After both the sender and recipient enter their code phrases, they will be able to see each other's public keys. If the public key of the other person does not match what they say it should be (i.e. an attacker is trying to use the same code phrase to get your file - possible though unlikely), then you can cancel the transfer.
On the receiver's computer, each piece of received encrypted data is written to a separate file. These files are concatenated and then decrypted. The hash of the decrypted file is then checked against the hash transmitted from the sender (part of the meta data block).

View file

@ -263,7 +263,7 @@ func (c *Connection) Run() error {
} else {
color.New(color.FgHiGreen, color.Bold).Fprint(os.Stderr, c.Code)
}
fmt.Fprintf(os.Stderr, "\n")
fmt.Fprintf(os.Stderr, "\n\n")
c.spinner = spinner.New(spinner.CharSets[24], 100*time.Millisecond) // Build our new spinner
c.spinner.Suffix = " Waiting for recipient.."
@ -616,9 +616,9 @@ func (c *Connection) runClient(serverName string) error {
fName = fName[:len(fName)-4]
}
if _, err := os.Stat(path.Join(c.Path, c.File.Name)); os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "Receiving %s (%s) into: '%s'\n\n", fType, humanize.Bytes(uint64(c.File.Size)), fName)
fmt.Fprintf(os.Stderr, "Receiving %s (%s) into: '%s'\n", fType, humanize.Bytes(uint64(c.File.Size)), fName)
} else {
fmt.Fprintf(os.Stderr, "Overwriting %s '%s' (%s)\n\n", fType, fName, humanize.Bytes(uint64(c.File.Size)))
fmt.Fprintf(os.Stderr, "Overwriting %s '%s' (%s)\n", fType, fName, humanize.Bytes(uint64(c.File.Size)))
}
var sentFileNames []string