Pre-1.0 Notice: This library is under active development. The API may change between minor versions until 1.0.
Rust implementation of the AlgoChat protocol for encrypted messaging on Algorand.
Add to your Cargo.toml:
[dependencies]
algochat = "0.2"use algochat::{AlgoChatClient, AlgorandConfig};
// Create client from a 32-byte seed
let client = AlgoChatClient::from_seed(seed, AlgorandConfig::localnet()).await?;
// Discover a recipient's public key on-chain
let key = client.discover_key("RECIPIENT_ADDR").await?;
// Encrypt a message
let recipient_pk = key.unwrap().public_key;
let envelope = client.encrypt("Hello, World!", &recipient_pk)?;
// Decrypt a received message
let text = client.decrypt(&envelope, &sender_pk)?;
// Sync and process new messages
let messages = client.sync().await?;use algochat::{derive_keys_from_seed, encrypt_message, decrypt_message, ChatEnvelope};
let (sender_private, sender_public) = derive_keys_from_seed(&seed)?;
let (recipient_private, recipient_public) = derive_keys_from_seed(&recipient_seed)?;
let envelope = encrypt_message(
"Hello, World!",
&sender_private,
&sender_public,
&recipient_public,
)?;
let encoded = envelope.encode();
let decoded = ChatEnvelope::decode(&encoded)?;
let result = decrypt_message(&decoded, &recipient_private, &recipient_public)?;AlgoChat uses:
- X25519 for key agreement
- ChaCha20-Poly1305 for authenticated encryption
- HKDF-SHA256 for key derivation
The protocol supports bidirectional decryption, allowing senders to decrypt their own messages.
The PSK (Pre-Shared Key) protocol extends AlgoChat with an additional layer of symmetric key security:
- Hybrid encryption: Combines X25519 ECDH with a pre-shared key
- Two-level ratchet: Session + position derivation for forward secrecy
- Replay protection: Counter-based state tracking with configurable window
- Exchange URI: Out-of-band key sharing via
algochat-psk://URIs - Zeroized key material: Sensitive keys are zeroized after use
The AlgoChatClient manages PSK contacts and counter state automatically:
use algochat::{AlgoChatClient, AlgorandConfig, PSKContact, PSKExchangeURI};
let client = AlgoChatClient::from_seed(seed, AlgorandConfig::localnet()).await?;
// Add a PSK contact (exchanged out-of-band via URI)
let uri = PSKExchangeURI::decode("algochat-psk://v1?addr=ADDR&psk=...&label=Alice")?;
client.add_psk_contact(&uri.address, PSKContact::new(uri.psk, uri.label)).await;
// Send β counter management is automatic
let (envelope_bytes, counter) = client.send_psk("RECIPIENT_ADDR", "Hello with PSK!").await?;
// Receive β replay protection is automatic
let text = client.receive_psk(&envelope_bytes, "SENDER_ADDR").await?;For direct control over encryption and counters:
use algochat::{
encrypt_psk_message, decrypt_psk_message,
encode_psk_envelope, decode_psk_envelope, is_psk_message,
PSKState,
};
let psk = [0xAA; 32];
let mut state = PSKState::new();
// Encrypt with PSK
let counter = state.advance_send_counter();
let envelope = encrypt_psk_message(
"Hello with PSK!",
&sender_private,
&sender_public,
&recipient_public,
&psk,
counter,
)?;
// Encode for transmission
let encoded = encode_psk_envelope(&envelope);
// Decode and decrypt
let decoded = decode_psk_envelope(&encoded)?;
let text = decrypt_psk_message(&decoded, &recipient_private, &recipient_public, &psk)?;This implementation is fully compatible with:
- swift-algochat (Swift)
- ts-algochat (TypeScript)
- py-algochat (Python)
- kt-algochat (Kotlin)
MIT