go-chat-server
Simple & Encrypted Chat
877
A simple encrypted chat system using a PUB/SUB single channel. Supports PGP and AES-256-GCM end-to-end encryption. Any message sent from a client (publisher) is encrypted and routed to every other client (subscriber) on the channel.
All messages are encrypted client-side before being sent to the relay server. The server never sees plaintext — it only routes opaque encrypted payloads between clients.
┌────────┐ ┌────────┐
Message ─────► Client │ │ Client ├──Decrypt──► Message
└───┬────┘ └────▲───┘
│ │
│ ┌────────┐ │
└─Encrypt───► Server ├───────┘
└────────┘
Messages use length-prefixed binary framing (4-byte big-endian header + JSON payload) for reliable delivery over TCP, replacing the previous delimiter-based protocol.
| Mode | Algorithm | Type | Key Material | Best For |
|---|---|---|---|---|
pgp | GPG/PGP | Asymmetric | Public + Private key files | High-security, identity-based |
aes | AES-256-GCM + Argon2id | Symmetric | Shared passphrase | Simple setup, fast encryption |
Uses public-key cryptography. Each client encrypts with the shared public key and decrypts with the private key + passphrase. Ideal when you need strong identity-based security.
Uses authenticated symmetric encryption with:
This is the recommended mode for simplicity and performance.
Configuration is done through environment variables. You can create a .env file in the project root:
START_MODE=server
HOST=localhost
PORT=12345
ENCRYPTION=pgp
PUBLIC_KEY_FILE=./keys/public.asc
PRIVATE_KEY_FILE=./keys/private.asc
PASSPHRASE=your-secure-passphrase
| Variable | Description | Default | Required |
|---|---|---|---|
START_MODE | Application mode | — | Yes (server or client) |
PORT | TCP port | 12345 | No |
HOST | Bind/connect address | localhost | No |
ENCRYPTION | Encryption algorithm | pgp | No (pgp or aes) |
PUBLIC_KEY_FILE | Path to PGP public key | — | PGP mode only |
PRIVATE_KEY_FILE | Path to PGP private key | — | PGP mode only |
PASSPHRASE | PGP key passphrase or AES shared secret | — | Client mode |
Note: Escape any special characters in
PASSPHRASEwhen using shell commands.
Generate a PGP key pair using GPG:
# Generate a new key pair (follow the prompts)
gpg --full-generate-key
# List your keys to find the key ID
gpg --list-keys
# Export public key (replace KEY_ID with your key ID or email)
gpg --armor --export KEY_ID > keys/public.asc
# Export private key
gpg --armor --export-secret-keys KEY_ID > keys/private.asc
Quick generation (non-interactive, for testing):
mkdir -p keys
# Generate key with predefined settings
gpg --batch --gen-key <<EOF
Key-Type: RSA
Key-Length: 4096
Subkey-Type: RSA
Subkey-Length: 4096
Name-Real: Go Chat User
Name-Email: [email protected]
Expire-Date: 0
Passphrase: your-secure-passphrase
%commit
EOF
# Export keys
gpg --armor --export [email protected] > keys/public.asc
gpg --armor --export-secret-keys [email protected] > keys/private.asc
Warning
You can't use PGP keys on smart-cards like YubiKey because the `gopenpgp` requires raw private key material in memory.
For AES-256-GCM mode, only a shared passphrase is needed:
# All clients must use the same passphrase
export ENCRYPTION=aes
export PASSPHRASE="a-strong-shared-secret-at-least-16-chars"
Generate a strong random passphrase:
# Using openssl
openssl rand -base64 32
# Using /dev/urandom
head -c 32 /dev/urandom | base64
Download the latest release from the releases page.
Server:
START_MODE=server PORT=12345 ./go-chat
Client (PGP):
START_MODE=client ENCRYPTION=pgp \
PUBLIC_KEY_FILE=./keys/public.asc \
PRIVATE_KEY_FILE=./keys/private.asc \
PASSPHRASE="your-passphrase" \
HOST=server-address PORT=12345 \
./go-chat
Client (AES):
START_MODE=client ENCRYPTION=aes \
PASSPHRASE="shared-secret" \
HOST=server-address PORT=12345 \
./go-chat
Client Commands:
/quit or /exit to disconnectCtrl+C for graceful shutdownNote: For macOS, you may need to allow the binary:
System Preferences > Security & Privacy > General > Open Anyway.
Run the server in a Docker container:
docker run -it -p 12345:12345 hatamiarash7/go-chat-server
With custom settings:
docker run -it -p 9999:9999 \
-e PORT=9999 \
-e HOST=0.0.0.0 \
hatamiarash7/go-chat-server
The Docker image defaults:
HOST=0.0.0.0,PORT=12345,START_MODE=server.
# Build
make build
# Run server
make server
# Run client (set env vars first or create .env)
make client
# Show version
./go-chat --version
# Run all tests with race detection
make test
# Run tests with coverage report
make coverage
# Format code
make fmt
# Run go vet
make vet
# Run all checks (format + vet + test)
make check
# Build Docker image
make docker-build
# Tidy dependencies
make deps
.
├── cmd/
│ └── go-chat/
│ └── main.go # Application entrypoint
├── internal/
│ ├── client/
│ │ └── client.go # Chat client implementation
│ ├── config/
│ │ ├── config.go # Configuration management
│ │ └── config_test.go # Config tests
│ ├── encryption/
│ │ ├── encryption.go # Encryptor interface
│ │ ├── aes.go # AES-256-GCM implementation
│ │ ├── pgp.go # PGP implementation
│ │ └── encryption_test.go # Encryption tests
│ ├── message/
│ │ ├── message.go # Message framing protocol
│ │ └── message_test.go # Message tests
│ ├── server/
│ │ ├── server.go # Relay server implementation
│ │ └── server_test.go # Server tests
│ └── version/
│ └── version.go # Build-time version info
├── .dockerignore
├── .env.example
├── .gitignore
├── Dockerfile
├── go.mod
├── go.sum
├── LICENSE
├── Makefile
└── README.md
Contributions are welcome! Here's how you can help:
git checkout -b feature/amazing-featuregit commit -m 'Add amazing feature'git push origin feature/amazing-featureEach project may have many problems. Contributing to the better development of this project by reporting them. 👍
Content type
Image
Digest
sha256:0c62de859…
Size
1.9 MB
Last updated
5 months ago
docker pull hatamiarash7/go-chat-server