Zum Inhalt

Security & Privacy

🔐 Security-First Architektur

CommunicationFinder behandelt Security und Privacy als fundamentale Design-Prinzipien, nicht als Nachgedanken.


🛡️ Threat Model

Was schützen wir?

graph TB A[Zu schützende Assets] --> B[User Settings] A --> C[User Identity] A --> D[Kommunikations-Patterns] A --> E[Meta-Daten] B --> F[Angriffsvektoren] C --> F D --> F E --> F F --> G[Unauthorized Access] F --> H[Data Leakage] F --> I[Manipulation] F --> J[Tracking] style A fill:#E3F2FD style F fill:#ffcdd2

Angreifer-Profile

Profil Motivation Fähigkeiten Risiko
Neugieriger User Snooping Niedrig Niedrig
Insider Threat Data Theft Mittel Mittel
Competitor Industrial Espionage Hoch Hoch
State Actor Surveillance Sehr Hoch Sehr Hoch

🔒 Verteidigungsschichten

Layer 1: Client-Side Encryption

Prinzip: Daten werden verschlüsselt, bevor sie den Client verlassen.

class ClientSideEncryption {
    async encryptSettings(settings, password) {
        // 1. Generate Salt
        const salt = crypto.getRandomValues(new Uint8Array(16));

        // 2. Derive Key from Password
        const keyMaterial = await crypto.subtle.importKey(
            'raw',
            new TextEncoder().encode(password),
            'PBKDF2',
            false,
            ['deriveBits', 'deriveKey']
        );

        const key = await crypto.subtle.deriveKey(
            {
                name: 'PBKDF2',
                salt,
                iterations: 100000, // OWASP recommended minimum
                hash: 'SHA-256'
            },
            keyMaterial,
            { name: 'AES-GCM', length: 256 },
            false,
            ['encrypt', 'decrypt']
        );

        // 3. Encrypt Data
        const iv = crypto.getRandomValues(new Uint8Array(12));
        const encrypted = await crypto.subtle.encrypt(
            { name: 'AES-GCM', iv },
            key,
            new TextEncoder().encode(JSON.stringify(settings))
        );

        // 4. Return Encrypted Package
        return {
            version: '1.0',
            algorithm: 'AES-256-GCM',
            iv: Array.from(iv),
            salt: Array.from(salt),
            data: Array.from(new Uint8Array(encrypted))
        };
    }

    async decryptSettings(encryptedPackage, password) {
        // Reverse process
        const keyMaterial = await crypto.subtle.importKey(
            'raw',
            new TextEncoder().encode(password),
            'PBKDF2',
            false,
            ['deriveBits', 'deriveKey']
        );

        const key = await crypto.subtle.deriveKey(
            {
                name: 'PBKDF2',
                salt: new Uint8Array(encryptedPackage.salt),
                iterations: 100000,
                hash: 'SHA-256'
            },
            keyMaterial,
            { name: 'AES-GCM', length: 256 },
            false,
            ['encrypt', 'decrypt']
        );

        const decrypted = await crypto.subtle.decrypt(
            {
                name: 'AES-GCM',
                iv: new Uint8Array(encryptedPackage.iv)
            },
            key,
            new Uint8Array(encryptedPackage.data)
        );

        return JSON.parse(new TextDecoder().decode(decrypted));
    }
}

Layer 2: Zero-Knowledge Architecture

Prinzip: Server/IPFS sieht nur verschlüsselte Blobs, nie Klartext.

sequenceDiagram participant U as User participant C as Client participant I as IPFS U->>C: Settings + Password C->>C: Encrypt(Settings, Password) C->>I: Upload(EncryptedBlob) I-->>C: CID C-->>U: Share CID + Password (separate!) Note over I: IPFS sieht nur verschlüsselte Daten U2->>I: Download(CID) I-->>U2: EncryptedBlob U2->>U2: Decrypt(EncryptedBlob, Password) U2->>U2: Use Settings

Garantie: Selbst bei IPFS-Kompromittierung → keine lesbaren Daten.


Layer 3: Anonymisierung

Prinzip: Settings enthalten keine persönlichen Informationen.

class Anonymizer {
    anonymize(rawSettings) {
        return {
            // ✅ Erlaubt: Abstrakte Gewichte
            weights: rawSettings.weights,

            // ✅ Erlaubt: Generische Regeln
            rules: rawSettings.rules.map(rule => ({
                condition: rule.condition, // "urgency > 0.8"
                channels: rule.channels,
                reason: this.genericReason(rule.reason)
            })),

            // ❌ Entfernt: Persönliche Details
            // name: REMOVED
            // email: REMOVED
            // answers: REMOVED

            // ✅ Technische Metadaten
            meta: {
                uuid: crypto.randomUUID(),
                version: '2.0',
                created: new Date().toISOString(),
                checksum: this.calculateChecksum(rawSettings)
            }
        };
    }

