-
Notifications
You must be signed in to change notification settings - Fork 1
security_multi_party
Stand: 5. Dezember 2025
Version: v1.3.0
Kategorie: 🔒 Security
- Problem Statement
- Lösung 1: Gruppenbasierte Schlüssel (Group-KEK)
- Lösung 2: Envelope-Encryption (Multi-Recipient)
Anforderung: Mehrere Personen/Rollen/Gruppen/Abteilungen/Behörden müssen dieselben verschlüsselten Daten lesen und schreiben können, ohne dass:
- Jeder Nutzer einen eigenen verschlüsselten Datensatz erhält (Storage-Explosion)
- Daten bei Gruppen-Änderung re-encrypted werden müssen (Performance)
- Ein zentraler Admin alle Daten entschlüsseln kann (Zero-Trust verletzt)
Beispiel-Szenarien:
-
HR-Abteilung: Alle Mitarbeiter von
hr_teamkönnen Gehalts-Daten lesen/schreiben - Projekt-Team: Alle Mitglieder von Projekt "Apollo" können Projektdokumente bearbeiten
- Behörden-übergreifend: Polizei, Staatsanwaltschaft, Gericht können Ermittlungsakte teilen
-
Rollenbasiert: Alle mit Rolle
doctorkönnen Patientenakten lesen
┌────────────────────────────────────────────────┐
│ VCC-PKI Root CA │
│ └── Service Cert (themis-db.vcc.local) │
└─────────────────┬──────────────────────────────┘
│ verschlüsselt
▼
┌────────────────────────────────────────────────┐
│ Master KEK (Key Encryption Key) │
│ - Pro ThemisDB-Instanz │
│ - Verschlüsselt mit PKI-Zertifikat │
└─────────────────┬──────────────────────────────┘
│ verschlüsselt
▼
┌────────────────────────────────────────────────┐
│ Gruppen-DEKs (Data Encryption Keys) │
│ - Pro Gruppe/Rolle/Abteilung (z.B. "hr_team") │
│ - Gespeichert als: "key:group:hr_team" │
│ - Verschlüsselt mit Master KEK │
└─────────────────┬──────────────────────────────┘
│ verschlüsselt
▼
[Shared Encrypted Data]
// include/security/group_key_manager.h
class GroupKeyManager {
public:
// Erstelle oder lade DEK für eine Gruppe
std::vector<uint8_t> getGroupDEK(const std::string& group_name);
// Rotiere Gruppen-Key (bei Mitglieder-Austritt)
void rotateGroupKey(const std::string& group_name);
// Prüfe ob User Zugriff auf Gruppe hat (via JWT)
bool hasGroupAccess(const JWTClaims& claims, const std::string& group_name);
private:
std::vector<uint8_t> master_kek_; // Von PKI abgeleitet
std::unordered_map<std::string, std::vector<uint8_t>> group_deks_; // Cache
};// Bei jedem Schreibvorgang
std::string jwt_token = request.get_header("Authorization");
auto claims = jwt_validator_->parseAndValidate(jwt_token);
// Bestimme zuständige Gruppe aus JWT oder Schema
std::string group = determineDataOwnerGroup(claims, field_schema);
// z.B. "hr_team" aus claims.groups[0] oder Schema-Annotation
// Hole Gruppen-DEK (gecacht, verschlüsselt in DB)
auto group_dek = group_key_mgr_->getGroupDEK(group);
// Leite Field-Key ab
auto field_key = HKDF_SHA256(
group_dek,
salt = field_name,
info = "field-encryption:" + group
);
// Verschlüsseln
auto ciphertext = AES_GCM_encrypt(plaintext, field_key, nonce);
// Metadaten speichern (für Entschlüsselung)
entity.setField("salary_encrypted", base64(ciphertext));
entity.setField("salary_group", group); // "hr_team"// Bei jedem Lesevorgang
auto encrypted_salary = entity.getField("salary_encrypted");
auto data_group = entity.getField("salary_group").as<std::string>();
// Prüfe ob aktueller User Zugriff hat
if (!group_key_mgr_->hasGroupAccess(claims, data_group)) {
throw UnauthorizedException("User not member of group: " + data_group);
}
// Hole Gruppen-DEK
auto group_dek = group_key_mgr_->getGroupDEK(data_group);
// Leite Field-Key ab (gleich wie beim Verschlüsseln)
auto field_key = HKDF_SHA256(group_dek, salt = "salary", info = "field-encryption:" + data_group);
// Entschlüsseln
auto plaintext = AES_GCM_decrypt(base64_decode(encrypted_salary), field_key, nonce);✅ Shared Access: Alle Gruppenmitglieder nutzen denselben DEK
✅ Keine Daten-Duplizierung: Ein verschlüsselter Datensatz für alle
✅ Skalierbar: Gruppenmitgliedschaft über JWT-Claims (Keycloak)
✅ Zero-Trust: Admin ohne Gruppenmitgliedschaft kann nicht entschlüsseln
[Plaintext Data]
│
│ verschlüsselt mit
▼
┌─────────────────────┐
│ Data Encryption │ ← Zufälliger DEK pro Datensatz
│ Key (DEK) │ (AES-256, 32 Bytes)
└─────────────────────┘
│
│ wird verschlüsselt für jeden Empfänger
▼
┌──────────────────────────────────────────┐
│ Wrapped Keys (einer pro Empfänger): │
│ - DEK_wrapped_alice (RSA/AES für Alice)│
│ - DEK_wrapped_bob (RSA/AES für Bob) │
│ - DEK_wrapped_hr (für Gruppe hr) │
└──────────────────────────────────────────┘
// Pro verschlüsseltem Feld: Speichere multiple wrapped DEKs
struct EncryptedField {
std::string ciphertext; // Mit DEK verschlüsselte Daten
std::string nonce; // IV/Nonce für AES-GCM
// Pro authorisierter Gruppe/User: wrapped DEK
std::map<std::string, std::string> wrapped_keys;
// z.B. {"hr_team": "base64(RSA_encrypt(DEK, hr_pubkey))",
// "admin_group": "base64(RSA_encrypt(DEK, admin_pubkey))"}
};
// Beim Verschlüsseln
std::vector<uint8_t> dek = random_bytes(32); // Zufälliger DEK
auto ciphertext = AES_GCM_encrypt(plaintext, dek, nonce);
// Wrap DEK für jede autorisierte Gruppe
for (const auto& group : authorized_groups) {
auto group_pubkey = getGroupPublicKey(group);
auto wrapped_dek = RSA_encrypt(dek, group_pubkey);
field.wrapped_keys[group] = base64(wrapped_dek);
}
// Beim Entschlüsseln
auto user_group = claims.groups[0]; // Erste Gruppe des Users
if (!field.wrapped_keys.contains(user_group)) {
throw UnauthorizedException("No key for your group");
}
auto group_privkey = getGroupPrivateKey(user_group); // Aus KMS/HSM
auto dek = RSA_decrypt(base64_decode(field.wrapped_keys[user_group]), group_privkey);
auto plaintext = AES_GCM_decrypt(field.ciphertext, dek, field.nonce);✅ Feingranular: Zugriff pro Feld konfigurierbar
✅ Einfache Zugriffsänderung: Neuen Empfänger hinzufügen = neuen wrapped key hinzufügen (kein Re-Encrypt der Daten)
✅ User-Austritt sicher: Wrapped key löschen → kein Zugriff mehr
Kombination aus Gruppen-DEKs (Lösung 1) für Standard-Zugriff und Envelope-Encryption (Lösung 2) für feingranulare Freigaben.
{
"salary": {
"ciphertext": "...",
"encryption_group": "hr_team",
"encryption_type": "group-dek"
}
}Alle hr_team-Mitglieder können lesen/schreiben.
{
"classified_document": {
"ciphertext": "...",
"encryption_type": "envelope",
"wrapped_keys": {
"police_dept": "...",
"prosecutors_office": "...",
"court_judges": "..."
}
}
}Nur diese drei Behörden können lesen.
// BaseEntity erweitern für Encryption-Metadaten
class EncryptedFieldMetadata {
public:
enum class Type {
NONE, // Unverschlüsselt
GROUP_DEK, // Gruppen-basiert (Lösung 1)
ENVELOPE // Multi-Recipient (Lösung 2)
};
Type type;
std::string encryption_group; // Für GROUP_DEK
std::map<std::string, std::string> wrapped_keys; // Für ENVELOPE
std::string algorithm = "AES-256-GCM";
std::string nonce; // Base64
};Aktuell (BaseEntity):
key: users:alice
value: {
"pk": "users:alice",
"name": "Alice",
"email": "alice@vcc.local"
}
Mit Group-Encryption:
key: users:alice
value: {
"pk": "users:alice",
"name": "Alice",
"salary_encrypted": "base64_ciphertext",
"salary_group": "hr_team",
"salary_nonce": "base64_nonce"
}
Mit Envelope-Encryption:
key: users:alice
value: {
"pk": "users:alice",
"name": "Alice",
"ssn_encrypted": "base64_ciphertext",
"ssn_encryption_type": "envelope",
"ssn_nonce": "base64_nonce",
"ssn_wrapped_keys": {
"hr_team": "base64_wrapped_dek",
"audit_team": "base64_wrapped_dek"
}
}
# Gruppen-DEKs (verschlüsselt mit Master KEK)
key:group:hr_team → encrypted_dek (32 bytes AES key, encrypted)
key:group:finance_dept → encrypted_dek
key:group:admin → encrypted_dek
# Gruppen-Membership-Cache (optional, für Performance)
key:group:hr_team:members → ["alice", "bob", "charlie"]
# Audit-Log für Key-Rotation
key:group:hr_team:history → [
{"version": 1, "created": 1730000000, "rotated": 1730100000},
{"version": 2, "created": 1730100000, "active": true}
]
-
✅ PKIKeyProvider erweitern
-
getGroupDEK(group_name)→ lädt/erstellt verschlüsselte DEKs -
rotateGroupKey(group_name)→ erstellt neuen DEK, markiert alten als deprecated
-
-
JWT-Claims-Mapping
-
JWTValidatorextrahiertgroups/rolesaus Token -
AuthMiddlewareprüft Gruppenmitgliedschaft
-
-
Schema-Annotation
{ "fields": { "salary": { "type": "int64", "encrypted": true, "encryption_group": "hr_team" } } } -
QueryEngine-Integration
- Bei INSERT/UPDATE: Verschlüssele mit Gruppen-DEK
- Bei SELECT: Prüfe Gruppenmitgliedschaft, entschlüssele mit Gruppen-DEK
-
KMS-Integration (für Gruppen-Keypairs)
- Generiere RSA-Keypair pro Gruppe
- Speichere Private Keys in HSM/KMS oder verschlüsselt in DB
-
Envelope-Wrapping
- Implementiere
EnvelopeEncryptionKlasse - Wrap/Unwrap DEKs mit RSA/ECIES
- Implementiere
-
API-Erweiterung
POST /api/v1/data/share { "document_id": "doc123", "grant_access_to": ["police_dept", "prosecutors_office"] }
Für VCC-Kontext:
-
Start mit Gruppen-DEK (Lösung 1)
- Nutze bestehende Keycloak-Gruppen (
hr_team,finance_dept, etc.) - Mappt gut auf Behörden-Struktur (Abteilungen, Ämter)
- Wenig Storage-Overhead
- Nutze bestehende Keycloak-Gruppen (
-
Später Envelope für Sonderfälle (Lösung 2)
- Wenn behördenübergreifende Ad-hoc-Freigaben nötig
- Wenn feingranulare Zugriffskontrolle auf Feld-Ebene gefordert
-
DB-Änderungen minimal
- Nur Metadaten-Felder hinzufügen (
*_encrypted,*_group,*_nonce) - Keine Breaking Changes für unverschlüsselte Felder
- Rückwärtskompatibel:
encrypted=false→ wie bisher
- Nur Metadaten-Felder hinzufügen (
Nächster Schritt:
Soll ich die Gruppen-DEK-Implementierung prototypisch in PKIKeyProvider ergänzen?
ThemisDB v1.3.4 | GitHub | Documentation | Discussions | License
Last synced: January 02, 2026 | Commit: 6add659
Version: 1.3.0 | Stand: Dezember 2025
- Übersicht
- Home
- Dokumentations-Index
- Quick Reference
- Sachstandsbericht 2025
- Features
- Roadmap
- Ecosystem Overview
- Strategische Übersicht
- Geo/Relational Storage
- RocksDB Storage
- MVCC Design
- Transaktionen
- Time-Series
- Memory Tuning
- Chain of Thought Storage
- Query Engine & AQL
- AQL Syntax
- Explain & Profile
- Rekursive Pfadabfragen
- Temporale Graphen
- Zeitbereichs-Abfragen
- Semantischer Cache
- Hybrid Queries (Phase 1.5)
- AQL Hybrid Queries
- Hybrid Queries README
- Hybrid Query Benchmarks
- Subquery Quick Reference
- Subquery Implementation
- Content Pipeline
- Architektur-Details
- Ingestion
- JSON Ingestion Spec
- Enterprise Ingestion Interface
- Geo-Processor Design
- Image-Processor Design
- Hybrid Search Design
- Fulltext API
- Hybrid Fusion API
- Stemming
- Performance Tuning
- Migration Guide
- Future Work
- Pagination Benchmarks
- Enterprise README
- Scalability Features
- HTTP Client Pool
- Build Guide
- Implementation Status
- Final Report
- Integration Analysis
- Enterprise Strategy
- Verschlüsselungsstrategie
- Verschlüsselungsdeployment
- Spaltenverschlüsselung
- Encryption Next Steps
- Multi-Party Encryption
- Key Rotation Strategy
- Security Encryption Gap Analysis
- Audit Logging
- Audit & Retention
- Compliance Audit
- Compliance
- Extended Compliance Features
- Governance-Strategie
- Compliance-Integration
- Governance Usage
- Security/Compliance Review
- Threat Model
- Security Hardening Guide
- Security Audit Checklist
- Security Audit Report
- Security Implementation
- Development README
- Code Quality Pipeline
- Developers Guide
- Cost Models
- Todo Liste
- Tool Todo
- Core Feature Todo
- Priorities
- Implementation Status
- Roadmap
- Future Work
- Next Steps Analysis
- AQL LET Implementation
- Development Audit
- Sprint Summary (2025-11-17)
- WAL Archiving
- Search Gap Analysis
- Source Documentation Plan
- Changefeed README
- Changefeed CMake Patch
- Changefeed OpenAPI
- Changefeed OpenAPI Auth
- Changefeed SSE Examples
- Changefeed Test Harness
- Changefeed Tests
- Dokumentations-Inventar
- Documentation Summary
- Documentation TODO
- Documentation Gap Analysis
- Documentation Consolidation
- Documentation Final Status
- Documentation Phase 3
- Documentation Cleanup Validation
- API
- Authentication
- Cache
- CDC
- Content
- Geo
- Governance
- Index
- LLM
- Query
- Security
- Server
- Storage
- Time Series
- Transaction
- Utils
Vollständige Dokumentation: https://makr-code.github.io/ThemisDB/