A minimalist, peer-to-peer (P2P) encrypted chat application written in Go. It establishes a secure channel between two nodes using Elliptic-Curve Diffie-Hellman (ECDH) for key exchange and executes a stateful cryptographic key ratchet for message transmission, allowing custom IP/port configuration and dynamic Short Authentication String (SAS) generation.
- P2P Architecture: Direct communication between Host and Client over TCP across local networks or localhost.
- Dual-Stack Network Support: Native support for both IPv4 and IPv6 addresses.
- IPv6 by Default: The application defaults to IPv6 (
::1) for local connections if no specific IP address is provided by the user. - Dynamic Connection Inputs: Flexible configuration prompting the client for target Host IP addresses (IPv4/IPv6) and custom ports.
- Input Validation: Automatic bounds checking ensuring port values fall strictly within the safe unprivileged range (1024-65535).
- Dynamic Key Exchange: X25519 Elliptic-Curve Diffie-Hellman (ECDH) handshake creates a unique master secret per session.
- Perfect Forward Secrecy (PFS): A stateful, unidirectional symmetric key ratchet powered by HKDF-SHA512 ensures that compromising a current message key exposes zero clues about past or future keys.
- Asymmetric Conveyor Belts: Separate independent ratchets for sending and receiving eliminate race conditions and collisions when users type simultaneously.
- Out-of-Order Message Resilience: Smart packet-loss cache map natively captures skipped message keys (up to a 100-packet threshold) and destroys them immediately upon late consumption to prevent replay attacks.
- Out-of-Band Verification (SAS): MitM mitigation via a formatted Short Authentication String derived from a SHA-512 hash of the shared secret.
- End-to-End Encryption: Authenticated encryption using AES-GCM with unique nonces and unique ephemeral keys for every single transmitted message.
- Text-Safe Wire Protocol: Network payloads are encoded into a zero-padded hex sequence header combined with a Base64 ciphertext stream separated by a colon (
:). - Concurrent I/O: Asynchronous message reading and writing managed through Go goroutines.
The application implements a Trust on First Use (TOFU) model for seamless connectivity. To protect users against Man-in-the-Middle (MitM) attacks, the application prints a distinct, chunked Short Authentication String (SAS) derived from the initial shared key. Users can manually compare this code via an independent out-of-band secure channel (e.g., voice call) to verify identity authenticity before trusting the session.
- IP Protocol Selection: The network engine parses the provided IP address to automatically determine the protocol. If an IPv6 address is detected, it encapsulates the literal address in brackets (e.g.,
[::1]:port) to comply with standard Go network dialing formats. - Default Fallback: Pressing Enter at the IP prompt automatically defaults the connection to the IPv6 loopback address (
::1). - Valid Port Range: 1024 to 65535 (Unprivileged/Private Ports).
- Restricted Port Range: 1 to 1023 (System/Well-Known Ports requiring root privileges are blocked to minimize runtime socket access errors).
- Connection Setup: One node acts as Host (binding to a user-defined port) and the other connects as Client by inputting the specific target IP (IPv4/IPv6) and matching port. If no IP is specified, the client defaults to IPv6 (
::1). - Handshake Phase: Both nodes generate an ephemeral X25519 key pair, exchange public keys in Base64 via the unified connection scanner, and locally derive an identical 32-byte master secret.
- Authentication Block: The master secret is hashed using SHA-512 to display the structured SAS code on both terminals for visual out-of-band verification.
- Ratchet Initialization: The master secret is split using dedicated HKDF domain separation info labels (
privy-host-to-clientandprivy-client-to-host) into asymmetrical sending and receiving conveyor belts. - Session Transmission: Every sent line advances the sending ratchet to generate a one-time key for AES-GCM encryption, tracking the frame on the wire via an explicit hex sequence number header. The receiver evaluates the sequence header to match the happy path, handle packet drops via the map cache, or catch up through a jump-forward loop.
- Go 1.21 or higher
- Golang extended cryptography dependencies
go get golang.org/x/crypto/hkdf
Clone the repository and navigate into the project directory:
git clone [https://github.com/bosioF/Privy.git](https://github.com/bosioF/Privy.git)
cd Privy
go build . # to build the binary "privy"
Run the application in two different terminal instances on your local machine or two machines connected to the same network.
./privy --help
Print this menu: ./privy --help
Host on PORT: ./privy -h -p <PORT>
Connect to PORT on localhost: ./privy -c -p <PORT>
Connect to PORT on IPv4 or IPv6: ./privy -c -p <PORT> -ip <IP>
Run the program and select the host option, then enter a valid port:
./privy # Or use flags: ./privy -h -p <port>
Prompt flow (if run without args):
You want to host(h) or connect(c)?
h
On what port do you want to listen? (1024-65535) 5000
Listening
Run the program, select the connect option, enter the target port, and provide the Host IP address. Press Enter to use the default IPv6 localhost (::1), or specify the details as CLI args:
./privy # Or use flags: ./privy -c -p 5000 -ip <ip>
Prompt flow showing the IPv6 default behavior (pressing Enter for localhost):
You want to host(h) or connect(c)?
c
On what port do you want to connect? (1024-65535) 5000
What is the IP? (Press Enter for localhost):
Connecting to [::1]:5000 ...
Once the handshake is computed, the verification prompt will display on both terminals:
Connection successful! [::1]:5000
Handshake successful! Connection Secure!
If you suspect someone is attempting a MitM attack, verify that this code is the same as the other person, over another secure channel.
SAS Code: a1b2-c3d4-e5f6-7g8h-a1b2-c3d4-e5f6-7g8h
You can now type messages in the terminal and press Enter to stream encrypted data.
- Key Exchange: Curve25519 (
crypto/ecdh) - Key Derivation Function: HKDF-SHA512 (
golang.org/x/crypto/hkdf,crypto/sha512) - Authentication Hashing: SHA-512 (
crypto/sha512) - Symmetric Cipher: AES-256-GCM (
crypto/aes,crypto/cipher) - Payload Encoding: Standard Base64 (
encoding/base64) & Zero-Padded Hex Headers