CryptoKit ist das Framework, das Swift-Apps auf Apple-Plattformen für Hashing, Signaturen, Schlüsseleinigung, AEAD und HPKE verwenden. Es wird mit dem Betriebssystem ausgeliefert, seine Version ist also die des Betriebssystems; das SDK weist P-256 ab iOS 13 und macOS 10.15 als verfügbar aus, ML-KEM, ML-DSA und X-Wing ab iOS 26 und macOS 26. Die Fakten auf dieser Seite wurden unter macOS 27.0.1 mit Swift 6.4 auf einem Mac mit Apple Silicon geprüft, und beide Beispiele wurden dort kompiliert und ausgeführt; iOS wurde nicht geprüft. Unter Linux stellt swift-crypto dieselbe API bereit.
Eine P-256-Signatur ist ein Wert vom Typ ECDSASignature mit zwei Formen: rawRepresentation, das 64 Byte lange r‖s, das JWS (ES256) und WebCrypto verwenden, und derRepresentation, die DER-Form, die X.509, OpenSSL und Java erwarten. Die falsche Form zu senden ist ein häufiger Interoperabilitätsfehler; das Beispiel konvertiert explizit, und der Konverter DER ⇄ Raw zeigt beide. Das Parsen ist streng und wirft Fehler: Rohe Bytes in init(derRepresentation:) lösen einen CryptoKitASN1Error aus – truncatedASN1Field bei der Testsignatur aus RFC 6979, wobei der konkrete Fall von den Bytes abhängt –, und DER in init(rawRepresentation:) löst incorrectParameterSize aus, während isValidSignature einfach false zurückgibt.
Die Nonces sind zufällig – zwei Signaturen derselben Nachricht unterschieden sich, und der Testschlüssel aus RFC 6979 ergab nicht das r aus dem RFC –, und s wird nicht normalisiert: High-S-Werte kommen vor, und eine Signatur, in der s durch n − s ersetzt war, bestand die Prüfung. signature(for: data) hasht mit dem zur Kurve passenden Hash (SHA-256, SHA-384, SHA-512), signature(for: digest) akzeptiert dagegen jeden Digest-Typ: Ein SHA-256-Digest ließ sich mit einem P-384-Schlüssel signieren und prüfen, und ein SHA-512-Digest wurde bei P-256 auf seine ersten 32 Byte gekürzt, was Security.framework bestätigte. Übergib beim Pre-Hashing selbst den passenden Digest.
Ed25519-Signaturen (Curve25519.Signing) sind randomisiert: Mit dem Testschlüssel aus RFC 8032 unterschied sich die Signatur, die CryptoKit für die Testnachricht erzeugte, von der aus dem RFC und von der eigenen vorherigen, dennoch bestanden beide die Prüfung, auch mit Node.js. Tests, die Signaturbytes mit den Vektoren aus RFC 8032 vergleichen, schlagen mit CryptoKit unter macOS deshalb fehl; prüfe stattdessen die Signaturen. Nicht kanonische S-Werte werden abgelehnt, aber das neutrale Element wurde als öffentlicher Schlüssel akzeptiert, und eine Signatur mit R = neutrales Element und S = 0 bestand die Prüfung für eine beliebige Nachricht. Lehne Schlüssel kleiner Ordnung selbst ab, wenn eine Signatur an einen bestimmten Signierer gebunden sein muss. Ed25519-Schlüssel gibt es nur als 32 rohe Bytes; eine PEM- oder DER-Form existiert für sie nicht.
Die Post-Quanten-Typen sind ML-KEM-768 und ML-KEM-1024, ML-DSA-65 und ML-DSA-87 – ML-KEM-512, ML-DSA-44 und SLH-DSA fehlen – sowie das hybride X-Wing-KEM (XWingMLKEM768X25519), das auch als HPKE-Cipher-Suite angeboten wird. ML-DSA signiert im Hedged-Modus und akzeptiert einen Kontext-String nach FIPS 204, den der Verifizierer wiederholen muss. Die ML-KEM-Entkapselung eines beschädigten Chiffrats gibt einen anderen Schlüssel zurück, statt einen Fehler zu werfen. Private Schlüssel werden nur als Seeds gespeichert – 64 Byte für ML-KEM, 32 für ML-DSA – oder als Seed mit Integritätsprüfung; ein expandierter privater Schlüssel, den eine andere Bibliothek exportiert hat, lässt sich daher nicht importieren. Probiere die Verfahren im ML-KEM-Tool und im Tool für Post-Quanten-Signaturen aus.
SecureEnclave.P256.Signing.PrivateKey() erzeugt einen Schlüssel in der Secure Enclave, und auf diesem Mac taten das auch die ML-KEM- und ML-DSA-Typen unter SecureEnclave. Diese Typen geben keinen privaten Schlüssel in roher Form, als DER oder PEM heraus – nur dataRepresentation, ein Handle, mit dem sich der Schlüssel wieder öffnen ließ –, während der öffentliche Schlüssel ein gewöhnlicher P256.Signing.PublicKey oder MLDSA65.PublicKey ist. Software-Schlüssel für P-256 lassen sich als PKCS#8 exportieren (derRepresentation, pemRepresentation) und aus PKCS#8 und SEC1 importieren, jeweils als PEM oder DER, nicht aber aus verschlüsseltem PKCS#8; JWK unterstützt CryptoKit nicht.