Technische Whitepapers

Ausführliche technische Dokumentation der kryptografischen Architektur, des Sicherheitsmodells und des Datenschutz-Engineerings von PDF Pro. Verfasst für sicherheitsbewusste Nutzer, Prüfer und Gutachter.

Veröffentlicht: 16. April 2025 Zuletzt aktualisiert: 16. April 2026 Version: 2.0

Whitepaper-Verzeichnis

  1. Ende-zu-Ende-verschlüsselter Dateitransfer
  2. Datenschutzorientierte kryptografische Dokumentensignatur

Ende-zu-Ende-verschlüsselter Dateitransfer

PDF Pro Whitepaper WP-001 — Architektur und Sicherheitsanalyse

1.1 Kurzfassung

Dieses Whitepaper beschreibt die Architektur des Secure-Transfer-Systems von PDF Pro, eines Zero-Knowledge-Mechanismus zur Dateiübertragung, bei dem Dateien vor dem Upload clientseitig mit AES-256-GCM verschlüsselt werden. Der Server speichert ausschließlich opakes Chiffrat und ist zu keinem Zeitpunkt in der Lage, Dateiinhalte zu entschlüsseln, einzusehen oder zu lesen. Das System unterstützt zwei Schlüsselmodi: einen automatisch erzeugten Zufallsschlüssel (der über das URL-Fragment übertragen wird, welches niemals an den Server gesendet wird) oder einen aus einer Passphrase abgeleiteten Schlüssel mittels PBKDF2. In beiden Modi existiert der Verschlüsselungsschlüssel ausschließlich in den Browsern von Absender und Empfänger. Dieses Dokument beschreibt die kryptografischen Primitiven, den Datenfluss, das Bedrohungsmodell sowie die ehrlich dargelegten Einschränkungen des Systems.

1.2 Architekturübersicht

Das Secure-Transfer-System folgt einer strikten Trennung zwischen Client und Server, bei der alle kryptografischen Operationen ausschließlich im Browser stattfinden:

Der Server ist bewusst als „dumme Leitung" für verschlüsselte Daten konzipiert. Er hat keine Kenntnis vom Verschlüsselungsschlüssel, der Passphrase oder den Dateiinhalten. Dies wird architektonisch durchgesetzt und nicht bloß durch Richtlinien.

Designprinzip: Der Server sollte kompromittierbar sein, ohne dass dadurch Nutzerdaten kompromittiert werden. Selbst bei vollständigem Datenbankzugriff und serverseitiger Codeausführung kann ein Angreifer übertragene Dateien nicht entschlüsseln.

1.3 Verschlüsselung: AES-256-GCM über die Web Crypto API

Die gesamte Dateiverschlüsselung verwendet den authentifizierten Verschlüsselungsalgorithmus AES-256-GCM, der über die native Web Crypto API des Browsers angesprochen wird. Dies gewährleistet sowohl Vertraulichkeit (Daten können nicht gelesen werden) als auch Integrität (Daten können nicht unbemerkt verändert werden).

1.3.1 Algorithmusparameter

ParameterWertBegründung
AlgorithmusAES-256-GCMNIST-zugelassene, authentifizierte Verschlüsselung mit assoziierten Daten (AEAD)
Schlüssellänge256 BitMaximale AES-Schlüssellänge; bietet 128-Bit-Sicherheit gegen Brute-Force-Angriffe
IV-Länge96 Bit (12 Byte)Von NIST empfohlene IV-Länge für den GCM-Modus
Tag-Länge128 Bit (16 Byte)Vollständiger Authentifizierungs-Tag für maximalen Integritätsschutz
IV-Erzeugungcrypto.getRandomValues()Kryptografisch sicherer Zufallszahlengenerator

1.3.2 Implementierung der Verschlüsselung

// Vereinfachter Verschlüsselungsablauf (Web Crypto API)

const iv = crypto.getRandomValues(new Uint8Array(12));
const salt = crypto.getRandomValues(new Uint8Array(16));

// Schlüssel aus Passphrase ableiten (siehe Abschnitt 1.4)
const key = await deriveKey(passphrase, salt);

// Datei verschlüsseln
const ciphertext = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv: iv },
  key,
  fileArrayBuffer
);

// Paketstruktur: [salt (16B)] + [iv (12B)] + [ciphertext + tag]
const blob = concatenate(salt, iv, ciphertext);

Der finale verschlüsselte Blob ist eine Verkettung dreier Komponenten: des 16 Byte langen Salt (für die Schlüsselableitung verwendet), des 12 Byte langen IV (für AES-GCM verwendet) und des Chiffrats mit angehängtem 16 Byte langen GCM-Authentifizierungs-Tag. Dieser Blob ist das, was der Server empfängt und speichert.

