BouncyCastle.Cryptography (el paquete que sustituyó a Portable.BouncyCastle) es código administrado puro: sus resultados no dependen de Windows CNG ni de la versión de OpenSSL de Linux, y eso es justo lo que lo hace útil junto a System.Security.Cryptography. Ofrece una API SignerUtilities basada en cadenas y clases de más bajo nivel como ECDsaSigner.
Sus valores predeterminados de ECDSA siguen la tradición de OpenSSL y no la de .NET: SHA-256withECDSA produce DER, mientras que SHA-256withPLAIN-ECDSA da el r‖s en bruto de 64 bytes que usan el propio ECDsa de .NET y JWS. Confundirlos es el fallo de interoperabilidad habitual entre las dos bibliotecas dentro de una misma aplicación, y cualquier entrada mal formada devuelve false en lugar de lanzar una excepción. Los nonces son aleatorios con SignerUtilities; ECDsaSigner con un HMacDsaKCalculator reprodujo el vector de prueba del RFC 6979. s no se normaliza y la verificación acepta high-S.
La cobertura es el motivo por el que se añade: de P-224 a P-521, secp256k1 y las curvas Brainpool r1; Ed25519 y Ed448, como en el ejemplo; y ML-KEM, ML-DSA y SLH-DSA mediante MLKemEncapsulator, MLDsaSigner y SlhDsaSigner, que funcionaron todos en la misma imagen de Linux en la que la biblioteca de clases base no indicaba ninguna compatibilidad poscuántica. Prueba los algoritmos en la herramienta de firmas poscuánticas.
PemWriter escribe las claves privadas EC como SEC1 -----BEGIN EC PRIVATE KEY----- y PemReader las devuelve como un AsymmetricCipherKeyPair; PKCS#8 pasa por PrivateKeyInfoFactory. La versión propia del ensamblado es la de nombre seguro 2.0.0 en todas las versiones 2.x, así que comprueba la versión del paquete (aquí, 2.7.0) cuando compares comportamientos.