Polyglot verification

A modern stack rarely speaks one language. The signing service might be Ruby, the verifier in the API gateway might be Go, the auditing pipeline might be Python, and the on-call runbook might be a shell script. Demanding that every consumer link against a Confium binding is unrealistic.

The Confium daemon solves this by exposing verification as a JSON-RPC service. Any language that can speak HTTP over a Unix socket (or TCP) can verify a composite signature, evaluate a threshold policy, or query a transparency log — without linking against any Confium code.

What changed in the workspace

The daemon gained two stateless, side-effect-free methods that are safe to expose to untrusted callers:

  • composite_verify — verify an Ed25519 + ECDSA-P256 composite signature against a public key + message.
  • attributes_evaluate — evaluate a threshold-policy predicate against a signer-attribute set, without touching engine state.

Both methods are pure: same inputs → same outputs, no mutation, no persisted state. That makes them safe to expose broadly — even to callers you don’t fully trust.

Where it fits

Need Use this
API gateway verifies a composite signature on every request composite_verify over Unix socket
Compliance pipeline checks a threshold policy before signing attributes_evaluate
Shell script audits a day’s signatures composite_verify via curl --unix-socket
Go service verifies without a CGo Confium binding composite_verify over TCP
Java service verifies without JNA glue composite_verify over TCP

Example: verify from a shell script

curl --unix-socket /var/run/confium.sock \
     -H 'content-type: application/json' \
     -d '{
           "jsonrpc": "2.0",
           "id": 1,
           "method": "composite_verify",
           "params": {
             "message": "'$(base64 -w0 message.bin)'",
             "signature": "'$(base64 -w0 sig.bin)'",
             "public_key": "'$(base64 -w0 pubkey.bin)'"
           }
         }' \
     http://localhost/

Response:

{"jsonrpc":"2.0","id":1,"result":{"valid":true,"components_checked":2}}

Example: verify from Go

// Composite verify via JSON-RPC over the daemon's Unix socket.
// No CGo, no Confium binding — just net/http.
type verifyReq struct {
    JSONRPC string                 `json:"jsonrpc"`
    ID      int                    `json:"id"`
    Method  string                 `json:"method"`
    Params  map[string]interface{} `json:"params"`
}

resp, err := client.Post("http://localhost/", "application/json",
    jsonReader(verifyReq{
        JSONRPC: "2.0", ID: 1, Method: "composite_verify",
        Params: map[string]interface{}{
            "message":   base64(message),
            "signature": base64(sig),
            "public_key": base64(pub),
        },
    }))

The Go service has zero Confium code in its binary. It just talks JSON-RPC over a Unix socket.

When to use the daemon vs a native binding

Use the daemon when Use a native binding when
Multiple languages need to verify One language, perf-critical
You want to upgrade Confium without recompiling consumers You want zero-latency in-process verify
Untrusted callers (stateless methods are safe) Trusted callers only
Shell scripts / ops automation Application hot path

The daemon and the bindings produce the same answers — they share the same engine code. Choose based on operational constraints, not cryptographic ones.

Deployment shape

┌─────────────────────────────────────────┐
│  Consumers (any language)               │
│  ┌──────┐ ┌──────┐ ┌──────┐ ┌────────┐  │
│  │ Go   │ │ Ruby │ │ Shell│ │ Python │  │
│  └──┬───┘ └──┬───┘ └──┬───┘ └───┬────┘  │
│     │        │        │         │       │
│     └────────┴────────┴─────────┘       │
│              │ JSON-RPC                 │
│              ▼                          │
│     ┌────────────────────┐              │
│     │ confiumd (daemon)  │              │
│     │  /var/run/confium  │              │
│     └────────────────────┘              │
└─────────────────────────────────────────┘

The daemon is the only Confium process consumers talk to. It exposes a stable JSON-RPC API across upgrades.

See also