Encrypted messaging for Robinhood Chain wallets

Protocol

Encryption

HoodChat uses NaCl box — X25519 key agreement with XSalsa20-Poly1305 — the same well-studied primitives used across modern secure messaging.

Key derivation

Your wallet signs a fixed unlock message. The secret key is the first 32 bytes of SHA-512("hoodchat/x25519/v1" ‖ signature). Standard wallets sign deterministically (RFC 6979), so the same wallet always derives the same key. Some smart-contract wallets don’t; HoodChat detects a mismatch with your on-chain key and warns you.

Message envelope

What goes on-chain for each message:

version (1) | sender public key (32) | recipient public key (32) | nonce (24) | box (ciphertext + 16-byte MAC)

And what’s sealed inside the box:

from address (20) | to address (20) | length (4) | UTF-8 text | zero padding to a 32-byte boundary
  • Both public keys are included so either side can open it — which is how you can read your own sent messages.
  • The addresses inside are checked against the on-chain sender and recipient, so ciphertext can’t be replayed under another wallet.
  • Messages longer than ~3,900 bytes are sealed into a blob stored on IPFS; only an encrypted pointer goes on-chain, so even the file location stays private.
  • Decrypted text is only ever held in memory. The app caches ciphertext, never plaintext.

Source

The implementation lives in packages/sdk/src/crypto.ts, with tests covering round-trips, tampering, replay and padding. See Privacy & security for the current limits.