Aller au contenu
ecdsa.com
.NET

Bouncy Castle for .NET (BouncyCastle.Cryptography)

Bouncy Castle pour .NET, la bibliothèque cryptographique managée qu’ajoutent les développeurs .NET pour ce qui manque à la bibliothèque de classes de base : Ed25519 et Ed448, secp256k1 sur toutes les plateformes, ECDSA déterministe, PGP, PEM, ainsi que ML-KEM, ML-DSA et SLH-DSA sans dépendre du système d’exploitation.
Licence
MIT
Version vérifiée
2.7.0 ·
Code source
github.com/bcgit/bc-csharp
Documentation
www.bouncycastle.org/documentation/documentation-c/

Compatibilité en un coup d’œil

ECDSAEdDSAPost-quantique

Courbes ECDSA
P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
Ed25519Ed448
Algorithmes post-quantiques
ML-KEMML-DSASLH-DSA
Formats de clé publique
spki-pemspki-der
Formats de clé privée
pkcs8-dersec1-pem

BouncyCastle.Cryptography (le paquet qui a remplacé Portable.BouncyCastle) est du code entièrement managé : ses résultats ne dépendent ni de CNG sous Windows ni de la version d’OpenSSL sous Linux, et c’est précisément ce qui le rend utile à côté de System.Security.Cryptography. Il propose une API SignerUtilities fondée sur des chaînes de caractères et des classes de plus bas niveau comme ECDsaSigner.

Ses comportements ECDSA par défaut suivent la tradition d’OpenSSL plutôt que celle de .NET : SHA-256withECDSA produit du DER, tandis que SHA-256withPLAIN-ECDSA donne le r‖s brut de 64 octets qu’utilisent JWS et la classe ECDsa de .NET elle-même. Les confondre est l’échec d’interopérabilité classique entre les deux bibliothèques au sein d’une même application, et toute entrée mal formée renvoie false au lieu de lever une exception. Les nonces sont aléatoires via SignerUtilities ; ECDsaSigner avec un HMacDsaKCalculator a reproduit le vecteur de test de la RFC 6979. s n’est pas normalisé et la vérification accepte high-S.

C’est pour sa couverture que les développeurs l’ajoutent : de P-224 à P-521, secp256k1 et les courbes Brainpool r1 ; Ed25519 et Ed448, comme dans l’exemple ; et ML-KEM, ML-DSA et SLH-DSA via MLKemEncapsulator, MLDsaSigner et SlhDsaSigner, qui ont tous fonctionné sur la même image Linux où la bibliothèque de classes de base ne signalait aucune prise en charge post-quantique. Essayez les algorithmes dans le bac à sable des signatures post-quantiques.

PemWriter écrit les clés privées EC au format SEC1 -----BEGIN EC PRIVATE KEY-----, et PemReader les renvoie sous forme d’AsymmetricCipherKeyPair ; PKCS#8 passe par PrivateKeyInfoFactory. La version propre de l’assembly est la version de nom fort 2.0.0 pour toutes les versions 2.x : vérifiez donc la version du paquet (ici 2.7.0) lorsque vous comparez des comportements.

Les faits et les vérifications qui les fondent

