Skip to content

wsc: keyless signing over an arbitrary digest, not only a WASM Module #256

Description

@avrabe

Reported from varve, which depends on wsc for DSSE and is evaluating keyless signing to remove long-lived realm root keys entirely.

The gap

Verification is already general. airgapped::AirgappedVerifier::verify_signature takes a 32-byte hash:

pub fn verify_signature(
    &self,
    signature: &KeylessSignature,
    module_hash: &[u8; 32],
) -> Result<VerificationResult, WSError>

Signing is not. KeylessSigner::sign_module(&self, module: Module) requires a WASM Module.

So a caller with bytes that are not a WASM module — varve signs a layer manifest, whose sha256 is exactly a 32-byte digest — can verify with wsc but cannot sign with it.

Ask

A signing entry point over a digest, mirroring what the verifier already accepts:

pub fn sign_digest(&self, digest: &[u8; 32]) -> Result<KeylessSignature, WSError>

sign_module then becomes sign_digest(hash_of(module)) plus the module-embedding step, so there is one keyless signing path rather than two.

Why this matters beyond varve

The airgapped/ module is, as far as I can tell, the only implementation of offline Sigstore keyless verification with a provisioned Trust Bundle in the Rust ecosystem — with real TUF support (tuf.rs, 471 lines, no stubs), a bundle grace period, and an explicit unreliable-time fallback for devices with no clock.

That is valuable to anything signing artifacts for air-gapped consumers, not just WASM. The Module requirement on the signing side is the only thing making it WASM-specific, and it is not load-bearing — the verifier already proves the design is hash-based underneath.

Context

varve is considering replacing its realm root (a long-lived ed25519 key that it can neither rotate nor revoke — both stated as permanent limits in its own threat model) with keyless identity signing. The blocker for that was always offline verification for air-gapped consumers, and wsc::airgapped solves it. This entry point is what stands between the two halves.

Recorded on the varve side as DD-025. Happy to contribute the patch if you would rather review than write it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions