How Croc's Code Phrase PAKE Authentication Works
Croc uses Password-Authenticated Key Exchange (PAKE) to convert the human-readable code phrase into a strong symmetric session key without ever transmitting the password over the network.
The open-source file transfer tool croc (github.com/schollz/croc) secures peer-to-peer connections using a shared code phrase that acts as a password. Through croc code phrase PAKE authentication, this human-readable secret transforms into a cryptographically strong key that encrypts all subsequent data, ensuring that even the relay server cannot read the transferred files.
Deriving the Room and Password from the Code Phrase
Room Name Generation and Secret Extraction
In src/croc/croc.go, the New function validates that the code phrase contains at least six characters. The implementation hashes the first four bytes to generate the room name used for rendezvous, while the remaining bytes (starting at index 5) serve as the weak password fed into the PAKE algorithm.
Role-Based PAKE Initialization
Both peers initialize the PAKE object from the github.com/schollz/pake/v3 library using the same password but with opposite roles. The receiver uses role 0 and the sender uses role 1. The elliptic curve defaults to p256 but is configurable via the --curve CLI flag defined in src/cli/cli.go.
The PAKE Handshake Sequence
The handshake occurs before any file data transmission, establishing an encrypted channel through a two-message exchange.
Step 1: Sender Initiates PAKE
In senderWaitForHandshake (src/croc/croc.go), the sender creates a PAKE instance with role 1 and transmits its public value via SimpleMessage{Kind:"pake1", Bytes:B.Bytes()} to the receiver.
Step 2: Receiver Responds
Upon receiving "pake1", the receiver calls A.Update(dataMessage.Bytes) and derives the session key kB via A.SessionKey(). It replies with SimpleMessage{Kind:"pake2", Bytes:A.Bytes()} containing its own public value.
Step 3: Key Confirmation
The sender processes "pake2" by calling B.Update(dataMessage.Bytes) and computing kA via B.SessionKey(). At this point, both sides hold the identical session key (kA == kB), though neither has transmitted the original code phrase.
Step 4: Channel Encryption
All subsequent communication uses crypt.Encrypt and crypt.Decrypt from src/crypt/crypt.go with the derived session key. The first encrypted message is the handshakeRequest, signaling the completion of the PAKE exchange.
Security Properties
Zero Password Transmission
The raw code phrase never leaves the client devices. Only public PAKE values (A.Bytes() and B.Bytes()) traverse the network, rendering eavesdropping attacks ineffective.
Authenticated Encryption
The derived session key provides both confidentiality and integrity through the crypt package, preventing man-in-the-middle tampering with file metadata or chunks.
CLI Usage and Configuration
Practical examples of invoking croc with custom code phrases and curves:
# Sender specifies custom code phrase
croc send --code "my secret phrase" file.txt
# Receiver joins with matching phrase
croc receive --code "my secret phrase"
# Use alternative elliptic curve for PAKE
croc send --curve p384 --code "another secret" file.txt
Core Implementation Files
src/croc/croc.go: ContainsNew,senderWaitForHandshake, and the PAKE handshake orchestration logic.src/message/message.go: Definesmessage.TypePAKEand theSimpleMessagestructure used for PAKE value exchange.src/crypt/crypt.go: ImplementsEncryptandDecryptfunctions that protect data using the PAKE-derived key.src/cli/cli.go: Exposes the--curveparameter allowing selection of elliptic curves likep256,p384, orp521.
Summary
- Croc requires code phrases of at least six characters, using the first four bytes for room identification and the remainder for PAKE authentication.
- The PAKE exchange assigns role
0to receivers and role1to senders, defaulting to thep256elliptic curve. - Public PAKE values are exchanged via "pake1" and "pake2" messages in
senderWaitForHandshake, resulting in identical session keys on both peers. - No password material ever transmits over the network; only public cryptographic values leave the client.
- Post-handshake communication uses authenticated encryption via the
cryptpackage with the derived session key.
Frequently Asked Questions
What is PAKE and why does croc use it?
PAKE (Password-Authenticated Key Exchange) is a cryptographic protocol that allows two parties to establish a shared secret key using a weak password, without transmitting the password itself. Croc uses PAKE to ensure that the human-readable code phrase never appears on the wire, preventing relay operators or network eavesdroppers from capturing authentication credentials.
How does croc prevent man-in-the-middle attacks during the handshake?
Croc mitigates man-in-the-middle attacks through the PAKE protocol's mathematical properties: the session key derivation depends on both the shared secret (code phrase) and the public values exchanged. An attacker without the code phrase cannot compute the correct session key, and the subsequent authenticated encryption in src/crypt/crypt.go rejects any tampered messages.
Can I use a custom elliptic curve for the PAKE exchange?
Yes. While croc defaults to the p256 curve for balanced security and performance, you can specify alternatives like p384 or p521 using the --curve flag. The CLI parser in src/cli/cli.go passes this parameter to the PAKE constructor in src/croc/croc.go.
What happens if the code phrase is shorter than six characters?
The New function in src/croc/croc.go enforces a minimum length of six characters for the code phrase. This requirement ensures sufficient entropy for the room name (first four bytes) and the PAKE password (remaining bytes) to maintain security.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →