BouncyCastle.Cryptography (das Paket, das Portable.BouncyCastle abgelöst hat) ist reiner verwalteter Code: Seine Ergebnisse hängen weder von Windows CNG noch von der OpenSSL-Version unter Linux ab – genau das macht es neben System.Security.Cryptography nützlich. Das Paket bietet die stringbasierte API SignerUtilities und tiefer liegende Klassen wie ECDsaSigner.
Die ECDSA-Standardeinstellungen folgen der OpenSSL-Tradition, nicht der von .NET: SHA-256withECDSA erzeugt DER, während SHA-256withPLAIN-ECDSA das 64 Byte lange rohe r‖s liefert, das ECDsa aus .NET selbst und JWS verwenden. Diese beiden zu verwechseln ist der typische Interoperabilitätsfehler zwischen den zwei Bibliotheken in einer Anwendung, und jede fehlerhafte Eingabe gibt false zurück, statt eine Ausnahme zu werfen. Über SignerUtilities sind die Nonces zufällig; ECDsaSigner mit einem HMacDsaKCalculator reproduzierte den Testvektor aus RFC 6979. s wird nicht normalisiert, und die Prüfung akzeptiert High-S.
Der Funktionsumfang ist der Grund, Bouncy Castle einzubinden: P-224 bis P-521, secp256k1 und die Brainpool-r1-Kurven; Ed25519 und Ed448 wie im Beispiel; außerdem ML-KEM, ML-DSA und SLH-DSA über MLKemEncapsulator, MLDsaSigner und SlhDsaSigner – alle funktionierten auf demselben Linux-Image, auf dem die Basisklassenbibliothek überhaupt keine Post-Quanten-Unterstützung meldete. Probiere die Algorithmen im Playground für Post-Quanten-Signaturen aus.
PemWriter schreibt private Schlüssel vom Typ EC als SEC1 -----BEGIN EC PRIVATE KEY-----, und PemReader gibt sie als AsymmetricCipherKeyPair zurück; PKCS#8 läuft über PrivateKeyInfoFactory. Die Version der Assembly selbst ist für jedes 2.x-Release die Strong-Name-Version 2.0.0; achte beim Vergleich des Verhaltens daher auf die Paketversion (hier 2.7.0).