Security Considerations When Using croc: End-to-End Encryption and Relay Architecture Explained
croc encrypts files end-to-end using AES-GCM or ChaCha20-Poly1305, but relies on user-supplied passphrases and relay passwords that must be strong to prevent brute-force attacks against its PAKE key exchange.
croc is a peer-to-peer file transfer tool that combines end-to-end encryption with a relay-based connection model to transfer files across networks. Understanding the security considerations when using schollz/croc requires examining its cryptographic implementation, where encryption primitives, key derivation functions, and password-authenticated key exchange (PAKE) protocols work together to protect your data.
How croc Implements End-to-End Encryption
All file payloads in croc are encrypted before leaving the sender's machine, ensuring confidentiality even if the relay server is compromised.
In src/crypt/crypt.go, the Encrypt function (lines 37-55) implements AES-GCM with a randomly generated initialization vector (ivBytes, lines 41-45) for every message. Alternatively, the EncryptChaCha function (lines 99-108) provides ChaCha20-Poly1305 encryption. Both ciphers provide authenticated encryption, guaranteeing both confidentiality and integrity.
The randomness for these operations is sourced from crypto/rand throughout the codebase, ensuring unpredictable keys and IVs essential for semantic security.
Key Derivation: PBKDF2 vs Argon2
The strength of croc's encryption depends on how the session key is derived from your passphrase.
By default, croc derives a 256-bit key using PBKDF2 with SHA-256 in the New function (src/crypt/crypt.go, lines 16-34). However, PBKDF2 with the default iteration count provides only modest resistance to GPU-based brute-force attacks.
For stronger security, croc offers Argon2 key derivation via the NewArgon2 function (lines 76-96). Argon2 is a memory-hard function that significantly increases the cost of brute-force attacks.
- PBKDF2: Default option, faster but less resistant to hardware attacks.
- Argon2: Available via the
--argon2flag, recommended for high-security environments.
PAKE Protocol and Relay Security
croc uses a password-authenticated key exchange (PAKE) implementation to protect the relay password from eavesdroppers, even over untrusted networks.
The PAKE Handshake Process
In src/tcp/tcp.go, the clientCommunication function (lines 78-84) initializes the PAKE exchange. The server creates a PAKE instance with a weak static seed (var weakKey = []byte{1, 2, 3}) and role 1, while the client uses role 0. This hard-coded weakKey serves only as a protocol seed; actual security derives from the passphrase-generated session key.
Relay Password Requirements
The relay requires a password (RelayPassword) sent encrypted over the PAKE channel. However, src/webrelay/webrelay.go contains a dangerous default in normalizeConfig (lines 155-158): the default relay password is "pass123".
Always override the default. Use --pass <secret> with a high-entropy string, or configure a custom relay:
# Run your own relay with a strong password
croc relay --host myrelay.example.com --pass "SuperSecretRelayPass"
# Connect using custom credentials
croc send --relay myrelay.example.com --pass "SuperSecretRelayPass" file.txt
Host Validation and Transport
The normalizeConfig function (lines 58-66) validates relay hosts using net.SplitHostPort to prevent malicious URL schemes that could enable man-in-the-middle attacks.
Importantly, the WebSocket bridge (/ws) merely forwards raw bytes and does not implement additional encryption. All security relies on the end-to-end encryption described previously.
Local Attack Surfaces and Misconfigurations
Beyond network security, local configurations present additional risks.
The Local Relay Option
By default, croc starts a local relay on the sender's machine bound to 127.0.0.1 using randomly chosen ports. If an attacker gains code execution on the sender host, they could intercept traffic before encryption occurs.
Disable the local relay when operating in untrusted environments:
croc send --no-local --code "my-secure-code" file.txt
Passphrase Entropy Requirements
The CLI enforces a minimum codephrase length of 6 characters (--code flag) via determinePass in src/cli/cli.go. Short codephrases are vulnerable to dictionary attacks. Always use longer, high-entropy passphrases.
Configuring croc for Maximum Security
Apply these configurations to align croc's security posture with enterprise threat models:
-
Use Argon2 for key derivation to resist GPU attacks:
croc send --argon2 --code "correct-horse-battery-staple" file.txt -
Disable the local relay when the sender's environment is untrusted:
croc send --no-local file.txt -
Specify strong custom credentials for both the code and relay password:
croc send --code "correct horse battery staple" --pass "W!c0rD$3cReT!" file.txt -
Run a private relay instead of using public relays to eliminate third-party trust assumptions.
Summary
- croc provides end-to-end encryption via AES-GCM or ChaCha20-Poly1305 in
src/crypt/crypt.go, ensuring confidentiality even if relays are compromised. - Key derivation defaults to PBKDF2, but
--argon2offers superior brute-force resistance through theNewArgon2implementation. - PAKE protects the relay password during transmission, though the default relay password
"pass123"insrc/webrelay/webrelay.gomust always be overridden. - The local relay functionality presents a local attack surface that can be eliminated with
--no-local. - All cryptographic randomness uses
crypto/rand, but security ultimately depends on user-supplied passphrase entropy and proper relay configuration.
Frequently Asked Questions
Is croc vulnerable to man-in-the-middle attacks if the relay is compromised?
No. Because croc uses end-to-end encryption, even a compromised relay cannot decrypt file contents without the session key derived from your passphrase. The PAKE protocol ensures that the relay password itself is never transmitted in plaintext, protecting against credential theft even if the relay is malicious.
What is the difference between PBKDF2 and Argon2 in croc?
PBKDF2 is the default key derivation function in the New function (src/crypt/crypt.go), using SHA-256 hashing. Argon2, available via --argon2 and implemented in NewArgon2, is a memory-hard algorithm specifically designed to resist GPU and ASIC attacks. Use Argon2 when transferring sensitive data or when the passphrase may have moderate entropy.
How long should my croc passphrase be?
While croc enforces a minimum of 6 characters, you should use a passphrase of at least 20 characters with high entropy (random words or alphanumeric strings). Short passphrases are susceptible to brute-force attacks against the PAKE exchange, particularly when using the default PBKDF2 derivation instead of Argon2.
Can the local relay feature expose my files to other users on the same machine?
Yes. The local relay binds to 127.0.0.1 (localhost), but if another user or process has compromised your machine with code execution privileges, they could potentially intercept the file before encryption occurs. Use --no-local to disable this feature and transmit directly through the encrypted peer-to-peer connection when operating in multi-user or untrusted local environments.
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 →