Pubky Messenger
A Rust library for secure private messaging using the Pubky protocol. This library provides end-to-end encrypted messaging capabilities with authentication via pkarr recovery files.
Features
- 🔐 End-to-end encrypted messaging using X25519-ECDH
- 🔑 Authentication via pkarr recovery files
- ✅ Message signature verification using Ed25519
- 👥 Profile and contact management
- 🔄 Async/await API using Tokio
Installation
Add this to your Cargo.toml:
[]
= "0.2.1"
Usage
Basic Example
use ;
use Result;
async
Creating a Client from Keypair
If you already have a keypair, you can create the client directly:
use Keypair;
use PrivateMessengerClient;
let keypair = random;
let client = new?;
Creating a Client from Recovery Phrase
You can also create a client using a 12-word mnemonic recovery phrase with optional passphrase and language:
use PrivateMessengerClient;
// Basic usage - defaults to English, no passphrase
let mnemonic = "your twelve word recovery phrase goes here with spaces between words";
let client = from_recovery_phrase?;
// Sign in and use as normal
client.sign_in.await?;
With optional passphrase for additional security:
// Add a passphrase for extra security
let client_with_passphrase = from_recovery_phrase?;
With different language:
use ;
// Use a different language
let client = from_recovery_phrase?;
With both passphrase and language:
let client = from_recovery_phrase?;
The recovery phrase must be:
- Exactly 12 words from the BIP39 wordlist for the specified language
- In the correct format for that language (e.g., lowercase for English)
- Separated by single spaces
Parameters:
mnemonic_phrase: The 12-word BIP39 mnemonic (required)passphrase: Optional passphrase for additional security (defaults to empty string)language: Optional language for mnemonic validation (defaults to English)
This method provides a deterministic way to recover your keypair from a mnemonic phrase. The same mnemonic with the same passphrase and language will always produce the same keypair.
Working with Profiles
// Get your own profile
if let Some = client.get_own_profile.await?
// Get followed users
let followed = client.get_followed_users.await?;
for user in followed
Managing Messages
The library provides methods to delete messages from your conversations:
// Delete a single message
let message_id = "550e8400-e29b-41d4-a716-446655440000";
client.delete_message.await?;
// Delete multiple messages at once
let message_ids = vec!;
client.delete_messages.await?;
// Clear all your sent messages in a conversation
client.clear_messages.await?;
Note: These delete operations only remove messages from your own storage on the Pubky network. Messages stored by the recipient remain unchanged.
API Reference
PrivateMessengerClient
The main client for interacting with the Pubky messaging system.
Methods
new(keypair: Keypair) -> Result<Self>- Create a new client from a keypairfrom_recovery_file(bytes: &[u8], passphrase: Option<&str>) -> Result<Self>- Create from recovery file with optional passphrasefrom_recovery_phrase(mnemonic: &str, passphrase: Option<&str>, language: Option<Language>) -> Result<Self>- Create from 12-word BIP39 mnemonic with optional passphrase and languagesign_in(&self) -> Result<Session>- Sign in to the homeserversend_message(&self, recipient: &PublicKey, content: &str) -> Result<String>- Send encrypted messageget_messages(&self, other: &PublicKey) -> Result<Vec<DecryptedMessage>>- Get conversation messagesdelete_message(&self, message_id: &str, other: &PublicKey) -> Result<()>- Delete a single messagedelete_messages(&self, message_ids: Vec<String>, other: &PublicKey) -> Result<()>- Delete multiple messagesclear_messages(&self, other: &PublicKey) -> Result<()>- Clear all sent messages in a conversationget_own_profile(&self) -> Result<Option<PubkyProfile>>- Get user's profileget_followed_users(&self) -> Result<Vec<FollowedUser>>- Get followed userspublic_key(&self) -> PublicKey- Get the client's public keypublic_key_string(&self) -> String- Get public key as string
Types
DecryptedMessage- A decrypted message with sender, content, timestamp, and verification statusPubkyProfile- User profile information (name, bio, image, status)FollowedUser- Information about a followed user
Error Handling
All methods return Result<T> where the error type is anyhow::Error. This provides flexible error handling with context. Common error scenarios include:
- Network connectivity issues
- Invalid recovery file or passphrase
- Encryption/decryption failures
- Missing or invalid public keys
Example error handling:
match client.send_message.await
Examples
Check the examples/ directory for more detailed examples:
Basic Usage Example
# Run the basic usage example
This example demonstrates:
- Loading a recovery file and signing in
- Displaying your profile information
- Listing followed users
- Sending a test message (if recipient pubky provided)
- Reading conversation messages
Send Message Example
# Send a message to a specific pubky
# Example:
This example:
- Takes a recovery file, recipient pubky, and message as arguments
- Signs in to Pubky
- Sends the message to the specified recipient
- Displays the message ID and timestamp
Read Messages Example
# Read all messages from a conversation with a specific pubky
# Example:
This example:
- Takes a recovery file and peer pubky as arguments
- Signs in to Pubky
- Fetches all messages from the conversation
- Displays messages in a formatted, chronological order
- Shows sender information, timestamps, and verification status
Real-time Conversation Example
# Start an interactive chat session with a specific pubky
# Example:
This example provides a real-time chat experience:
- Shows the last 10 messages when starting
- Allows you to type and send messages interactively
- Automatically checks for new messages every 3 seconds
- Displays messages with timestamps in HH:MM:SS format
- Press Ctrl+C to exit the chat session
Features:
- Real-time message polling
- Interactive terminal UI
- Message history display
- Automatic new message detection
- Clean, chat-like interface
Testing
Running Tests
The library includes comprehensive unit and integration tests. Due to API rate limiting, it's recommended to run tests sequentially:
# Run all tests sequentially (recommended)
# Run specific test file
# Run with output for debugging
Test Files with Recovery Keys
The repository includes test recovery files (p1.pkarr and p2.pkarr) in the root directory for integration testing. Both use "password" as the passphrase.
Important: These test files are for development only and should never be used in production.
Writing Tests
When writing tests that interact with the Pubky network:
- Use unique message content with timestamps to avoid conflicts
- Add delays between operations when necessary (
tokio::time::sleep) - Handle existing messages in conversations gracefully
- Run tests sequentially to avoid rate limiting
Security
This library implements end-to-end encryption using:
- X25519-ECDH for key agreement
- ChaCha20-Poly1305 for message encryption (via pubky-common)
- Ed25519 for message signatures
- Blake3 for hashing
Messages are encrypted with a shared secret derived from the sender and recipient's keypairs.
License
MIT