1.4 Schlüsselerzeugung & -transport

Secure Transfer unterstützt zwei sich gegenseitig ausschließende Schlüsselmodi. Der Modus wird vom Absender beim Erstellen der Übertragung gewählt.

1.4.1 Modus A — Automatisch erzeugter Schlüssel (Standard)

Im Standardmodus ist keine Passphrase beteiligt. Der Browser erzeugt direkt einen kryptografisch zufälligen 256-Bit-AES-Schlüssel:

1.4.2 Modus B — Passphrasengeschützte Übertragung

Wenn der Absender eine Passphrase festlegt, wird der Schlüssel mittels PBKDF2 aus dieser Passphrase abgeleitet:

1.4.3 PBKDF2-Parameter (Modus B)

ParameterWertBegründung
AlgorithmusPBKDF2Gemäß NIST SP 800-132 empfohlen; umfassend geprüft
HashfunktionSHA-256Kryptografische Standard-Hashfunktion; 256-Bit-Ausgabe
Iterationen600.000Erfüllt die OWASP-Empfehlung 2023 für PBKDF2-SHA256
Salt-Länge128 Bit (16 Byte)Eindeutig je Übertragung; verhindert Rainbow-Table-Angriffe
Ausgabe-Schlüssellänge256 BitEntspricht der Anforderung von AES-256

1.4.4 Implementierung der Schlüsselableitung (Modus B)

async function deriveKey(passphrase, salt) {
  // Passphrase als rohes Schlüsselmaterial importieren
  const keyMaterial = await crypto.subtle.importKey(
    "raw",
    new TextEncoder().encode(passphrase),
    { name: "PBKDF2" },
    false,
    ["deriveKey"]
  );

  // AES-256-GCM-Schlüssel ableiten
  return crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt: salt,
      iterations: 600000,
      hash: "SHA-256"
    },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    false,
    ["encrypt", "decrypt"]
  );
}

Sicherheitshinweis: Die Sicherheit hängt in Modus B von der Entropie der Passphrase ab. Wir empfehlen Passphrasen mit mindestens 12 Zeichen, die Groß- und Kleinbuchstaben, Ziffern sowie Symbole kombinieren.

1.5 Datenfluss

Der vollständige Lebenszyklus einer sicheren Übertragung verläuft wie folgt:

