Dexcompiler.Ed25519 1.0.5

dotnet add package Dexcompiler.Ed25519 --version 1.0.5
                    
NuGet\Install-Package Dexcompiler.Ed25519 -Version 1.0.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Dexcompiler.Ed25519" Version="1.0.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Dexcompiler.Ed25519" Version="1.0.5" />
                    
Directory.Packages.props
<PackageReference Include="Dexcompiler.Ed25519" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Dexcompiler.Ed25519 --version 1.0.5
                    
#r "nuget: Dexcompiler.Ed25519, 1.0.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Dexcompiler.Ed25519@1.0.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Dexcompiler.Ed25519&version=1.0.5
                    
Install as a Cake Addin
#tool nuget:?package=Dexcompiler.Ed25519&version=1.0.5
                    
Install as a Cake Tool

Ed25519

A pure C# implementation of the Ed25519 digital signature algorithm, ported from the ref10 reference implementation and the improved C port by Orson Peters (orlp/ed25519).

Features

  • RFC 8032 compliant - Passes all standard test vectors
  • Pure C# - No native dependencies
  • High performance - Uses precomputed tables for fast scalar multiplication
  • PKCS#8 / SPKI support - Import/export keys in standard formats
  • PEM support - Read and write PEM-encoded keys

Installation

Install from NuGet:

dotnet add package Dexcompiler.Ed25519

Note: This package ID is the canonical package name for this repository. The similarly named Ed25519 package on NuGet is a different project.

Usage

Generate a Keypair

using Ed25519;

Span<byte> publicKey = stackalloc byte[32];
Span<byte> privateKey = stackalloc byte[64];
Span<byte> seed = stackalloc byte[32];

// Fill seed with 32 bytes of cryptographically secure random data
RandomNumberGenerator.Fill(seed);

Ed25519.CreateKeypair(publicKey, privateKey, seed);

Key Material (important)

  • Seed (32 bytes): the secret input to RFC 8032 key generation. This library’s PKCS#8 helpers encode/decode the seed.
  • Public key (32 bytes): the encoded curve point.
  • Private key (64 bytes): this library’s “expanded” private key, derived as SHA-512(seed) and stored as:
    • privateKey[0..31]: clamped scalar
    • privateKey[32..63]: prefix

Ed25519.Sign(...) expects the expanded 64-byte private key (and optionally the public key).

API Notes

  • Deterministic signatures: Ed25519 signing is deterministic for a given (expanded) private key and message (no external randomness needed).
  • Constant-time vs variable-time:
    • Signing uses constant-time building blocks (CMov, etc.).
    • Verification uses variable-time operations (inputs are public).
  • Strict verification:
    • Verification rejects signatures with non-canonical S (must satisfy S < L).
    • Verification rejects low-order public keys (small torsion subgroup).
  • Exact-size contracts:
    • CreateKeypair: public key = 32 bytes, private key = 64 bytes, seed = 32 bytes.
    • Sign/Verify: fixed-size key/signature inputs must be exact size (not oversized).

Sign a Message

byte[] message = "Hello, World!"u8.ToArray();
Span<byte> signature = stackalloc byte[64];

Ed25519.Sign(signature, message, privateKey);

Verify a Signature

bool isValid = Ed25519.Verify(signature, message, publicKey);

