Skip to content

WLANRouterKing/seal

Repository files navigation

Seal

https://sealchat.app

CI Security License: MIT

Private messaging sealed with Nostr

Seal is a privacy-focused messaging app built on the Nostr protocol. Messages are end-to-end encrypted using NIP-17 Gift Wraps, ensuring that even metadata like sender identity is protected.

Features

Privacy & Security

  • End-to-End Encryption - All messages encrypted using NIP-17 Gift Wraps with NIP-44 encryption
  • Encrypted Media - Images and voice messages encrypted with AES-256-GCM before upload
  • Disappearing Messages - Self-destructing messages with NIP-40 expiration
  • Account Deletion - Request data removal from relays with NIP-62 Vanish Request
  • Local Encryption - Optional password protection with AES-256 for all local data
  • No Analytics - Zero tracking, no telemetry, no server-side storage

Communication

  • Text Messages - Rich text messaging with emoji support
  • Voice Messages - Record and send encrypted voice messages (up to 60s)
  • Image Sharing - Send encrypted images with automatic compression
  • Real-time Delivery - Instant message delivery via Nostr relays

Identity

  • No Account Required - Your cryptographic keys are your identity
  • QR Code Import/Export - Easily transfer your identity between devices
  • Key Backup - Secure backup of your private key (nsec)

Sync & Access

  • Device Sync - Transfer chats between devices via P2P WebRTC connection
  • PWA - Install as a Progressive Web App on any device
  • Multi-Language - English and German support
  • Dark/Light Theme - System-aware theme with manual override

How It Works

NIP-17 Gift Wraps

Messages are wrapped in multiple layers of encryption:

┌─────────────────────────────────────┐
│         Gift Wrap (kind 1059)       │  ← Signed with random key
│  ┌───────────────────────────────┐  │     Encrypted to recipient
│  │       Seal (kind 13)          │  │
│  │  ┌─────────────────────────┐  │  │  ← Signed by sender
│  │  │    Rumor (kind 14)      │  │  │     Encrypted content
│  │  │  - sender pubkey        │  │  │
│  │  │  - message content      │  │  │  ← Actual message
│  │  │  - timestamp            │  │  │
│  │  │  - expiration (NIP-40)  │  │  │
│  │  └─────────────────────────┘  │  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘

This ensures:

  • Relays cannot read message content
  • Relays cannot identify the sender
  • Only the intended recipient can decrypt
  • Messages can auto-expire

Encrypted File Upload

Media files are encrypted client-side before upload:

  1. Generate random AES-256 key
  2. Encrypt file with AES-GCM
  3. Encrypt AES key with NIP-44 (recipient's pubkey)
  4. Upload encrypted blob to Blossom/NIP-96 server
  5. Send URL + encrypted key in message

Getting Started

Development

# Install dependencies
npm install

# Start development server
npm run dev

# Run tests
npm run test

# Build for production
npm run build

Android Build (Capacitor)

# Sync with Capacitor
npx cap sync android

# Build APK
cd android && ./gradlew assembleRelease

Tech Stack

  • React 19 - UI framework
  • TypeScript - Type safety
  • Vite - Build tool & dev server
  • Mantine 7 - UI component library
  • Zustand - State management
  • IndexedDB - Encrypted local storage
  • nostr-tools - Nostr protocol implementation
  • Capacitor - Native mobile builds
  • WebRTC - P2P device sync
  • Vitest - Unit testing

Supported NIPs

NIP Description Status
NIP-01 Basic protocol
NIP-17 Private Direct Messages
NIP-40 Expiration Timestamp
NIP-44 Encrypted Payloads
NIP-59 Gift Wrap
NIP-62 Request to Vanish
NIP-96 HTTP File Storage
NIP-98 HTTP Auth

Project Structure

src/
├── components/          # React components
│   ├── chat/            # Chat UI (MessageBubble, MessageInput)
│   ├── onboarding/      # Account setup flow
│   ├── settings/        # Settings screens
│   └── sync/            # Device sync UI
├── hooks/               # Custom React hooks
│   └── useAudioRecorder # Voice message recording
├── i18n/                # Translations (en, de)
├── pages/               # Main app pages
├── services/            # Core services
│   ├── crypto.ts        # NIP-17/44/59/62 implementation
│   ├── db.ts            # IndexedDB with encryption
│   ├── fileUpload.ts    # Encrypted file upload
│   ├── relay.ts         # Nostr relay pool
│   └── webrtc.ts        # P2P sync connection
├── stores/              # Zustand state stores
└── utils/               # Helper functions

Security Considerations

  • Private keys are stored locally and never transmitted
  • All network traffic uses encrypted Nostr events
  • Media files are encrypted before leaving the device
  • Optional password protection encrypts all local data
  • No server-side components or data collection
  • Open source and auditable

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Third-Party Licenses

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages