SD-JWT / Compact · JWS JSON
Share selected claims with verifiable presentations
Issue, selectively present, and verify RFC 9901 SD-JWTs in Ruby. Use ruby-jwt and OpenSSL for signatures, with recursive disclosures and holder key binding handled by the gem.
require "sd_jwt"
issuer_key = OpenSSL::PKey::EC.generate("prime256v1")
holder_key = OpenSSL::PKey::EC.generate("prime256v1")
holder_jwk = JWT::JWK.new(holder_key).export.transform_keys(&:to_s)
issuer = SDJWT::Issuer.new(signing_key: issuer_key, alg: "ES256")
credential = issuer.issue(
{ "iss" => "https://issuer.example", "exp" => Time.now.to_i + 3600,
"name" => "Example", "address" => { "street" => "Harbor Street", "city" => "Port" } },
disclose: ["/name", "/address", "/address/street"],
decoys: 2,
holder_jwk: holder_jwk,
header: { "typ" => "example+sd-jwt", "kid" => "key-1" }
)
held = SDJWT.parse(credential.to_s) # Unauthenticated holder-side parsing.
presentation = held.present(
only: ["/name"],
key_binding: { key: holder_key, alg: "ES256", aud: "https://verifier.example", nonce: "transaction-nonce" }
)
verifier = SDJWT::Verifier.new(
algorithms: ["ES256"],
issuer_key: issuer_key, # Or ->(untrusted_header, untrusted_payload) { trusted_key_lookup(...) }
issuer: "https://issuer.example",
required_claims: ["iss", "exp", "cnf"],
require_key_binding: true,
audience: "https://verifier.example",
nonce: "transaction-nonce",
max_kb_age: 300
)
result = verifier.verify(presentation)
result.claims # Immutable, authenticated disclosed claims.
result.key_binding_verified # true
Issue disclosures
Create credentials with selectively disclosed object claims, array entries, and nested values.
Choose what to share
Select disclosure paths and bind a presentation to a holder key, audience, and transaction nonce.
Set verification policy
Verify Compact and JWS JSON forms with explicit algorithms, issuer trust, required claims, and limits.
Installation
Add the gem to your Gemfile:
gem "sd_jwt"
Run bundle install, then try the quick start. Requires Ruby 3.3 or later.
For supported dependencies and optional integrations, see the installation guide.
Scope & documentation
Applications must establish issuer trust and manage nonce replay protection, revocation, and credential profile rules. Parsing alone does not authenticate a credential. EdDSA, symmetric holder keys, and SD-CWT are outside scope.
Read the full documentation for supported formats, examples, and API details.
No independent external human security audit has been completed. Automated tests and RFC conformance checks do not replace such an audit. Security policy.