A secure, terminal-based chat application that uses PGP (Pretty Good Privacy) encryption for end-to-end encrypted communication. This application allows users to create secure chat rooms, generate PGP key pairs, and exchange encrypted messages with confidence.
- Textual: Terminal UI framework for creating the interactive interface
- python-gnupg: Python wrapper for GnuPG (GNU Privacy Guard)
- Socket Programming: For network communication between clients and servers
- Threading: For handling multiple connections simultaneously
- JSON: For structured data exchange between clients and server
This application is designed for:
- Protected: Message content confidentiality using PGP encryption
- Protected: Message authenticity and integrity via PGP signatures
- NOT Protected: Metadata (who's talking to whom, message timing, room names)
- NOT Protected: Against endpoint compromise (if attacker has your passphrase)
- No Perfect Forward Secrecy: Compromised private key exposes all past messages
- Metadata Leakage: Server sees IP addresses, connection times, room names
- Trust on First Use: No key verification mechanism (vulnerable to MITM during key exchange)
- Cleartext Passphrases in Memory: Application holds passphrases in plaintext during session
Planned improvements:
- Implement Double Ratchet algorithm (Signal Protocol) for forward secrecy
- Add key fingerprint verification UI
- Ephemeral message support (auto-delete after reading)
- Memory zeroization for sensitive data
terminal-pgp uses a client-server architecture:
- Server Component: Handles room hosting, client connections, and message broadcasting
- Client Component: Manages user connections to rooms and handles message encryption/decryption
- UI Component: Terminal-based interface built with Textual
- Key Generation: Users generate PGP key pairs (public/private keys)
- Authentication: Users login with their email and passphrase
- Secure Communication:
- Messages are encrypted with the recipient's public key
- Recipients decrypt messages using their private key and passphrase
- The application supports pairwise encryption for group chats (separate encryption for each recipient)
- A user types a message in the chat interface
- The message is encrypted with each recipient's public key, creating a bundle of ciphertexts
- This bundle is sent to the server
- The server broadcasts the bundle to all connected clients
- Each client attempts to decrypt their specific ciphertext using their private key
- Successfully decrypted messages are displayed in the chat UI
- Python 3.7 or higher
- GnuPG installed on your system
- OpenSSL certificate for server
- Only working for local testing for now
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes -subj "/CN=localhost"
-
Clone the repository:
git clone [repository-url] cd terminal-pgp -
Install required dependencies:
pip install -r requirements.txt
The application requires multiple terminal instances to demonstrate the chat functionality:
python app.py-
Generate a key pair (Button: "Generate Key Pair")
- Enter your email and a secure passphrase
- Note the fingerprint displayed in the output
-
Login with your credentials (Button: "Login")
- Enter the email and passphrase used in key generation
-
Host a chat room (Button: "Host Room")
- Enter a room name
- Specify a port number (e.g., 8000)
python app.py- Generate another key pair with different credentials
- Login with the second set of credentials
- Connect to the hosted room (Button: "Connect to Room")
- Enter "127.0.0.1" as the Host IP
- Enter the port number matching the hosted room
- Generate key pairs for all users
- Login with user credentials
- One user hosts a room
- Other users connect to the room
- Exchange encrypted messages
- Close the chat when finished
- Key Management: Generate, list, update, and delete PGP key pairs
- Secure Messaging: End-to-end encrypted communication
- Room Hosting: Create private chat rooms
- Group Chat: Support for multiple users with pairwise encryption
- Terminal UI: Clean, intuitive interface for all operations
-
User Authentication Enhancement
- Implement a more robust authentication system
- Add support for key verification and trust levels
-
Persistent Storage
- Add message history with encrypted local storage
- Support for exporting/importing encrypted conversation logs
-
UI Enhancements
- File transfer capabilities
- Emoji support
- Markdown rendering for formatted messages
-
Network Improvements
- Support for NAT traversal to enable connections across networks
- Implement WebSocket support for web client compatibility
- Add relay servers for improved connectivity
-
Security Enhancements
- Perfect forward secrecy implementation
- Key rotation mechanisms
- Support for multiple encryption algorithms
-
Usability Features
- Contact management system
- Notifications for new messages
- Status indicators (online, typing, etc.)
-
Web Interface
# Example of adding a Flask web interface from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('chat.html') # Implement WebSocket for real-time communication
-
Adding File Transfer
To enhance the application with file transfer capabilities, you can extend the PGPChatClient class:
# Add to PGPChatClient class
def send_file(self, filepath, recipient):
with open(filepath, 'rb') as file:
content = file.read()
encrypted = encrypt_and_sign_message(
self.app.user_email,
self.app.user_passphrase,
recipient,
content
)
file_bundle = {
"type": "file",
"filename": os.path.basename(filepath),
"sender": self.app.user_email,
"content": encrypted
}
self.client_socket.sendall(json.dumps(file_bundle).encode("utf-8"))- Message Persistence
To add chat message persistence, you can extend the PGPApp class to encrypt and save chat logs locally:
# Add to PGPApp class
def save_chat_history(self, room_name):
chat_messages = [msg.text for msg in self.query_one(".chat-messages").children]
encrypted = encrypt_and_sign_message(
self.user_email,
self.user_passphrase,
self.user_email, # Encrypt to self
json.dumps(chat_messages).encode("utf-8") # Ensure bytes are used
)
with open(f"{room_name}_history.gpg", "wb") as history_file:
history_file.write(encrypted.data)If you want to contribute to this project, consider implementing any of the suggested enhancements. Here's a step-by-step process for contributing:
- Fork the Repository: Fork this project to your own GitHub account.
- Make Changes: Implement new features or fix bugs in your fork.
- Create a PR: Submit a pull request to the original repository with a descriptive title and comment explaining your changes.
- Review Process: The PR will go through a review process before it is merged.
- Key Generation Errors: Ensure GnuPG is installed correctly and verify that you have adequate permissions to write to the PGP key directory.
- Connection Issues: Check that both clients are connecting to the same host and port. Use
127.0.0.1for local testing. - Decryption Failures: Verify that recipients have their private keys loaded and the correct passphrase is being used.
- Other Unmentioned Errors: Application logs will be stored in a
pgp_logfile. Be sure to check it if you run into any errors, it will help in tracking down any caught exceptions
- This project uses python-gnupg for PGP encryption and Textual for the terminal UI.
Feel free to reach out with questions or to discuss potential enhancements. Happy coding