    genericReason(specificReason) {
        // "Weil mein Chef immer Email bevorzugt"
        // →
        // "Hohe Dringlichkeit + formale Beziehung"

        const patterns = {
            /chef|boss|manager/i: "Hierarchie-Regel",
            /kunde|client|customer/i: "Kunden-Präferenz",
            /team|kollege|colleague/i: "Team-Standard",
            /privat|persönlich|private/i: "Persönliche Präferenz"
        };

        for (const [pattern, generic] of Object.entries(patterns)) {
            if (pattern.test(specificReason)) {
                return generic;
            }
        }

        return "Kontext-basierte Regel";
    }
}

Layer 4: Access Control

Prinzip: Granulare Kontrolle über wer was sehen darf.

class AccessControl {
    async shareSettings(settings, recipient, permissions) {
        // 1. Encrypt mit Recipient's Public Key
        const recipientPublicKey = await this.fetchPublicKey(recipient);
        const encrypted = await this.encryptForRecipient(settings, recipientPublicKey);

        // 2. Set Permissions
        const accessToken = {
            recipient,
            permissions: {
                read: permissions.includes('read'),
                modify: permissions.includes('modify'),
                reshare: permissions.includes('reshare')
            },
            expires: Date.now() + (7 * 24 * 60 * 60 * 1000), // 7 Tage
            revokable: true
        };

        // 3. Store Access Token on-chain (optional)
        if (permissions.includes('revokable')) {
            await this.blockchain.storeAccessToken(accessToken);
        }

        return {
            encrypted,
            accessToken,
            cid: await this.uploadToIPFS(encrypted)
        };
    }

    async revokeAccess(accessTokenId) {
        // On-chain revocation
        await this.blockchain.revokeAccessToken(accessTokenId);

        // Nachfolgende Zugriffe werden blockiert
    }
}

🕵️ Privacy-Schutzmechanismen

1. Differential Privacy

Use Case: Aggregierte Statistiken ohne User-Tracking

class DifferentialPrivacy {
    addNoise(value, epsilon = 1.0) {
        // Laplace Mechanism
        const scale = 1 / epsilon;
        const u = Math.random() - 0.5;
        const noise = -scale * Math.sign(u) * Math.log(1 - 2 * Math.abs(u));

        return value + noise;
    }

    async publishStatistics(allSettings) {
        // Echte Statistik
        const avgWhatsAppWeight = allSettings
            .map(s => s.weights.whatsapp)
            .reduce((a, b) => a + b) / allSettings.length;

        // Mit Noise (Privacy-Schutz)
        const privatized = this.addNoise(avgWhatsAppWeight);

        // Publizieren
        return {
            metric: 'avg_whatsapp_weight',
            value: privatized,
            epsilon: 1.0,
            // Einzelne User-Werte nicht rekonstruierbar
        };
    }
}

2. K-Anonymity

Prinzip: Settings sind in Gruppe von min. K anderen ähnlichen Settings versteckt.

class KAnonymity {
    async ensureKAnonymity(settings, k = 5) {
        // Finde K-1 ähnliche Settings
        const similar = await this.findSimilar(settings, k - 1);

        if (similar.length < k - 1) {
            throw new Error(`Nicht genug ähnliche Settings (k=${k})`);
        }

        // Generalisiere Settings
        return this.generalize([settings, ...similar]);
    }

    generalize(settingsGroup) {
        // Beispiel: Runde Gewichte auf 10er
        return settingsGroup.map(s => ({
            ...s,
            weights: Object.fromEntries(
                Object.entries(s.weights).map(([k, v]) => 
                    [k, Math.round(v / 10) * 10]
                )
            )
        }));
    }
}

🔍 Audit & Compliance

DSGVO Compliance

class GDPRCompliance {
    // Art. 15 DSGVO: Auskunftsrecht
    async exportUserData(userId) {
        return {
            settings: await this.getSettings(userId),
            auditLogs: await this.getAuditLogs(userId),
            created: await this.getCreationDate(userId),
            // Alle gespeicherten Daten
        };
    }

    // Art. 17 DSGVO: Recht auf Vergessenwerden
    async deleteUserData(userId) {
        // 1. Lokale Daten löschen
        await this.deleteLocalData(userId);

        // 2. IPFS: Depublish (best effort)
        await this.ipfs.unpin(userCIDs);

        // 3. Blockchain: Pseudonymisierung
        await this.blockchain.pseudonymize(userId);

        // WICHTIG: Blockchain-Daten nicht löschbar
        // → Nur Hashes, keine persönlichen Daten on-chain!
    }