1.5.1 Senden (Upload) — Modus A (automatisch erzeugter Schlüssel)

  1. Der Absender wählt eine Datei im Browser aus.
  2. Der Browser erzeugt einen zufälligen 256-Bit-AES-GCM-Schlüssel und einen zufälligen 12 Byte langen IV mit crypto.getRandomValues().
  3. Der Browser verschlüsselt die Datei mittels AES-256-GCM und erzeugt Chiffrat und Authentifizierungs-Tag.
  4. Der Browser verkettet [IV | Chiffrat+Tag] zu einem einzelnen Blob.
  5. Der Browser lädt den verschlüsselten Blob über HTTPS auf den Server hoch.
  6. Der Server speichert den Blob in Supabase Storage und erstellt einen Metadatensatz (Übertragungs-ID, Ablauf, Downloadlimit, Dateiname, Dateigröße).
  7. Der Server gibt eine Übertragungs-URL zurück. Der Browser hängt den exportierten Schlüssel an das URL-Fragment (#) an.
  8. Der Absender teilt die vollständige URL (mit Fragment) mit dem Empfänger.

1.5.2 Senden (Upload) — Modus B (Passphrase)

  1. Der Absender wählt eine Datei aus und gibt eine Passphrase im Browser ein.
  2. Der Browser erzeugt ein zufälliges 16 Byte langes Salt und einen 12 Byte langen IV mittels crypto.getRandomValues().
  3. Der Browser leitet aus der Passphrase mittels PBKDF2 (600.000 Iterationen) einen AES-256-Schlüssel ab.
  4. Der Browser verschlüsselt die Datei mittels AES-256-GCM und erzeugt Chiffrat und Authentifizierungs-Tag.
  5. Der Browser verkettet [Salt | IV | Chiffrat+Tag] zu einem einzelnen Blob.
  6. Der Browser lädt den verschlüsselten Blob über HTTPS auf den Server hoch.
  7. Der Server speichert den Blob in Supabase Storage und erstellt einen Metadatensatz (Übertragungs-ID, Ablauf, Downloadlimit, Dateiname, Dateigröße).
  8. Der Server gibt eine Übertragungs-URL zurück, die die Übertragungs-ID enthält.
  9. Der Absender teilt die Übertragungs-URL und die Passphrase über getrennte Kanäle mit dem Empfänger.

1.5.3 Empfangen (Download) — Modus A

  1. Der Empfänger öffnet die vollständige Übertragungs-URL (mit Schlüssel im Fragment).
  2. Der Browser extrahiert den AES-Schlüssel aus dem URL-Fragment (wird nie an den Server gesendet).
  3. Der Browser lädt den verschlüsselten Blob über HTTPS vom Server herunter.
  4. Der Browser extrahiert den IV (erste 12 Byte) aus dem Blob.
  5. Der Browser entschlüsselt das Chiffrat mittels AES-256-GCM mit extrahiertem Schlüssel und IV.
  6. Ist die Entschlüsselung erfolgreich (GCM-Tag ist gültig), wird die Klartextdatei dem Nutzer bereitgestellt.
  7. Der Server aktualisiert den Download-Zähler und löscht den Blob, falls „Burn on read" aktiviert ist.

1.5.4 Empfangen (Download) — Modus B

  1. Der Empfänger öffnet die Übertragungs-URL und gibt die Passphrase im Browser ein.
  2. Der Browser lädt den verschlüsselten Blob über HTTPS vom Server herunter.
  3. Der Browser extrahiert das Salt (erste 16 Byte) und den IV (nächste 12 Byte) aus dem Blob.
  4. Der Browser leitet aus Passphrase + Salt mittels PBKDF2 (600.000 Iterationen) den AES-256-Schlüssel ab.
  5. Der Browser entschlüsselt das Chiffrat mittels AES-256-GCM mit abgeleitetem Schlüssel und IV.
  6. Ist die Entschlüsselung erfolgreich (GCM-Tag ist gültig), wird die Klartextdatei dem Nutzer bereitgestellt.
  7. Schlägt die Entschlüsselung fehl (falsche Passphrase = falscher Schlüssel = ungültiger GCM-Tag), wird ein Fehler angezeigt.
  8. Der Server aktualisiert den Download-Zähler und löscht den Blob, falls „Burn on read" aktiviert ist.

1.6 Was der Server speichert und was er niemals sieht

DatenelementServerzugriff?Details
Verschlüsselter Blob (Salt + IV + Chiffrat + Tag)JaOpake Binärdaten; der Server kann die Inhalte nicht interpretieren
Übertragungs-IDJaÜbertragungs-IDs sind UUID-v4-Werte, erzeugt durch PostgreSQLs gen_random_uuid(), und liefern 122 Bit kryptografische Zufälligkeit aus dem serverseitigen CSPRNG
Ursprünglicher DateinameJaIn den Metadaten gespeichert zur Anzeige beim Empfänger
Ursprüngliche DateigrößeJaIn den Metadaten zu Anzeigezwecken gespeichert
AblaufzeitstempelJaWird zur Durchsetzung der automatischen Löschung verwendet
Downloadanzahl / LimitJaWird zur Durchsetzung von „Burn on read" und Downloadlimits verwendet
Absender-Nutzer-ID (bei Authentifizierung)JaVerknüpft die Übertragung zu Verwaltungszwecken mit dem Konto
PassphraseNein — niemalsWird niemals an den Server gesendet; verlässt niemals den Browser
Abgeleiteter VerschlüsselungsschlüsselNein — niemalsExistiert nur während der Ver-/Entschlüsselung im Browserspeicher
Klartext-DateiinhalteNein — niemalsNur verschlüsseltes Chiffrat erreicht den Server
PBKDF2-IterationsanzahlNeinIm Client fest kodiert; wird nicht an den Server übermittelt

1.7 Automatische Ablaufzeit und Burn-on-Read

Alle sicheren Übertragungen sind ihrer Gestaltung nach flüchtig. Es gibt keine Option zur dauerhaften Speicherung.

1.7.1 Ablaufoptionen

OptionVerhaltenDurchsetzung
Burn on readDer verschlüsselte Blob wird unmittelbar nach dem ersten erfolgreichen Download gelöschtServerseitig: Blob wird nach Abschluss des Download-Streams aus dem Speicher gelöscht
1 StundeAutomatische Löschung nach 1 Stunde unabhängig vom DownloadstatusServerseitig: geplanter Aufräumjob + Ablaufprüfung beim Zugriff
24 StundenAutomatische Löschung nach 24 StundenWie oben
7 TageMaximale Aufbewahrung; automatische Löschung nach 7 TagenWie oben

1.7.2 Löschgarantie

Wenn eine Übertragung abläuft oder beim Lesen vernichtet wird, wird der verschlüsselte Blob dauerhaft aus Supabase Storage gelöscht. Der Metadatensatz wird 30 Tage lang in einem weich-gelöschten Zustand aufbewahrt (zur Missbrauchsuntersuchung), bevor er endgültig entfernt wird. Der Metadatensatz enthält weder den Verschlüsselungsschlüssel, noch die Passphrase, noch irgendeine Information, mit der die Datei rekonstruiert werden könnte.

1.8 Bedrohungsmodell und Gegenmaßnahmen

BedrohungAngriffsvektorGegenmaßnahme
Serverkompromittierung Der Angreifer erlangt vollständigen Zugriff auf Datenbank und Speicher Alle gespeicherten Daten sind AES-256-GCM-Chiffrat. Der Angreifer erhält lediglich opake Blobs. Ohne Passphrase ist ein Brute-Force gegen 256-Bit-AES rechnerisch undurchführbar.
Netzwerk-Abhörung (MITM) Der Angreifer fängt Daten während der Übertragung ab Der gesamte Verkehr nutzt TLS 1.3. Selbst wenn TLS gebrochen wäre, erhielte der Angreifer nur verschlüsselte Blobs (analog zur Serverkompromittierung).
Schwache Passphrase Der Angreifer knackt eine kurze oder häufige Passphrase per Brute-Force PBKDF2 mit 600.000 Iterationen verteuert jeden Versuch erheblich. Selbst eine vierstellige Passphrase erfordert nennenswerte Rechenleistung. Die Benutzeroberfläche erzwingt eine Mindestlänge und gibt Rückmeldung zur Passphrasenstärke.
Abfangen der Passphrase Der Angreifer fängt die zwischen Absender und Empfänger geteilte Passphrase ab Die Passphrase wird außerhalb unseres Systems geteilt. Wir empfehlen, sie über einen anderen Kanal als die Übertragungs-URL auszutauschen. Dies liegt in der Verantwortung des Nutzers.
Manipulation des clientseitigen Codes Der Angreifer verändert das an den Nutzer ausgelieferte JavaScript Alle Assets werden über HTTPS und das CDN von Vercel ausgeliefert. Subresource Integrity (SRI)-Hashes schützen vor Manipulationen auf CDN-Ebene. Nutzer können den Quellcode in den DevTools des Browsers überprüfen.
Speicherauslese Der Angreifer extrahiert den Verschlüsselungsschlüssel aus dem Browserspeicher Schlüssel der Web Crypto API werden, wo möglich, als nicht extrahierbar markiert. Abgeleitete Schlüssel existieren nur während der Ver-/Entschlüsselung im Speicher. Die Speicher-Isolation des Browsers bietet Schutz auf Betriebssystemebene.
Replay-Angriff Der Angreifer spielt einen abgefangenen verschlüsselten Blob erneut ab Jede Übertragung besitzt eine eindeutige ID und ist durch Downloadlimits sowie Ablaufzeiten geschützt. Burn-on-Read-Übertragungen werden nach dem ersten Zugriff gelöscht.

1.8.1 Annahmen

1.8.2 Außerhalb des Geltungsbereichs

1.9 Einschränkungen und ehrliche Offenlegung

Ehrliche Einschränkungen: Kein Sicherheitssystem ist perfekt. Wir stehen für die transparente Offenlegung bekannter Einschränkungen.


Datenschutzorientierte kryptografische Dokumentensignatur

PDF Pro Whitepaper WP-002 — Architektur und Sicherheitsanalyse

2.1 Kurzfassung

Dieses Whitepaper beschreibt die Architektur des Privacy-Signature-Systems von PDF Pro, eines kryptografischen Mechanismus zur Dokumentensignatur, bei dem das PDF-Dokument den Browser des Unterzeichners niemals verlässt. Das System verwendet ECDSA mit der Kurve P-256 und SHA-256-Hashing zur Erzeugung abgetrennter digitaler Signaturen. Nur der Dokumenten-Hash, die kryptografische Signatur und der öffentliche Schlüssel werden an den Server übermittelt. Private Schlüssel werden ausschließlich im Browser des Nutzers erzeugt, verschlüsselt und in IndexedDB gespeichert, geschützt durch PBKDF2-Schlüsselableitung (600.000 Iterationen) und AES-256-GCM-Verschlüsselung. Dieses Dokument beschreibt die vollständige Signier- und Verifizierungsarchitektur, das Schlüsselverwaltungsmodell, das Schema des signierten Payloads, die Gestaltung des Audit-Trails, das Bedrohungsmodell sowie die ehrlich dargelegten Einschränkungen.

2.2 Architekturübersicht

Das Privacy-Signature-System ist auf eine fundamentale Einschränkung hin konzipiert: Das PDF-Dokument darf niemals an den Server übermittelt werden. Dies wird architektonisch durch ein Modell abgetrennter Signaturen durchgesetzt.

Kerngarantie: Der Server sieht, empfängt oder verarbeitet das PDF-Dokument niemals. Die einzigen dokumentenbezogenen Daten, die der Server jemals erhält, sind ein SHA-256-Hash — ein fester 256-Bit-Wert, aus dem das Originaldokument nicht rekonstruiert werden kann.

2.3 Signieralgorithmus: ECDSA P-256 / SHA-256

2.3.1 Algorithmusparameter

ParameterWertBegründung
SignaturalgorithmusECDSA (Elliptic Curve Digital Signature Algorithm)NIST FIPS 186-4; kompakte Signaturen; hohe Sicherheit pro Schlüsselbit
KurveP-256 (secp256r1 / prime256v1)NIST-zugelassen; 128-Bit-Sicherheitsniveau; breite Unterstützung in der Web Crypto API
HashfunktionSHA-256NIST FIPS 180-4; 256-Bit-Digest; kollisionsresistent
Schlüssellänge256-Bit-Privatschlüssel, 512-Bit-Öffentlicher Schlüssel (unkomprimiert)Standard für P-256; äquivalent zu ~3072-Bit-RSA
Signaturgröße64 Byte (r: 32 Byte, s: 32 Byte)Kompakt; geeignet für Speicherung und Übertragung
SignaturformatIEEE P1363 (roh r || s)Native Ausgabe der Web Crypto API; base64url-kodiert zur Speicherung

Signaturkodierung: ECDSA mit P-256 in der Web Crypto API erzeugt eine rohe 64-Byte-Signatur, bestehend aus zwei 32-Byte-Ganzzahlen (r || s) im Big-Endian-Festbreitenformat. Diese Rohausgabe wird zur Speicherung base64url-kodiert. Sie ist NICHT DER-kodiert — es handelt sich um das IEEE P1363-Format, das die Web Crypto API nativ produziert.

2.3.2 Signierablauf

// 1. PDF-Dokument hashen (clientseitig)
const fileBuffer = await file.arrayBuffer();
const hashBuffer = await crypto.subtle.digest("SHA-256", fileBuffer);
const hashHex = Array.from(new Uint8Array(hashBuffer))
  .map(b => b.toString(16).padStart(2, '0')).join('');

// 2. Hash mit privatem Schlüssel signieren (clientseitig)
const signature = await crypto.subtle.sign(
  { name: "ECDSA", hash: "SHA-256" },
  privateKey,   // CryptoKey aus IndexedDB (entschlüsselt)
  hashBuffer
);

// 3. An den Server senden: Hash + Signatur + öffentlicher Schlüssel (NICHT das PDF)
await submitSignature({
  documentHash: hashHex,
  signature: base64Encode(signature),
  publicKey: exportedPublicKeyJWK
});

2.4 Schlüsselverwaltung: flüchtig vs. persistent

SchlüsseltypKontextLebenszyklusSpeicherung
Flüchtig Gastnutzer (nicht angemeldet) Je Sitzung erzeugt; beim Schließen des Tabs vernichtet Nur im Speicher (CryptoKey-Objekt); niemals persistiert
Persistent Authentifizierte Nutzer (angemeldet) Einmal erzeugt; sitzungsübergreifend persistiert; widerrufbar IndexedDB (verschlüsselt mit PBKDF2 + AES-256-GCM)

2.4.1 Schlüsselerzeugung

// ECDSA-P-256-Schlüsselpaar erzeugen (Web Crypto API)
const keyPair = await crypto.subtle.generateKey(
  {
    name: "ECDSA",
    namedCurve: "P-256"
  },
  true,   // extrahierbar (für Verschlüsselung + Speicherung erforderlich)
  ["sign", "verify"]
);

// Öffentlichen Schlüssel als JWK für die Server-Registrierung exportieren
const publicKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.publicKey);

// Privaten Schlüssel als JWK zur verschlüsselten Speicherung exportieren
const privateKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.privateKey);

Format des öffentlichen Schlüssels: Öffentliche Schlüssel werden im JWK-Format (JSON Web Key) exportiert und gespeichert. Der Schlüssel-Fingerprint wird als SHA-256 über das kanonische JWK berechnet, das ausschließlich die öffentlichen Felder {crv, kty, x, y} in alphabetisch sortierter Reihenfolge enthält.

2.5 Schutz des privaten Schlüssels: PBKDF2 + AES-GCM → IndexedDB

Persistente private Schlüssel werden niemals im Klartext gespeichert. Bevor der private Schlüssel (als JWK-JSON exportiert) in IndexedDB geschrieben wird, wird er nach demselben Muster wie bei Secure Transfer verschlüsselt:

2.5.1 Schutzparameter

ParameterWert
SchlüsselableitungPBKDF2-SHA256, 600.000 Iterationen
SaltZufällige 16 Byte (pro Schlüssel)
VerschlüsselungAES-256-GCM
IVZufällige 12 Byte (pro Verschlüsselung)
EingabePrivater Schlüssel als JWK (JSON-String, UTF-8-kodiert)
In IndexedDB gespeicherte Ausgabe{ salt, iv, ciphertext, publicKeyJWK, keyId, createdAt }