Import/Export Keys (PKCS#8 and SPKI / RFC 8410)

// Export private key seed to PKCS#8 (DER)
byte[] pkcs8 = Pkcs.EncodePkcs8PrivateKey(seed);

// Import seed from PKCS#8 (DER)
byte[] importedSeed = Pkcs.DecodePkcs8PrivateKey(pkcs8);

// Re-expand to this library's 64-byte private key format (and compute public key)
Span<byte> importedPrivateKey = stackalloc byte[64];
Span<byte> importedPublicKey = stackalloc byte[32];
Ed25519.CreateKeypair(importedPublicKey, importedPrivateKey, importedSeed);

// Export public key to SPKI (DER)
byte[] spki = Pkcs.EncodeSubjectPublicKeyInfo(publicKey);

// Import public key from SPKI (DER)
byte[] importedPubKey = Pkcs.DecodeSubjectPublicKeyInfo(spki);

PEM Format

// Export to PEM
string privatePem = Pkcs.ExportPrivateKeyPem(seed);      // "PRIVATE KEY" (PKCS#8)
string publicPem = Pkcs.ExportPublicKeyPem(publicKey);   // "PUBLIC KEY" (SPKI)

// Import from PEM (example: private key)
byte[] privateDer = Pkcs.DecodePem(privatePem, "PRIVATE KEY");
byte[] importedSeed = Pkcs.DecodePkcs8PrivateKey(privateDer);

Building Self-Signed Certificates

While Ed25519 keys can be used for signing, .NET's X509Certificate2 has limited support for Ed25519. For self-signed certificates with Ed25519, you may need to:

  1. Generate the Ed25519 keypair using this library
  2. Manually construct the TBS (To-Be-Signed) certificate structure
  3. Sign it with Ed25519.Sign()
  4. Encode the final certificate in DER/PEM format

If your goal is certificate issuance, this repo includes CSR (PKCS#10) helpers in Pkcs:

  • Pkcs.EncodePkcs10CertificationRequest(...) (DER)
  • Pkcs.ExportCsrPem(...) (PEM)
  • Pkcs.VerifyPkcs10CertificationRequest(...)

It also supports exporting encrypted PKCS#8 PEM ("ENCRYPTED PRIVATE KEY") via Pkcs.ExportEncryptedPrivateKeyPem(seed, password, iterations).

The old encrypted export overload Pkcs.ExportEncryptedPrivateKeyPem(seed, publicKey, password, iterations) is kept for compatibility but marked obsolete; the publicKey argument is ignored.

Implementation Notes

This implementation follows the ref10 naming conventions from the original C code. The short names preserve traceability to the reference implementation for auditing purposes.

Naming Conventions

Type Full Name Description
Fe Field Element Internal type for elements of Z/(2²⁵⁵-19), represented as 10 limbs of 26/25 bits
Sc Scalar Internal type for integers modulo L (group order ≈ 2²⁵²)
Ge Group Element Internal static class for curve point operations
GeP2 Projective Point Internal point type in (X:Y:Z) projective coordinates where x=X/Z, y=Y/Z
GeP3 Extended Point Internal point type in (X:Y:Z:T) extended coordinates where T=XY/Z
GeP1P1 Completed Point Internal intermediate point form (X:Y:Z:T), with x=X/Z, y=Y/T
GePrecomp Precomputed Point Internal affine Niels form (y+x, y-x, 2dxy) for fast fixed-base multiplication
GeCached Cached Point Internal extended Niels form for efficient point addition

Precomputed Tables

Two precomputed tables accelerate scalar multiplication:

  • Base[32,8]: Contains (j+1) × 256^i × B for i ∈ [0,31], j ∈ [0,7]. Used by ScalarMultBase for signing.
  • Bi[8]: Contains (2i+1) × B for i ∈ [0,7]. Used by DoubleScalarMultVartime for verification.

Constant-Time Operations

The implementation uses constant-time conditional moves (CMov, CSwap) to prevent timing side-channels during signing. Verification uses variable-time operations since all inputs are public.

Curve Parameters

  • Curve: Edwards curve -x² + y² = 1 + dx²y² where d = -121665/121666
  • Base point B: The standard Ed25519 generator
  • Group order L: 2²⁵² + 27742317777372353535851937790883648493

Maintainer Release Workflow

  1. Set NUGET_API_KEY in repository secrets.
  2. Update Version in src/Ed25519.csproj for the intended release.
  3. Push a tag in vX.Y.Z format (for example, v1.0.5).
  4. GitHub Actions will build, test, pack, and publish Dexcompiler.Ed25519 with --skip-duplicate.
  5. Verify package availability on nuget.org and test dotnet add package Dexcompiler.Ed25519 in a clean project.

License

MIT License

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.5 111 4/2/2026
1.0.4 107 4/2/2026