Skip to main content

Message Signing

Excalibur.Dispatch provides message signing to ensure messages haven't been tampered with during transmission. The signing infrastructure supports both symmetric (HMAC) and asymmetric (ECDSA, Ed25519, RSA) algorithms.

Package: Excalibur.Dispatch.Security

Architecture

The signing system follows a composite pattern (similar to ASP.NET Core CompositeFileProvider):

IMessageSigningService
├── HmacMessageSigningService (default, symmetric)
└── CompositeMessageSigningService (multi-algorithm)
├── HmacSignatureAlgorithmProvider (HMAC-SHA256/512)
├── EcdsaSignatureAlgorithmProvider (ECDSA P-256)
└── Ed25519SignatureAlgorithmProvider (Ed25519)
  • AddMessageSigning() — Registers HmacMessageSigningService for HMAC-only scenarios
  • AddAsymmetricSigning() — Registers CompositeMessageSigningService with all algorithm providers for non-repudiation scenarios

Both methods register MessageSigningMiddleware in the Dispatch pipeline automatically.

Supported Algorithms

AlgorithmEnum ValueTypeUse Case
HMAC-SHA256SigningAlgorithm.HMACSHA256SymmetricInternal service-to-service (default)
HMAC-SHA512SigningAlgorithm.HMACSHA512SymmetricHigher security symmetric
ECDSA P-256SigningAlgorithm.ECDSASHA256AsymmetricNon-repudiation, cross-boundary
Ed25519SigningAlgorithm.Ed25519AsymmetricHigh-performance asymmetric
RSA-SHA256SigningAlgorithm.RSASHA256AsymmetricLegacy interoperability
RSA-PSS-SHA256SigningAlgorithm.RSAPSSSHA256AsymmetricModern RSA with PSS padding

Setup

HMAC Signing (Symmetric)

For service-to-service signing where all parties share a secret key:

builder.Services.AddMessageSigning(opt =>
{
opt.Enabled = true;
opt.DefaultAlgorithm = SigningAlgorithm.HMACSHA256;
opt.DefaultKeyId = "service-signing-key";
opt.MaxSignatureAgeMinutes = 5;
});

Asymmetric Signing (ECDSA / Ed25519)

For non-repudiation scenarios where the signer and verifier use different keys:

builder.Services.AddAsymmetricSigning(opt =>
{
opt.Enabled = true;
opt.DefaultAlgorithm = SigningAlgorithm.ECDSASHA256;
opt.DefaultKeyId = "ecdsa-signing-key";
opt.MaxSignatureAgeMinutes = 5;
opt.IncludeTimestampByDefault = true;
opt.KeyRotationIntervalDays = 30;
});

AddAsymmetricSigning() registers all algorithm providers (HMAC, ECDSA, Ed25519) via CompositeMessageSigningService, so you can use any algorithm at runtime.

Per-Tenant Algorithms

Override the signing algorithm for specific tenants:

builder.Services.AddAsymmetricSigning(opt =>
{
opt.DefaultAlgorithm = SigningAlgorithm.HMACSHA256;
opt.TenantAlgorithms["tenant-financial"] = SigningAlgorithm.ECDSASHA256;
opt.TenantAlgorithms["tenant-healthcare"] = SigningAlgorithm.Ed25519;
});

Full Security Registration

Use AddDispatchSecurity() to register signing alongside encryption, rate limiting, and authentication:

builder.Services.AddDispatchSecurity(security =>
{
security.Signing.EnableSigning = true;
security.Signing.SigningAlgorithm = SigningAlgorithm.ECDSASHA256;

security.Encryption.EnableEncryption = true;
security.Authentication.EnableAuthentication = true;
});

Key Provider

Signing requires an IKeyProvider to supply key material. Cloud-specific packages provide implementations:

  • Excalibur.Dispatch.Security.Azure — Azure Key Vault
  • Excalibur.Dispatch.Security.Aws — AWS KMS

For local development, register a custom IKeyProvider:

builder.Services.AddSingleton<IKeyProvider, MyLocalKeyProvider>();

Asymmetric Key Resolution

For asymmetric algorithms (ECDSA, Ed25519, RSA), the CompositeMessageSigningService automatically appends :pub to the key ID when resolving keys for verification. Store your keys using this convention:

OperationKey ID resolved
Signingsigning:{tenantId}:{keyId}
Verificationsigning:{tenantId}:{keyId}:pub

SigningOptions Reference

PropertyTypeDefaultDescription
EnabledbooltrueEnable/disable signing
DefaultAlgorithmSigningAlgorithmHMACSHA256Default algorithm
DefaultKeyIdstring?nullDefault key identifier
MaxSignatureAgeMinutesint5Replay protection window
IncludeTimestampByDefaultbooltrueEmbed timestamp in signed data
KeyRotationIntervalDaysint30Key rotation interval
TenantAlgorithmsDictionary<string, SigningAlgorithm>emptyPer-tenant algorithm overrides

Pipeline Integration

MessageSigningMiddleware runs at the Validation stage of the Dispatch pipeline. It:

  1. Outbound messages — Signs message content using the configured algorithm and key
  2. Inbound messages — Verifies the signature and rejects tampered messages

The middleware is registered automatically by both AddMessageSigning() and AddAsymmetricSigning().

See Also