2.5.2 Speicher-Schema

// Datensatzstruktur in IndexedDB für einen verschlüsselten Signierschlüssel
{
  "keyId":       "uuid-v4-unique-identifier",
  "publicKey":   { /* JWK-Format, unverschlüsselt */ },
  "encryptedPrivateKey": {
    "salt":       "base64-encoded-16-bytes",
    "iv":         "base64-encoded-12-bytes",
    "ciphertext": "base64-encoded-aes-gcm-ciphertext"
  },
  "algorithm":   "ECDSA",
  "curve":       "P-256",
  "createdAt":   "2026-04-16T00:00:00.000Z",
  "userId":      "supabase-auth-user-id"
}

Schlüsselwiederherstellung: Vergisst der Nutzer seine Signier-Passphrase, kann der private Schlüssel nicht wiederhergestellt werden. Wir verfügen weder über die Passphrase, noch über den abgeleiteten Schlüssel, noch über einen Mechanismus, den PBKDF2 + AES-GCM-Schutz zu umgehen. Nutzer sollten Schlüssel-Backups exportieren.

2.6 Modell der abgetrennten Signatur

PDF Pro verwendet ein Modell abgetrennter Signaturen, d. h. die Signatur wird getrennt vom Dokument gespeichert. Dies ist der entscheidende Datenschutzmechanismus: Das Dokument verlässt niemals das Gerät des Unterzeichners.