    // Art. 20 DSGVO: Datenportabilität
    async exportPortable(userId) {
        const data = await this.exportUserData(userId);

        // Standard-Format (JSON)
        return JSON.stringify(data, null, 2);
    }
}

SOC 2 Compliance (für Enterprise)

class SOC2Controls {
    // CC6.1: Logical Access Controls
    async enforceAccessControl(user, resource) {
        const authorized = await this.checkPermission(user, resource);

        if (!authorized) {
            await this.logUnauthorizedAccess(user, resource);
            throw new Error('Unauthorized');
        }

        await this.logAccess(user, resource);
        return true;
    }

    // CC7.2: System Monitoring
    async monitorAnomalies() {
        const recentAccess = await this.getRecentAccess();

        // Anomaly Detection
        const anomalies = recentAccess.filter(access => {
            return access.count > 100 || // Rate limiting
                   access.location !== access.user.usualLocation ||
                   access.time < 6 || access.time > 22; // Unusual hours
        });

        if (anomalies.length > 0) {
            await this.alertSecurityTeam(anomalies);
        }
    }
}

🚨 Incident Response

Security Incident Playbook

class IncidentResponse {
    async handleSecurityIncident(incident) {
        // 1. Contain
        await this.containThreat(incident);

        // 2. Assess
        const impact = await this.assessImpact(incident);

        // 3. Notify
        if (impact.severity >= 'HIGH') {
            await this.notifyAffectedUsers(impact.affectedUsers);
            await this.notifyAuthorities(impact); // DSGVO Art. 33
        }

        // 4. Remediate
        await this.patchVulnerability(incident.vulnerability);

        // 5. Learn
        await this.postmortem(incident);
    }

    async notifyDataBreach(breach) {
        // DSGVO Art. 34: Benachrichtigung Betroffener
        const notification = {
            subject: "Sicherheitsvorfall bei CommunicationFinder",
            body: `
                Sehr geehrte/r Nutzer/in,

                Am ${breach.date} haben wir einen Sicherheitsvorfall festgestellt:

                Art des Vorfalls: ${breach.type}
                Betroffene Daten: ${breach.affectedData}
                Maßnahmen: ${breach.remediation}

                Empfohlene Aktion: ${breach.userAction}
            `,
            severity: breach.severity
        };

        for (const user of breach.affectedUsers) {
            await this.sendNotification(user, notification);
        }

        // Meldung an Aufsichtsbehörde (innerhalb 72h)
        await this.notifyDataProtectionAuthority(breach);
    }
}

🛡️ Best Practices

Für Entwickler

// ✅ DO: Validiere alle Inputs
function validateSettings(settings) {
    if (!settings.uuid || !isValidUUID(settings.uuid)) {
        throw new Error('Invalid UUID');
    }

    if (!settings.weights || typeof settings.weights !== 'object') {
        throw new Error('Invalid weights');
    }

    // Sanitize alle User-Inputs
    return sanitize(settings);
}

// ❌ DON'T: Vertraue User-Input
function unsafeLoad(json) {
    return eval(json); // NEVER DO THIS!
}

// ✅ DO: Use Content Security Policy
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self'">

// ❌ DON'T: Inline Scripts ohne Nonce
<script>alert('XSS')</script>

Für User

## Security Checklist

- [ ] **Starke Passwörter**: Min. 12 Zeichen, gemischt
- [ ] **2FA aktiviert**: Für Wallet/DID
- [ ] **Regelmäßige Backups**: Settings exportieren
- [ ] **Verschlüsselte Speicherung**: Password-geschützte Exports
- [ ] **Vorsicht beim Teilen**: Nur vertrauenswürdige Empfänger
- [ ] **Updates**: Immer neueste Version nutzen
- [ ] **Public WiFi**: VPN nutzen bei Upload/Download

📊 Security Metrics

Monitoring-Dashboard

class SecurityMetrics {
    async getDashboard() {
        return {
            // Verschlüsselung
            encryptedSettings: await this.countEncrypted(),
            encryptionRate: '98%',

            // Zugriff
            unauthorizedAttempts: await this.countUnauthorized(),
            successRate: '99.97%',

            // Compliance
            gdprCompliant: true,
            soc2Certified: false, // Phase 4

            // Incidents
            incidentsLast30Days: 0,
            mtbf: 'Never', // Mean Time Between Failures

            // Updates
            lastSecurityAudit: '2025-10-15',
            nextAudit: '2026-01-15',
            vulnerabilitiesPatched: 23
        };
    }
}

← Zurück: Blockchain Weiter: Use Cases →