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
};
}
}