2.6.1 Was an den Server gesendet wird

2.6.2 Was NICHT an den Server gesendet wird

Kryptografische Zusicherung: SHA-256 ist eine Einweg-Hashfunktion. Allein anhand des Hashs e3b0c44298fc1c14... liefert sie unter den Sicherheitsannahmen von ECDSA und SHA-256 eine starke kryptografische Zusicherung, dass das Originaldokument nicht rekonstruiert werden kann. Der Hash offenbart nichts über Inhalt, Länge oder Struktur des Dokuments, abgesehen davon, dass er die Identität beim erneuten Hashen bestätigt.

2.7 Schema des signierten Payloads v1.0

Das folgende JSON-Schema definiert den vollständigen Signatur-Datensatz, der auf dem Server gespeichert wird:

{
  "schemaVersion":  "1.0",
  "signatureId":    "uuid-v4",
  "documentHash":   "sha256-hex-64-chars",
  "hashAlgorithm":  "SHA-256",
  "signature":      "base64-encoded-ecdsa-signature",
  "signatureAlgorithm": "ECDSA",
  "curve":          "P-256",
  "publicKey": {
    "kty": "EC",
    "crv": "P-256",
    "x":   "base64url-encoded-x-coordinate",
    "y":   "base64url-encoded-y-coordinate"
  },
  "signer": {
    "identityLevel": "authenticated | self-asserted",
    "displayName":   "string or null",
    "email":         "string or null",
    "userId":        "supabase-uid or null"
  },
  "timestamp":      "ISO-8601-UTC",
  "metadata": {
    "fileName":     "original-file-name.pdf",
    "fileSize":     123456,
    "pageCount":    12,
    "clientVersion": "2.0.0",
    "userAgent":    "browser-user-agent-string"
  },
  "auditChain": {
    "previousEventHash": "sha256-of-previous-audit-event or null",
    "eventHash":         "sha256-of-this-record"
  }
}

2.8 Verifikationsablauf

Die Signaturverifikation ist ein zweiphasiger Prozess: clientseitige kryptografische Verifikation, gefolgt von einer serverseitigen Gegenprüfung.

2.8.1 Phase 1: clientseitige kryptografische Verifikation

  1. Der Nutzer lädt ein PDF in den Browser.
  2. Der Browser berechnet den SHA-256-Hash des geladenen PDFs.
  3. Der Browser fragt den Server nach Signatur-Datensätzen, die diesem Hash entsprechen.
  4. Für jeden zurückgegebenen Signatur-Datensatz führt der Browser eine ECDSA-Verifikation durch:
    const isValid = await crypto.subtle.verify(
      { name: "ECDSA", hash: "SHA-256" },
      importedPublicKey,
      signatureBuffer,
      hashBuffer
    );
  5. Ist isValid === true, so ist die Signatur kryptografisch gültig: Das Dokument wurde seit dem Signieren nicht verändert, und die Signatur wurde vom Inhaber des zugehörigen privaten Schlüssels erzeugt.

