A .NET implementation of JSON Signature Format (JSF) — a scheme for signing JSON data with enveloped signatures.
JSF embeds cryptographic signatures directly within JSON objects, using JSON Canonicalization Scheme (RFC 8785) to produce deterministic representations for signing and verification. Unlike JWS/JWT where signatures are separate from the data, JSF keeps signature and payload together in a single JSON structure.
- Single signatures, multi-signatures (independent signers), and signature chains (sequential)
- 15 algorithms via JWA identifiers: ECDSA (ES256/384/512), RSA PKCS#1 v1.5 (RS256/384/512), RSA-PSS (PS256/384/512), EdDSA (Ed25519/Ed448), HMAC (HS256/384/512)
- Embedded JWK public keys for self-contained verification
- Property exclusions and custom extensions
- Non-mutating — all operations return new documents
- Accepts both
JsonObjectandstringinputs - Custom algorithm registry for extensibility
- .NET 8.0+
| Project | Description | Details |
|---|---|---|
| CoderPatros.Jsf | .NET library for signing and verifying JSON documents | Library README |
| CoderPatros.Jsf.Cli | Command-line tool for key generation, signing, and verification | CLI README |
| CoderPatros.Jsf.Api | REST API for key generation, signing, and verification | API README |
| CoderPatros.Jsf.Web | Browser-based tool for key generation, signing, and verification | Web README |
Install the NuGet package:
dotnet add package CoderPatros.JsfSign and verify a document:
using System.Security.Cryptography;
using System.Text.Json.Nodes;
using CoderPatros.Jsf;
using CoderPatros.Jsf.Keys;
using CoderPatros.Jsf.Models;
var service = new JsfSignatureService();
// Create a key pair
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);
var signingKey = SigningKey.FromECDsa(ecdsa);
var verificationKey = VerificationKey.FromECDsa(ecdsa);
// Sign
var document = new JsonObject { ["message"] = "hello" };
var signed = service.Sign(document, new SignatureOptions
{
Algorithm = JsfAlgorithm.ES256,
Key = signingKey
});
// Verify
var result = service.Verify(signed, new VerificationOptions
{
Key = verificationKey
});
Console.WriteLine(result.IsValid); // trueSee the Library README for the full API reference, multi-signature support, signature chains, key management, custom algorithms, and more.
Download the latest binary from the Releases page, or build from source:
dotnet build src/CoderPatros.Jsf.CliGenerate keys, sign, and verify:
# Generate an ECDSA key pair
jsf generate-key -a ES256
# Sign a document
jsf sign -k ES256-private.jwk -a ES256 -i document.json > signed.json
# Verify the signature
jsf verify -k ES256-public.jwk -i signed.json
# Output: ValidThe CLI also supports stdin/stdout piping, embedded public keys, key identifiers, and algorithm whitelisting. See the CLI README for the full command reference.
Run the API server with Docker:
docker run --rm -p 8080:8080 coderpatros/jsf-apiOr from source:
dotnet run --project src/CoderPatros.Jsf.ApiGenerate keys, sign, and verify with curl:
# Generate an ECDSA key pair
curl -s -X POST http://localhost:5000/api/keys/generate \
-H "Content-Type: application/json" \
-d '{"algorithm":"ES256"}'
# Sign a document
curl -s -X POST http://localhost:5000/api/sign \
-H "Content-Type: application/json" \
-d '{"document":{"message":"hello"},"algorithm":"ES256","key":{...}}'
# Verify the signature
curl -s -X POST http://localhost:5000/api/verify \
-H "Content-Type: application/json" \
-d '{"document":{...},"key":{...}}'
# Output: {"isValid":true,"error":null}The API also supports multi-signatures and signature chains. See the API README for the full endpoint reference.
Try the web tool online at patrickdwyer.au/dotnet-jsf.
Run the web tool with Docker:
docker run --rm -p 8080:8080 coderpatros/jsf-webOr run it locally:
dotnet run --project src/CoderPatros.Jsf.WebOpen the app in your browser to generate keys, sign documents, and verify signatures. All cryptographic operations run entirely in the browser — your keys and documents never leave your machine. See the Web README for more details.
- A signature object is created with the algorithm, optional public key, key ID, excludes, and extensions — but no
valueyet - This partial signature object is attached to the document
- The entire document is canonicalized using JCS (RFC 8785)
- The canonical bytes are signed with the specified algorithm and key
- The base64url-encoded signature is set as the
valueproperty
Verification reverses the process: remove value, canonicalize, and verify.
dotnet testApache-2.0