xPulse
🇩🇪 DE

Chat Crypto – Concept

Status: CONCEPT · Erstellt April 2026 Übergeordnet: TOOL_chat_roadmap.md Verwandt: TOOL_chat_concept-identity.md, TOOL_chat_concept-device.md Verwandt: TOOL_chat_concept-message.md, @xpulse/crypto


Grundsätze

Privacy First – kein Server sieht jemals Nachrichteninhalte. Vertrauen durch Verifikation – nicht durch Versprechen. Transparenz – was der Peer sieht ist dokumentiert und bewusst entschieden.


Warum ein eigenes Konzept?

Kryptographie zieht sich durch alle Teile von xPulse Chat – Identität, Nachrichten, Devices, Sync. Dieses Konzept legt fest:


Schlüssel-Übersicht

Pro User:
userId = SHA-256(userPublicKey) – öffentlich, stabil
userPublicKey = öffentlich – Peers kennen ihn
userPrivateKey = geheim – verlässt nie das Gerät
Pro Gerät:
clientId = SHA-256(clientPublicKey) – öffentlich, gerätegebunden
clientPublicKey = öffentlich – Peers kennen ihn
clientPrivateKey = geheim – verlässt nie das Gerät

Was der Peer sieht

Peer sieht: userId → wer du bist
userPublicKey → zum Verifizieren deiner Nachrichten
Peer sieht NICHT: clientId → welches Gerät
clientPublicKey → Geräte-Detail
privateKeys → niemals
Anzahl Geräte → intern

Der userPublicKey ist by Design öffentlich – genau wie bei SSH. Jeder mit dem du chattest kennt ihn. Das ist gewollt und notwendig für E2EE Verifikation.


Nachrichten-Verschlüsselung (E2EE)

Nachrichten werden Ende-zu-Ende verschlüsselt über den WebRTC DataChannel.

Sender →
Nachricht mit AES-GCM verschlüsseln
Schlüssel = ECDH(senderPrivateKey, receiverPublicKey)
→ verschlüsselte Nachricht über DataChannel
Empfänger →
Schlüssel = ECDH(receiverPrivateKey, senderPublicKey)
→ entschlüsseln → Klartext

Kein Server sieht jemals den Inhalt – die Verschlüsselung passiert ausschließlich zwischen den zwei Peers.


Message-Signing

Jede Nachricht wird mit dem userPrivateKey des Senders signiert. Der Empfänger verifiziert mit dem userPublicKey des Senders.

Sender →
Nachricht erstellen
Signatur = sign(message, userPrivateKey)
→ { ...message, signature } über DataChannel
Empfänger →
verify(message, signature, senderPublicKey)
OK → Nachricht ist authentisch ✅
NOK → Nachricht verwerfen ❌

Was Message-Signing verhindert:

signature in der Message-Struktur:

meta: {
receivedAt: Number,
viewedAt: Number,
signature: String, // Base64 – Signatur der Nachricht
}

Verifikation beim Sync

Beim Sync kommen Messages vom Peer – der Comparator prüft die Signatur bevor eine Message gemergt wird:

Message kommt rein →
signature vorhanden? →
verify(message, signature, senderPublicKey) →
OK → normal weiter (Graveyard, Duplikat, Merge)
NOK → Message verwerfen, warn loggen
keine signature (v0 migriert) →
akzeptieren – Migration hat keine Signaturen

Schlüssel-Austausch beim Pairing

Beim Chat-Pairing und Device-Pairing tauschen beide Peers ihre userPublicKeys aus:

Pairing →
A sendet userPublicKey → B speichert für A
B sendet userPublicKey → A speichert für B
→ beide können ab jetzt Nachrichten verschlüsseln + verifizieren

Der userPublicKey wird lokal gespeichert:

xpulse_chat_{userId}_peer_{peerId}_public_key

localStorage – Crypto Keys

// User-Keypair
xpulse_identity_{userId}_public_key ← öffentlich
xpulse_identity_{userId}_private_key ← AES-GCM verschlüsselt mit PBKDF2(pw + salt)
xpulse_identity_{userId}_salt ← Salt für PBKDF2
// Client-Keypair
xpulse_identity_client_public_key ← öffentlich
xpulse_identity_client_private_key ← AES-GCM verschlüsselt
// Bekannte Peer Public Keys
xpulse_chat_{userId}_peer_{peerId}_public_key ← Peer's userPublicKey

Algorithmen

Zweck Algorithmus Hinweis
Keypair Generierung Ed25519 (Fallback: ECDSA P-256) Identity + Signing
Schlüsselaustausch ECDH Nachrichten-Verschlüsselung
Nachrichten-Verschlüsselung AES-GCM via @xpulse/crypto
Schlüsselableitung PBKDF2 Passwort → Encryption Key
Hashing SHA-256 userId + clientId Ableitung
Signing Ed25519 (Fallback: ECDSA P-256) Message-Signatur

Offene Punkte

Thema Stand
Key-Rotation – Keypair erneuern ohne userId zu ändern TBD – komplex, später
Peer Public Key Verifikation out-of-band (z.B. QR-Vergleich) TBD – Nice-to-have
de/concept/crypto.md 2026-04-17