2.8.2 Phase 2: serverseitige Gegenprüfung

  1. Der Server bestätigt, dass der öffentliche Schlüssel im Signatur-Datensatz einem bekannten Nutzer zugeordnet ist (bei authentifizierten Signaturen).
  2. Der Server bestätigt, dass der Signatur-Datensatz nicht widerrufen wurde.
  3. Der Server bestätigt die Integrität des Audit-Trails (Hash-Ketten-Validierung).
  4. Der Server gibt die Identitätsstufe und den Registrierungsstatus des Unterzeichners zurück.

2.8.3 Verifikationsergebnisse

ErgebnisBedeutung
Gültig (authentifiziert)Die Signatur ist kryptografisch gültig UND der öffentliche Schlüssel gehört zu einem registrierten, authentifizierten PDF-Pro-Nutzer.
Gültig (selbst erklärt)Die Signatur ist kryptografisch gültig, die Identität des Unterzeichners jedoch selbst erklärt (Gastnutzer oder nicht verifizierter Name).
UngültigDie kryptografische Verifikation ist fehlgeschlagen. Das Dokument wurde seit dem Signieren verändert, oder die Signatur ist beschädigt.
WiderrufenDie Signatur war gültig, wurde jedoch vom Unterzeichner ausdrücklich widerrufen.
Keine Signatur gefundenFür diesen Dokumenten-Hash existiert kein Signatur-Datensatz.

2.9 Audit-Trail: hash-verkettete Ereignisse

Jedes Signier- und Verifikationsereignis wird in einem manipulationsevidenten Audit-Trail festgehalten. Die Ereignisse sind hash-verkettet: Jedes Ereignis enthält den SHA-256-Hash des vorherigen Ereignisses und bildet so eine ausschließlich anzufügende Kette, ähnlich einer Blockchain.

2.9.1 Audit-Ereignistypen

EreignistypAuslöserErfasste Daten
KEY_REGISTEREDNutzer registriert einen neuen öffentlichen SchlüsselÖffentlicher Schlüssel als JWK, Nutzer-ID, Zeitstempel
DOCUMENT_SIGNEDNutzer signiert ein DokumentDokumenten-Hash, Signatur, öffentlicher Schlüssel, Identität des Unterzeichners, Zeitstempel
SIGNATURE_VERIFIEDEin Nutzer verifiziert eine SignaturDokumenten-Hash, Verifikationsergebnis, Informationen zum Prüfer (bei Authentifizierung), Zeitstempel
SIGNATURE_REVOKEDUnterzeichner widerruft eine SignaturSignatur-ID, Widerrufsgrund, Zeitstempel
KEY_REVOKEDNutzer widerruft einen öffentlichen SchlüsselID des öffentlichen Schlüssels, Widerrufsgrund, Zeitstempel

2.9.2 Struktur der Hash-Kette

// Jedes Audit-Ereignis enthält:
{
  "eventId":            "uuid-v4",
  "eventType":          "DOCUMENT_SIGNED",
  "timestamp":          "ISO-8601-UTC",
  "data":               { /* ereignisspezifischer Payload */ },
  "previousEventHash": "sha256-of-previous-event-json",
  "eventHash":          "sha256-of-this-event-json-without-eventHash"
}

// Manipulationsdetektion: zur Prüfung der Kette berechnen:
// SHA-256(JSON.stringify(Ereignis ohne eventHash-Feld))
// und bestätigen, dass dies mit eventHash übereinstimmt.
// Anschließend bestätigen, dass previousEventHash dem eventHash des vorherigen Ereignisses entspricht.

Wird irgendein Ereignis in der Kette verändert, brechen alle nachfolgenden Hash-Verknüpfungen, wodurch Manipulationen sofort erkennbar werden. Dies liefert eine starke Garantie für die Integrität des Audit-Trails.

Wichtige Einschränkung: Die Hash-Kette macht Manipulationen innerhalb der aufgezeichneten Ereignisfolge erkennbar. Ein Datenbankadministrator mit direktem Zugriff könnte die Kette theoretisch jedoch löschen und rekonstruieren. Stärkere Garantien würden externe Zeitstempelung oder Drittparteien-Attestierung erfordern, was in dieser Version nicht implementiert ist.

2.10 Identitätsstufen