Rien de ce qui suit n’est copié d’une documentation. La vérification content/libraries/verify/bouncy-castle-csharp/run.sh a exécuté Bouncy Castle for .NET (BouncyCastle.Cryptography) 2.7.0 dans l’image de conteneur mcr.microsoft.com/dotnet/sdk:10.0.402-noble le 20 octobre 2026 ; la page doit correspondre à ce que la vérification a affiché, et chaque fait cite les lignes en question.

  • Encodage des signatures ECDSA

    der

    SHA-256withECDSA renvoie du DER ; SHA-256withPLAIN-ECDSA renvoie 64 octets de r‖s brut.

    Relevé par la vérification
    fact ecdsa-signature-encoding = der
    evidence ecdsa-signature-encoding: SHA-256withPLAIN-ECDSA output: 64 bytes
  • Nonce ECDSA

    rfc6979-opt-in

    Aléatoire via SignerUtilities ; ECDsaSigner avec HMacDsaKCalculator a reproduit l’annexe A.2.5 de la RFC 6979.

    Relevé par la vérification
    fact ecdsa-nonce = rfc6979-opt-in
    evidence ecdsa-nonce: SHA-256withECDSA repeats: False; ECDsaSigner with HMacDsaKCalculator reproduces RFC 6979 A.2.5: True
  • Low-S à la signature

    either

    s n’est pas normalisé : des valeurs high-S sont apparues parmi 64 signatures.

    Relevé par la vérification
    fact ecdsa-low-s-sign = either
  • High-S à la vérification

    accepts-high-s

    Une signature DER dont s a été remplacé par n − s a été vérifiée.

    Relevé par la vérification
    fact ecdsa-low-s-verify = accepts-high-s
  • Ce que l’appel de signature hache

    hashes-message-or-digest

    SHA-256withECDSA hache les données ; NONEwithECDSA signe un condensat, et cette signature a été vérifiée sur le message.

    Relevé par la vérification
    fact ecdsa-prehash = hashes-message-or-digest
  • Signature ECDSA mal formée

    returns-false

    Une signature r‖s brute passée à SHA-256withECDSA et un bloc de 3 octets renvoient false.

    Relevé par la vérification
    fact ecdsa-malformed-signature = returns-false
    evidence ecdsa-malformed-signature: raw r||s to SHA-256withECDSA: false; 3 bytes: false
  • Courbes ECDSA

    P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1

    Signature et vérification réussies avec P-224, P-256, P-384, P-521, secp256k1 et brainpoolP256r1/P384r1/P512r1.

    Relevé par la vérification
    fact ecdsa-curves = P-224, P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • EdDSA

    Ed25519Ed448

    Ed25519 et Ed448.

    Relevé par la vérification
    fact eddsa = Ed25519, Ed448
  • Algorithmes post-quantiques

    ML-KEMML-DSASLH-DSA

    Encapsulation et décapsulation réussies avec ML-KEM-768, signature et vérification avec ML-DSA-65 et SLH-DSA-SHA2-128f, en code managé.

    Relevé par la vérification
    fact pqc = ML-KEM, ML-DSA, SLH-DSA
  • Formats de clé publique

    spki-pemspki-der

    SPKI PEM via PemReader et SPKI DER via PublicKeyFactory.

    Relevé par la vérification
    fact public-key-formats = spki-pem, spki-der
    evidence public-key-formats: PublicKeyFactory.CreateKey(SPKI DER) verifies: True
  • Formats de clé privée

    pkcs8-dersec1-pem

    PemWriter écrit et PemReader lit le SEC1 PEM ; le PKCS#8 DER se charge via PrivateKeyFactory.

    Relevé par la vérification
    fact private-key-formats = pkcs8-der, sec1-pem
    evidence private-key-formats: PemWriter writes -----BEGIN EC PRIVATE KEY-----; PemReader returns AsymmetricCipherKeyPair; PKCS#8 DER round trip signs: True

Utilisation

Signer et vérifier avec Ed25519, que System.Security.Cryptography ne fournit pas.
using System.Text;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;

var message = Encoding.UTF8.GetBytes("order #1042 approved");

// Ed25519, which the .NET base class library does not offer.
var generator = new Ed25519KeyPairGenerator();
generator.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
var pair = generator.GenerateKeyPair();

var signer = SignerUtilities.GetSigner("Ed25519");
signer.Init(true, pair.Private);
signer.BlockUpdate(message, 0, message.Length);
var signature = signer.GenerateSignature();

var verifier = SignerUtilities.GetSigner("Ed25519");
verifier.Init(false, pair.Public);
verifier.BlockUpdate(message, 0, message.Length);
Console.WriteLine($"signature: {signature.Length} bytes, verified: {verifier.VerifySignature(signature)}");

Le banc de test des extraits de code exécute chaque exemple tel quel dans l’image de conteneur mcr.microsoft.com/dotnet/sdk:10.0.402-noble, et l’exécution échoue si la sortie ne correspond pas.

Mise en place
dotnet new console --force -o . >/dev/null && dotnet add package BouncyCastle.Cryptography --version 2.7.0 >/dev/null
Commande
rm -f Program.cs && DOTNET_NOLOGO=1 dotnet run 2>/dev/null
La sortie doit correspondre à cette expression régulière
signature: 64 bytes, verified: True

Bibliothèques