01 · Problem
Wofür braucht man das?
Empfänger müssen Integrität und Herkunft einer Nachricht prüfen können, ohne Zugriff auf den privaten Schlüssel zu besitzen.
02 · Denkmodell
Das mentale Modell
Header plus Payload werden kanonisch serialisiert und mit Private Key signiert; Key-ID wählt beim Prüfen den passenden Public Key.
Signiert JSON-Umschläge mit RSA-SHA256 und verschlüsselt Schlüsselexporte per AES-GCM. Schlüssel gehören lokal zum Signer. Produktiver Vertrauensaufbau, kanonische Serialisierung und Rotation benötigen ein Anwendungsdesign.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Keypair über eine explizite async Factory erzeugen oder laden.
- Versionierten Header und Payload kanonisch in Bytes wandeln.
- Bytes mit dem privaten Signaturschlüssel signieren.
- Key-ID auflösen, Timestamp-Policy prüfen und dieselben Bytes verifizieren.
- Private Keys versioniert und authentifiziert verschlüsselt persistieren.
04 · Bauteile
Die entscheidenden Verträge
Signature.signData / verifySignatureErzeugt und prüft einen JSON-Signaturumschlag.KeyPairEncryptionVerschlüsselt exportierte private Schlüssel per scrypt und AES-256-GCM.PayloadSignerSigniert und prüft exakte serialisierte Bytes.05 · Selbst bauen
Selbst implementieren
Beginne mit einer awaitbaren Factory und einem festen Signaturalgorithmus; Persistenz ist ein separater Schritt.
- Keypair vollständig erzeugen, bevor eine Signer-Instanz zurückgegeben wird.
- Header und Payload in ein kanonisches, versioniertes Byteformat bringen.
- Private-Key-Export mit eigener KDF-Salt und AES-GCM-IV als Base64url speichern.
async function sign(payload: unknown, privateKey: CryptoKey) {
const bytes = new TextEncoder().encode(canonicalJson(payload));
const signature = await crypto.subtle.sign(
{ name: "RSA-PSS", saltLength: 32 },
privateKey,
bytes,
);
return new Uint8Array(signature);
}
async function verify(payload: unknown, value: BufferSource, publicKey: CryptoKey) {
const bytes = new TextEncoder().encode(canonicalJson(payload));
return crypto.subtle.verify({ name: "RSA-PSS", saltLength: 32 }, publicKey, value, bytes);
}06 · Verifizieren
Was solltest du testen?
- Originalpayload verifiziert; veränderter Header, Payload oder Signatur verifiziert nicht.
- Signieren ist vor abgeschlossener Keyinitialisierung durch die API unmöglich.
- Export/Encrypt/Serialize/Parse/Decrypt/Import bildet den privaten Key verlustfrei ab und erkennt Manipulation.
Selbst ausprobieren
Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.
Originalpayload verifiziert; veränderter Header, Payload oder Signatur verifiziert nicht.
Ansatz vergleichen
Dein Test sollte beim gezielten Verletzen der Invariante fehlschlagen und nach der Korrektur wieder bestehen. Halte den Aufbau deterministisch und prüfe ein beobachtbares Ergebnis.
07 · Grenzen
Kompromisse und Stolperfallen
- RSA-PSS ist breit verfügbar, aber Key und Signatur sind groß.
- Kanonische Serialisierung ist zusätzlicher Aufwand und unverzichtbar für reproduzierbare Bytes.
- Keyrotation begrenzt Schäden, erfordert aber Historie, Ablauf und Revocation.
Schlüssel gehören lokal zum Signer. Produktiver Vertrauensaufbau, kanonische Serialisierung und Rotation benötigen ein Anwendungsdesign.
08 · Weiterdenken
Quellcode und verwandte Ideen
yarn tsx packages/signature/examples/basic.ts