StufeAnforderungenVertrauenseigenschaftenAnwendungsfall
Authentifiziert Angemeldeter PDF-Pro-Nutzer mit verifizierter E-Mail; persistentes Schlüsselpaar ist dem Konto zugeordnet E-Mail durch Supabase Auth verifiziert; öffentlicher Schlüssel an authentifiziertes Konto gebunden; Audit-Trail mit Nutzer-ID verknüpft Geschäftsdokumente, Verträge, formelle Vereinbarungen
Selbst erklärt Gastnutzer oder authentifizierter Nutzer mit selbst eingegebenem Namen; flüchtiges oder persistentes Schlüsselpaar Kryptografische Integrität gewährleistet; Identität des Unterzeichners ist selbst erklärt und nicht unabhängig verifiziert Schnelles Signieren, persönliche Dokumente, informelle Vereinbarungen

Hinweis: In der Produkt-Benutzeroberfläche kann „self_asserted" als „Selbst erklärte Identität" oder „Gastsignatur" angezeigt werden. „authenticated" kann als „Authentifiziertes Konto" angezeigt werden. Dies sind Anzeigebezeichnungen für dieselben zugrunde liegenden Identitätsstufen.

Identitätsbindung: Eine „authentifizierte" Signatur bedeutet, dass der öffentliche Schlüssel einem PDF-Pro-Konto mit verifizierter E-Mail zugeordnet ist. Sie bedeutet NICHT, dass die reale Identität des Unterzeichners durch staatlichen Ausweis, biometrische Merkmale oder persönliche Verifikation bestätigt wurde. Wir führen keine Know-Your-Customer-Prüfungen (KYC) durch.

2.11 Bedrohungsmodell

BedrohungAngriffsvektorGegenmaßnahme
Replay-Angriff Der Angreifer kopiert eine gültige Signatur und wendet sie auf ein anderes Dokument an Die Signatur ist an den SHA-256-Hash des konkreten Dokuments gebunden. Ein anderes Dokument besitzt einen anderen Hash, und die ECDSA-Verifikation schlägt fehl.
Fälschung Der Angreifer erzeugt eine gültige Signatur ohne den privaten Schlüssel Die Sicherheit von ECDSA P-256 basiert auf dem Elliptic-Curve-Discrete-Logarithm-Problem (ECDLP). Eine Signaturfälschung ohne privaten Schlüssel ist rechnerisch undurchführbar (128-Bit-Sicherheitsniveau).
Schlüsselsubstitution Der Angreifer registriert seinen eigenen öffentlichen Schlüssel und behauptet, eine Signatur sei von jemand anderem erzeugt worden Authentifizierte Signaturen binden den öffentlichen Schlüssel an eine verifizierte E-Mail. Der Audit-Trail erfasst, welcher Schlüssel welches Dokument signiert hat. Ereignisse der Schlüsselregistrierung sind hash-verkettet.
Dokumenten-Austausch Der Angreifer verändert ein signiertes PDF und behauptet, die Signatur sei weiterhin gültig Jede Änderung am PDF ändert dessen SHA-256-Hash. Die bestehende Signatur schlägt bei der Verifikation gegen den neuen Hash fehl. Das Auffinden einer Kollision (unterschiedliches Dokument mit gleichem Hash) erfordert ca. 2^128 Operationen.
Diebstahl des privaten Schlüssels Der Angreifer extrahiert den verschlüsselten privaten Schlüssel aus IndexedDB Der private Schlüssel ist mit AES-256-GCM verschlüsselt, der Schlüssel wurde mittels PBKDF2 (600.000 Iterationen) abgeleitet. Ohne die Passphrase ist eine Entschlüsselung rechnerisch undurchführbar.
Serverkompromittierung Der Angreifer erlangt vollständigen Serverzugriff Der Server verfügt nur über öffentliche Schlüssel und Signatur-Datensätze. Private Schlüssel erreichen den Server nie. Ein Angreifer kann keine neuen Signaturen fälschen. Er könnte bestehende Einträge löschen oder verändern, doch Brüche der Hash-Kette wären erkennbar.
Manipulation des Audit-Trails Der Angreifer verändert Audit-Trail-Ereignisse auf dem Server Hash-verkettete Ereignisse: Eine Änderung an einem Ereignis bricht die Kette ab diesem Punkt. Unabhängige Verifikationswerkzeuge können Kettenbrüche erkennen.

2.11.1 Annahmen

2.11.2 Außerhalb des Geltungsbereichs

2.12 Ehrliche Offenlegung

Was PDF-Pro-Signaturen NICHT sind:

2.12.1 Wofür PDF-Pro-Signaturen GEEIGNET sind

Unsere Verpflichtung: Wir bauen Sicherheit durch Architektur, nicht durch Marketing. Diese Whitepapers beschreiben genau, wie unsere Systeme funktionieren, einschließlich ihrer Einschränkungen. Wir glauben, dass sicherheitsbewusste Nutzer vollständige technische Transparenz verdienen. Wenn Sie Fragen zu irgendeinem Aspekt unserer Architektur haben, kontaktieren Sie uns unter info@webdesign9.com.