fix(cert-manager): Reiter zeigen nur noch passende Auswertungen, Aufteilen schützt Schlüssel

- Ausgabe-Reiter bieten nur an, was zur aktuellen Dateiliste passt: nach dem Entfernen
  einer Datei oder einer fehlgeschlagenen Prüfung kommt Hinweis oder Fehler mit
  „Erneut versuchen“ statt der alten Auswertung (WR-02)
- Aufteilen: ein in der Datei geschützter Schlüssel bleibt geschützt (Passwort für die
  Ausgabe, auch in der ZIP); ohne Schutz nur ausdrücklich und mit sichtbarem Hinweis;
  Schlüssel heißen nach ihrem Zertifikat (WR-03, IN-05)
- Meldungen: tooManyItems, aiaNotAllowed, buildFailed (statt „Dateien konnten nicht
  geprüft werden“ beim Erstellen), protectionTooExpensive; Hinweis zum Passwort
  genauer (IN-03, IN-05)
- Download-Adresse wird erst nach einer Sekunde widerrufen (IN-04)
- Anleitungen und Änderungsliste: Grenzen, Aufteilen mit Schlüsselschutz, Umlaut-Passwörter

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-09 17:10:45 +02:00
parent ff2226dfbd
commit 4b87249a4a
23 changed files with 758 additions and 113 deletions
+4 -4
View File
@@ -153,10 +153,10 @@ Der Zertifikat-Manager hilft Ihnen, Zertifikate, Schlüssel und Zertifikatsanfra
**Wichtig zu Schlüsseln und Passwörtern:** Die Liste lebt nur im Arbeitsspeicher Ihres Browserfensters. Private Schlüssel und Passwörter werden von Tessera nirgends gespeichert und in keinem Protokoll festgehalten. Laden Sie die Seite neu oder schließen Sie das Fenster, ist die Liste weg, und Sie laden Ihre Dateien bei Bedarf noch einmal hoch.
- **Dateien** — Hier sammeln Sie alles. Ziehen Sie Dateien in das Feld oder klicken Sie hinein und wählen Sie Dateien aus, so oft und in beliebiger Menge nacheinander; **jede neue Datei kommt zur Liste hinzu und ersetzt nie eine frühere**. Sie können auch die ZIP-Datei Ihres Zertifikatsausstellers hochladen: Tessera schaut hinein und nennt zu jedem enthaltenen Eintrag, was es darin gefunden hat. Überflüssiges wie Ordner mit dem Namen `__MACOSX` überspringt Tessera still; verschachtelte oder passwortgeschützte ZIP-Dateien nennt es mit dem Grund, warum es sie nicht öffnet. Zusätzlich können Sie PEM-Text einfügen („PEM-Text einfügen“, Text beginnt mit `-----BEGIN`); er erscheint als eigener Eintrag. Die Liste fasst bis zu 30 Einträge, höchstens 5 MB je Datei und zusammen höchstens 10 MB; dieselbe Datei kann nicht zweimal hinzugefügt werden. Zu jedem Eintrag zeigt die Liste, was erkannt wurde: Serverzertifikat, Zwischenzertifikat, Stammzertifikat, privater Schlüssel oder Zertifikatsanfrage. Mit dem Knopf am Eintrag nehmen Sie eine einzelne Datei wieder aus der Liste. Ist eine Datei durch ein Passwort geschützt (PFX-/P12-Datei oder verschlüsselter Schlüssel), erscheint beim Eintrag ein Feld für das Passwort; es gilt nur für diese eine Datei. Hat Tessera zum Serverzertifikat schon einen Schlüssel, erscheint eine passwortgeschützte PFX-Datei nur als ruhiger Hinweis, den Sie nicht beachten müssen.
- **Dateien** — Hier sammeln Sie alles. Ziehen Sie Dateien in das Feld oder klicken Sie hinein und wählen Sie Dateien aus, so oft und in beliebiger Menge nacheinander; **jede neue Datei kommt zur Liste hinzu und ersetzt nie eine frühere**. Sie können auch die ZIP-Datei Ihres Zertifikatsausstellers hochladen: Tessera schaut hinein und nennt zu jedem enthaltenen Eintrag, was es darin gefunden hat. Überflüssiges wie Ordner mit dem Namen `__MACOSX` überspringt Tessera still; verschachtelte oder passwortgeschützte ZIP-Dateien nennt es mit dem Grund, warum es sie nicht öffnet. Zusätzlich können Sie PEM-Text einfügen („PEM-Text einfügen“, Text beginnt mit `-----BEGIN`); er erscheint als eigener Eintrag. Die Liste fasst bis zu 30 Einträge, höchstens 5 MB je Datei und zusammen höchstens 10 MB; dieselbe Datei kann nicht zweimal hinzugefügt werden. Auf einmal prüft Tessera höchstens 200 Zertifikate, 50 Schlüssel und 50 Zertifikatsanfragen; steckt mehr in Ihren Dateien, erscheint ein Hinweis, und Sie nehmen einzelne Dateien aus der Liste. Zu jedem Eintrag zeigt die Liste, was erkannt wurde: Serverzertifikat, Zwischenzertifikat, Stammzertifikat, privater Schlüssel oder Zertifikatsanfrage. Mit dem Knopf am Eintrag nehmen Sie eine einzelne Datei wieder aus der Liste. Ist eine Datei durch ein Passwort geschützt (PFX-/P12-Datei oder verschlüsselter Schlüssel), erscheint beim Eintrag ein Feld für das Passwort; es gilt nur für diese eine Datei und darf Umlaute und Sonderzeichen enthalten. Ein Passwortschutz, den zu prüfen übermäßig aufwendig wäre (mehr als eine Million Rechenschritte, wie sie nur eine absichtlich präparierte Datei verlangt), wird mit einem Hinweis beim Eintrag übersprungen. Hat Tessera zum Serverzertifikat schon einen Schlüssel, erscheint eine passwortgeschützte PFX-Datei nur als ruhiger Hinweis, den Sie nicht beachten müssen.
- **Analysieren** — Zeigt zu jedem erkannten Teil die Einzelheiten: Name, Aussteller, Gültigkeit (mit den verbleibenden Tagen), Schlüsselart (RSA oder EC mit Kurve), die Namen, für die das Zertifikat gilt, sowie Seriennummer und Fingerabdrücke. Außerdem sehen Sie, was zusammengehört: welcher Schlüssel zu welchem Zertifikat passt und welche Zertifikatsanfrage zu welchem Zertifikat gehört. Tessera ordnet nie nach dem Namen zu, sondern prüft den Schlüssel selbst.
- **Aufteilen** — Zerlegt Ihre Dateien in die einzelnen Teile. Jedes Teil laden Sie in seinem natürlichen Format herunter (Zertifikat als `.crt`, Schlüssel als `.key`, Anfrage als `.csr`) oder alle zusammen als ZIP-Datei.
- **Zusammenführen** — Tessera ordnet Serverzertifikat, Zwischenzertifikate und Stammzertifikat **selbst**; die Reihenfolge Ihrer Dateien spielt keine Rolle. Dabei prüft es nicht nur Namen, sondern die echte Unterschrift jedes Zertifikats, sodass ein gleichnamiges, aber falsches Zwischenzertifikat nie verwendet wird. Gibt es mehrere Möglichkeiten, wählt Tessera nachvollziehbar die beste (zum Beispiel nicht abgelaufen). Sie können herunterladen: **Fullchain** (Serverzertifikat plus Zwischenzertifikate), **Nur Kette** (nur die Zwischenzertifikate, zum Beispiel für Systeme, die das Serverzertifikat getrennt wollen), **Zertifikat und Schlüssel** in einer PEM-Datei sowie eine **PFX-Datei**. Fullchain und Nur Kette gibt es als PEM, als `.p7b` oder als binäre `.p7c`. Für die PFX-Datei vergeben Sie ein Passwort (zweimal eingeben) und wählen die Verschlüsselung: **„Kompatibel (auch ältere Windows-Server)“** ist vorgewählt und die sichere Wahl, wenn Sie nicht wissen, wo die Datei eingespielt wird; **„Modern (AES-256)“** ist stärker, wird aber von älteren Systemen wie Windows Server 2016 oft nicht gelesen. Das Häkchen **„Root-Zertifikat mitnehmen“** ist standardmäßig aus, denn die meisten Server und Browser kennen die Wurzel schon und brauchen sie nicht; setzen Sie es nur, wenn ein Gerät es ausdrücklich verlangt (manche Geräte, Java-Anwendungen oder eigene Firmenwurzeln). Fehlt ein Aussteller in Ihrer Liste, sagt Tessera das ausdrücklich: **„Zwischenzertifikat fehlt“** heißt, dass direkt über dem Serverzertifikat das Zwischenzertifikat nicht in der Liste ist; fehlt dagegen nur das Zertifikat ganz oben (meist die Wurzel), erscheint ein ruhiger Hinweis, denn das ist für die meisten Server in Ordnung. Das fehlende Zertifikat können Sie selbst im Reiter „Dateien“ hinzufügen oder, wie unten beschrieben, von Tessera holen lassen.
- **Aufteilen** — Zerlegt Ihre Dateien in die einzelnen Teile. Jedes Teil laden Sie in seinem natürlichen Format herunter (Zertifikat als `.crt`, Schlüssel als `.key`, Anfrage als `.csr`) oder alle zusammen als ZIP-Datei. **Private Schlüssel bleiben geschützt:** War ein Schlüssel in Ihrer Datei durch ein Passwort geschützt, ist oben im Reiter „Schlüssel mit einem Passwort schützen“ schon angekreuzt; Sie geben ein Passwort ein (es darf ein anderes als das alte sein), und die heruntergeladenen Schlüsseldateien sind damit verschlüsselt, auch in der ZIP-Datei. Solange das Passwort fehlt, sind die Knöpfe für die Schlüssel und für die ZIP-Datei gesperrt; die Zertifikate laden Sie trotzdem herunter. Möchten Sie die Schlüssel bewusst ohne Schutz speichern, nehmen Sie das Häkchen heraus; Tessera weist dann ausdrücklich darauf hin, dass die Schlüsseldateien unverschlüsselt sind. Jeder Schlüssel trägt den Namen seines Zertifikats (`name.key`), gibt es keines, wird nummeriert.
- **Zusammenführen** — Tessera ordnet Serverzertifikat, Zwischenzertifikate und Stammzertifikat **selbst**; die Reihenfolge Ihrer Dateien spielt keine Rolle. Dabei prüft es nicht nur Namen, sondern die echte Unterschrift jedes Zertifikats, sodass ein gleichnamiges, aber falsches Zwischenzertifikat nie verwendet wird. Gibt es mehrere Möglichkeiten, wählt Tessera nachvollziehbar die beste (zum Beispiel nicht abgelaufen). Sie können herunterladen: **Fullchain** (Serverzertifikat plus Zwischenzertifikate), **Nur Kette** (nur die Zwischenzertifikate, zum Beispiel für Systeme, die das Serverzertifikat getrennt wollen), **Zertifikat und Schlüssel** in einer PEM-Datei sowie eine **PFX-Datei**. Fullchain und Nur Kette gibt es als PEM, als `.p7b` oder als binäre `.p7c`. Für die PFX-Datei vergeben Sie ein Passwort (zweimal eingeben; Umlaute und Sonderzeichen sind erlaubt, die Datei lässt sich damit auch mit Windows, OpenSSL und Java öffnen) und wählen die Verschlüsselung: **„Kompatibel (auch ältere Windows-Server)“** ist vorgewählt und die sichere Wahl, wenn Sie nicht wissen, wo die Datei eingespielt wird; **„Modern (AES-256)“** ist stärker, wird aber von älteren Systemen wie Windows Server 2016 oft nicht gelesen. Das Häkchen **„Root-Zertifikat mitnehmen“** ist standardmäßig aus, denn die meisten Server und Browser kennen die Wurzel schon und brauchen sie nicht; setzen Sie es nur, wenn ein Gerät es ausdrücklich verlangt (manche Geräte, Java-Anwendungen oder eigene Firmenwurzeln). Fehlt ein Aussteller in Ihrer Liste, sagt Tessera das ausdrücklich: **„Zwischenzertifikat fehlt“** heißt, dass direkt über dem Serverzertifikat das Zwischenzertifikat nicht in der Liste ist; fehlt dagegen nur das Zertifikat ganz oben (meist die Wurzel), erscheint ein ruhiger Hinweis, denn das ist für die meisten Server in Ordnung. Das fehlende Zertifikat können Sie selbst im Reiter „Dateien“ hinzufügen oder, wie unten beschrieben, von Tessera holen lassen.
- **Konvertieren** — Wandelt ein einzelnes Teil in ein anderes Format um: Zertifikate als PEM, DER, PKCS#7 (`.p7b`, `.p7c`); Schlüssel als PKCS#8, klassisch (PKCS#1 bei RSA, SEC1 bei EC) oder DER, auf Wunsch mit eigenem Passwort verschlüsselt; Zertifikatsanfragen als PEM oder DER.
- **Vorlagen** — Wählen Sie das System, auf dem Ihr Zertifikat laufen soll, und Tessera erzeugt mit einem Klick die passenden Dateien und zeigt die Zeilen für die Einrichtung (mit „Kopieren“). Mehrere Dateien kommen in einer ZIP-Datei, die zusätzlich eine kurze Anleitung enthält. Jede Vorlage braucht das Serverzertifikat **und** den dazu passenden privaten Schlüssel; fehlt der Schlüssel, erklärt Tessera das. Es gibt sieben Vorlagen: **Nginx** (`fullchain.pem` und `privkey.pem`); **Apache 2.4.8 und neuer** (ebenfalls `fullchain.pem` und `privkey.pem`); **Apache älter als 2.4.8** (getrennt `cert.pem`, `chain.pem` und `privkey.pem`); **Windows / IIS** (eine PFX-Datei mit dem Passwort, das Sie vergeben, vorgewählt ist „Kompatibel“); **Nginx Proxy Manager** (`certificate.pem`, `intermediate.pem` und `privkey.pem`; die Anleitung nennt, welche Datei in welches Feld unter „SSL Certificates“, „Add SSL Certificate“, „Custom“ gehört); **HAProxy** (eine einzige PEM-Datei mit Zertifikat, Zwischenzertifikaten und Schlüssel) und **Tomcat / Java** (eine `.p12`-Datei mit dem Passwort, das Sie vergeben, ebenfalls mit vorgewähltem „Kompatibel“). Das Passwort steht nie in den angezeigten Zeilen; dort steht stattdessen `IHR-PASSWORT`.
@@ -164,7 +164,7 @@ Der Zertifikat-Manager hilft Ihnen, Zertifikate, Schlüssel und Zertifikatsanfra
- **Nur auf Ihren Klick.** Tessera holt nie von sich aus etwas aus dem Internet, auch nicht beim Öffnen des Reiters oder wenn Sie Dateien hinzufügen oder entfernen. Der Hinweis über dem Knopf nennt den Server, bei dem Tessera nachfragt.
- **Nur eine geprüfte Antwort wird übernommen.** Tessera nimmt das heruntergeladene Zertifikat nur an, wenn es das betroffene Zertifikat wirklich ausgestellt hat (die Unterschrift wird geprüft). Alles andere verwirft Tessera; Sie sehen dann einen Hinweis, dass die Adresse kein passendes Zertifikat geliefert hat.
- **Nur öffentliche Adressen.** Adressen im eigenen Firmennetz oder auf dem Tessera-Server selbst ruft Tessera nie ab, ebenso keine Adressen mit besonderen Anschlussnummern oder Zugangsdaten. Dafür gibt es dann den Hinweis, dass die Adresse nicht abgerufen wird.
- **Nur öffentliche Adressen.** Adressen im eigenen Firmennetz oder auf dem Tessera-Server selbst ruft Tessera nie ab, ebenso keine Adressen mit besonderen Anschlussnummern, mit Zugangsdaten oder ohne http beziehungsweise https. Bei einer internen Adresse lautet der Hinweis, dass sie nicht auf einen öffentlichen Server verweist, bei den anderen, dass die Adresse nicht abgerufen werden darf. Den Knopf zeigt Tessera nur, wenn überhaupt eine abrufbare Adresse im Zertifikat steht.
- **Gekennzeichnet als „nachgeladen“.** Das geholte Zertifikat erscheint in der Liste im Reiter „Dateien“ als eigener Eintrag mit dem Vermerk „nachgeladen von“ und dem Namen des Servers, ebenso auf seiner Karte im Reiter „Analysieren“. Wie jeden anderen Eintrag können Sie ihn mit dem Knopf am Eintrag wieder entfernen.
- **Unter Umständen ein zweiter Klick.** Ein Klick holt genau eine Stufe. Fehlt über dem geholten Zwischenzertifikat noch ein weiteres (zum Beispiel das Stammzertifikat), erscheint an dieser Stelle der Knopf erneut, und Sie können noch einmal klicken. Das Stammzertifikat brauchen Sie für eine Fullchain meist nicht.
- **Wenn es nicht klappt.** Ist der Server des Ausstellers nicht erreichbar (zum Beispiel, weil der Tessera-Server selbst keinen Zugang zum Internet hat), meldet Tessera das. Laden Sie das Zertifikat dann beim Aussteller herunter und fügen Sie es im Reiter „Dateien“ hinzu. Steht im Zertifikat gar keine Adresse, gibt es keinen Knopf, sondern nur diesen Hinweis.
+1 -1
View File
@@ -202,7 +202,7 @@ Das Modul „Zertifikat-Manager“ braucht keine Einstellungen und keine eigene
- **Größe der Anfragen:** Die Dateien gehen über `/api-proxy` an die API. Eine einzelne Analyse schickt höchstens 10 MB (höchstens 30 Dateien, je Datei bis 5 MB). Die Voraussetzung am Proxy ist dieselbe wie im Abschnitt „Dateien (Nextcloud)“: `client_max_body_size` von mindestens `10m`. Beim Herunterladen eines Ergebnisses schickt der Browser nur Zertifikate und höchstens einen Schlüssel als JSON, höchstens 512 KiB je Anfrage (Tessera legt für genau diese Anfrage eine eigene Grenze fest, alle anderen JSON-Anfragen bleiben bei 100 kB).
- **Ausgehender Zugriff:** Der Zertifikat-Manager ruft von sich aus nichts im Internet ab. Eine Ausnahme gibt es: Klickt ein Benutzer auf „Fehlendes Zertifikat holen“, schickt der `api`-Container eine einzelne Anfrage an die Adresse, die im Zertifikat als Aussteller-Adresse steht (meist `http://`, selten `https://`). Dafür muss der `api`-Container ausgehend per HTTP und HTTPS (Ports 80 und 443) ins Internet kommen; andere Ports ruft Tessera nie ab. Ist das ausgehend gesperrt (Firewall, Proxy-Pflicht), meldet der Knopf „nicht erreichbar“, alles andere im Modul funktioniert weiter, und die Benutzer laden das Zertifikat selbst herunter. Tessera ruft dabei nur öffentliche Adressen ab (keine internen Rechner, keine Adressen des eigenen Netzes), prüft die Adresse im Moment des Verbindens noch einmal, folgt höchstens drei Weiterleitungen, begrenzt Wartezeit (8 Sekunden) und Antwortgröße (256 KiB) und übernimmt nur ein Zertifikat, das das betroffene Zertifikat wirklich ausgestellt hat. Im Protokoll steht bei einem Fehler genau eine Zeile mit dem Servernamen und einem Fehlercode, nie ein Zertifikat.
- **Rechenaufwand:** Passwortgeschützte PFX-Dateien und verschlüsselte Schlüssel öffnet Tessera mit den eingegebenen Passwörtern (je Datei höchstens zehn verschiedene Versuche); das kostet kurz Rechenzeit, belastet den Server aber nicht dauerhaft.
- **Rechenaufwand:** Passwortgeschützte PFX-Dateien und verschlüsselte Schlüssel öffnet Tessera mit den eingegebenen Passwörtern (je Datei höchstens zehn verschiedene Versuche); das kostet kurz Rechenzeit, belastet den Server aber nicht dauerhaft. Damit eine präparierte Datei die API nicht ausbremsen kann, gelten Grenzen je Anfrage: eine Passwortableitung höchstens eine Million Runden, alle zusammen höchstens sechs Millionen (mehr überspringt Tessera mit Hinweis), höchstens 200 Zertifikate, 50 Schlüssel und 50 Zertifikatsanfragen sowie 20 MiB für alle Dateien zusammen (Tessera bricht schon beim Empfang ab, mit der Meldung zu große Dateien, HTTP 413). ZIP-Dateien werden mit hartem Deckel entpackt (1 MiB je Eintrag, 20 MiB zusammen).
## 4. Neue Fassung einspielen
+34 -7
View File
@@ -909,22 +909,49 @@ deshalb für die Dauer **eines** synchronen Aufrufs drei Funktionen von `forge.p
(`privateKeyToAsn1`, `wrapRsaPrivateKey`, `certificateToAsn1`) gegen Durchreicher aus und stellt
sie im `finally` wieder her; ASN.1 für Zertifikate und Schlüssel kommt aus `node:crypto`, die
Verschlüsselung und den MAC macht weiterhin forge. Das ist sicher, weil Node einfädig ist und der
Aufruf nicht abgibt; das Spec prüft die Wiederherstellung auch nach einem Fehler. Profile:
Aufruf nicht abgibt; das Spec prüft die Wiederherstellung auch nach einem Fehler. **Passwörter:**
forge leitet den AES-Schlüssel (PBES2/PBKDF2) aus einem Byte je UTF-16-Einheit ab, OpenSSL 3, Windows
und Java nehmen die UTF-8-Bytes; mit Umlaut oder `€` wäre ein „modernes“ PFX sonst für jedes andere
Programm unlesbar (und umgekehrt, Review CR-03). Darum ersetzt `withForgeKdf` (Lesen **und**
Schreiben) zusätzlich `forge.pkcs5.pbkdf2` durch eine Ableitung mit `node:crypto` aus den UTF-8-Bytes
(auch SHA-256/512 nativ statt in reinem JavaScript). Die PKCS#12-eigene Ableitung (3DES, RC2, MAC)
bleibt, wie sie ist: sie nimmt BMPString (UTF-16) aus den Zeichen, genau wie OpenSSL. Dieselbe
Stelle zählt die Ableitungsrunden (siehe „Grenzen je Anfrage“). Profile:
`compat` (3DES, SHA-1, Vorgabe, lesbar bis Windows Server 2016) und `modern` (AES-256, der MAC bleibt
bei forge SHA-1). Die Vorlagen für IIS und Tomcat nutzen dieselbe Funktion (`cert-templates.ts`);
die Vorlagen für Dateien bauen aus denselben Bausteinen wie `buildOutput` und kennen `cert-output.ts`
bewusst nicht (sonst entstünde eine Importschleife).
*ZIP-Grenzen.* `zip-expand.ts` prüft **alles vor dem ersten Entpacken** an den Kopfdaten: höchstens
100 Einträge, 1 MiB je Eintrag, Verhältnis entpackt zu gepackt höchstens 100, Summe 20 MiB, nur eine
Ebene (ein ZIP im ZIP wird gemeldet, nicht geöffnet), verschlüsselte Einträge werden gemeldet.
Eintragsnamen dienen nur der Anzeige und werden nie als Dateipfad benutzt.
*ZIP-Grenzen.* `zip-expand.ts`: höchstens 100 Einträge, 1 MiB je Eintrag, Verhältnis entpackt zu
gepackt höchstens 100, Summe 20 MiB, nur eine Ebene (ein ZIP im ZIP wird gemeldet, nicht geöffnet),
verschlüsselte Einträge werden gemeldet. Die Kopfdaten (deklarierte Größe im Zentralverzeichnis)
sind nur Angreiferwunsch: adm-zip begrenzt die Ausgabe bei deklarierter Größe 0 gar nicht, ein
300-kB-ZIP entpackte dort zu 300 MiB (Review CR-01). Darum entpackt das Modul selbst
(`inflateRawSync` mit `maxOutputLength` = Einzelgrenze, höchstens die Restgrenze der Summe) und prüft
Größe, Verhältnis und CRC am echten Ergebnis; weicht die echte Größe von der deklarierten ab, gilt der
Eintrag als `suspicious`. Eintragsnamen dienen nur der Anzeige und werden nie als Dateipfad benutzt.
*Grenzen je Anfrage.* `cert-budget.ts` (`RequestBudget`, in `analyzeWorkingSet` einmal je Anfrage
angelegt und über `DetectContext.budget` durch alle Stufen gereicht): höchstens 200 Zertifikate, 50
Schlüssel, 50 Zertifikatsanfragen (413 `tooManyItems`; der Kettenbau ist quadratisch). Der Aufwand des
Passwortschutzes ist begrenzt (Review WR-04): eine Ableitung höchstens 1 000 000 Runden, alle zusammen
höchstens 6 000 000 je Anfrage; Runden werden vor dem Rechnen gemeldet (PKCS#12 über die drei
Ableitungsfunktionen von forge, verschlüsseltes PKCS#8 über `pkcs8Iterations` aus den Parametern),
zu teuer ergibt `protectionTooExpensive` für diese Datei. Der PEM-Scanner `pem-scan.ts` ist linear
(Review CR-02): die alte Regex `BEGIN … END` war bei vielen BEGIN-Zeilen ohne END quadratisch und
blockierte die API (5 MiB: Minuten); der Scanner sammelt die END-Stellen je Etikett in einem
Durchlauf und begrenzt die Blöcke auf 1000 je Text. Stellen, die Lesefehler bewusst verschlucken,
reichen die Anfragegrenzen mit `rethrowRequestError` weiter. Beim Empfang zählt
`cert-upload.ts` (eigener multer-Speicher) die Summe mit und bricht bei 20 MiB mit 413 `tooLarge` ab,
statt erst nach 30 vollständig gepufferten Dateien (Review WR-06). Die HTTP-Einrichtung
(`http-setup.ts`, aus `main.ts`) hängt den `build`-Leser **hinter** `enableCors` ein, damit auch
seine 413/400-Antworten CORS-Kopfzeilen tragen (Review WR-01; das Spec prüft die Reihenfolge).
*Grenze des Anfragekörpers von `build` (D-26).* Die Express-Voreinstellung von 100 kB reicht für die
größte erlaubte `build`-Anfrage nicht (Zertifikat, 20 Pool-Zertifikate, Schlüssel und Anfrage zu je
16 384 Zeichen ergeben rund 384 kB). Deshalb hat nur diese Route einen eigenen JSON-Leser mit
512 KiB (`cert-json-body.ts`), den `main.ts` per `app.use(CERT_BUILD_ROUTE, certBuildJsonBody,
certBuildBodyErrors)` **vor** `app.listen` einhängt (Nest registriert seine eigenen Leser erst in
512 KiB (`cert-json-body.ts`), den `configureHttp` in `http-setup.ts` per `app.use(CERT_BUILD_ROUTE,
certBuildJsonBody, certBuildBodyErrors)` nach `enableCors` und **vor** `app.listen` einhängt (Nest registriert seine eigenen Leser erst in
`init()`). Zwei Fallen: Erstens liegt `express` nicht in `apps/api/node_modules`, der Leser kommt
deshalb über `createRequire(...)` aus der Kopie, die auch `@nestjs/platform-express` lädt. Zweitens
**darf die Funktion nicht `jsonParser` heißen**: Nests `ExpressAdapter` überspringt seinen eigenen