For developers

Build on Confium in your language

Three bindings ship today: Ruby (full API surface via native extension), Rust (the source of truth), and WASM (browser/Node.js verifier). Each gets you to a working verify in under five minutes.


Pick a binding

Binding Use when Sign Verify Install
Ruby Ruby/Rails/Sinatra app; you want a friendly API and don't need bare-metal perf. Yes Yes gem install confium
Rust You need maximum performance, custom integrations, or are building a Confium plugin. Yes Yes cargo add confium-core
WASM Browser / Node.js verifier. Composite sigs, transparency proofs, X.509 / CMS parsing. No Yes npm install @confium/confium-wasm

The WASM package is verifier-only by design. Signing requires the full Rust or Ruby stack; browsers verify, servers sign.

Install

$ gem install confium

Ruby ≥ 3.1 + Rust stable for the native extension.

Five-minute quickstart: verify a composite signature in Ruby

The most common developer task: someone hands you a composite signature and you need to verify it. Here's a complete Sinatra app that does it in ~50 lines.

# app.rb
require "sinatra/base"
require "confium"

class VerifyApp < Sinatra::Base
  before { content_type :json }

  post "/verify" do
    payload = JSON.parse(request.body.read)
    message = payload["message"].b
    sig = Confium::Composite::Signature.from_json(payload["signature"].to_json)

    result = sig.verify(message, {
      "Ed25519"     => :builtin,
      "ECDSA-P256"  => :builtin,
      "ML-DSA-65"   => ->(pk, msg, s) { my_pq_verifier.verify(pk, msg, s) },
    })

    {
      valid:        result.all_verified?,
      per_component: result.per_component,
    }.to_json
  rescue Confium::ParseError => e
    halt 400, { error: "parse_failed", details: e.details }.to_json
  rescue Confium::VerificationError => e
    halt 422, { error: "verification_failed", details: e.details }.to_json
  end
end

Run it: ruby app.rb. Test it: curl -X POST http://localhost:4567/verify -d @payload.json.

For the full walkthrough (install, parse cert, validate chain, anchor in transparency log), see the Sinatra verifier quickstart in the Ruby gem docs.

Five-minute quickstart: threshold signing in Rust

The second most common task: split a key across N parties and produce a signature without ever reconstructing the secret.

use confium_tc_frost_p256::FrostP256;

// 1. Generate a keypair.
let kp = FrostP256::generate_keypair()?;

// 2. Split into 5 shares, threshold 3.
let shares = FrostP256::split_secret(&kp.private_key, 3, 5)?;

// 3. Distribute shares[i] to party i. The original secret can
//    now be destroyed — it will never be needed again.

// 4. Recover the secret from any 3 shares (demonstration only —
//    in production you never reconstruct; you co-sign instead).
let recovered = FrostP256::recover_secret(&[
    shares[0].as_ref(),
    shares[2].as_ref(),
    shares[4].as_ref(),
])?;
assert_eq!(recovered, kp.private_key);

// 5. Sign with the original key (in production, sign with shares).
let sig = FrostP256::sign(&kp.private_key, b"threshold test")?;
println!("der: , fixed: ", sig.der.len(), sig.fixed.len());

The full end-to-end walkthrough lives in the threshold-signing example in the Rust workspace docs.

Five-minute quickstart: WASM verifier in a browser

import init, { CompositeSignature } from "@confium/confium-wasm";

await init();

const sig = CompositeSignature.from_json(jsonString);
const result = sig.verify(messageBytes, {
  "Ed25519": "builtin",
  "ECDSA-P256": "builtin",
  "ML-DSA-65": (pk, msg, sig) => myExternalVerifier(pk, msg, sig),
});

console.log(result.all_verified);      // true
console.log(result.per_component);     // { Ed25519: true, ... }

The WASM package ships with per-subsystem Cargo features (verify-composite, verify-transparency, verify-attributes, verify-pki) so you can tree-shake down to just what you need.

The typed error model

Every failure mode has a typed error class. There are no bare RuntimeError raises.

Confium::Error                  # root — rescue this as catch-all
├── ParseError                  # malformed PEM / DER / JSON input
├── ValidationError             # well-formed but invalid (e.g. expired cert)
├── VerificationError           # signature / proof / inclusion check failed
├── ThresholdError              # threshold protocol failure (bad share, no quorum)
├── CryptoError                 # underlying primitive failure
├── NotFoundError               # requested signer / cert / share not found
├── IndexError                  # sequence number out of range
├── UnresolvedSignerError       # required signer could not be resolved
└── PolicyViolationError        # jurisdictional / FIPS policy violation

Every error carries .details — a Hash with structured context (which cert, which algorithm, which check failed). Code that reads .details should treat the keys as advisory and defensively check for presence.

See the error handling guide for HTTP-status mapping and rescue patterns.

Where to read next

  • Ruby API referenceall 11 subsystems documented.
  • Rust workspace map43-crate layout.
  • Sinatra verifier quickstart — the canonical end-to-end Ruby example.
  • Threshold signing example — the canonical end-to-end Rust example.
  • PQ migration walkthrough — composite signatures deep dive.
  • Policy / FIPS mode — jurisdictional algorithm allow-lists.