Verifying LLM Response Origins: Cryptographic Provenance in Practice

    When LLM API responses pass through proxies, gateways, or resellers, callers often receive nothing more than plain text. Billing may say one model tier while the upstream actually runs a cheaper model, a trimmed variant, or even output generated by an entirely different system. This article explains why conventional detection methods fall short, how cryptographic signing of request commitments and outputs creates a verifiable proof of origin, what such proofs can and cannot establish, and how to implement verification in production.

    Once a model service passes through a proxy, gateway, or secondary wrapper, what the caller sees is often just a piece of text. The bill may name a particular model tier, while the upstream actually executes a cheaper model, a trimmed-down version, or even output generated by another system and forwarded verbatim. Asking the model “who are you?” is nearly useless: a system prompt can make any model claim a designated identity. Comparing writing styles, inspecting returned fields, or guessing at reasoning traces are, at best, circumstantial evidence—they cannot produce a reproducible, publicly checkable conclusion when a dispute arises. What provenance attestation solves is turning “which release identity generated this response, under which input commitment” from a verbal assurance into a verifiable object.

    Where the Problem Comes From

    The typical enterprise path looks like this: an application sends requests to a unified gateway, which forwards them to a model vendor or an intermediary service. Every additional hop in this chain is another place where the model name can be rewritten, the upstream swapped, or metadata dropped. The risks are not limited to malicious impersonation. They also include silent downgrades for cost optimization, failover to a backup model without informing the caller, and forwarding user requests to an external model and returning the answer under one’s own brand. To the caller, all three look identical: the API call succeeds, the fields are complete, the content seems plausible—but the product and the delivery do not match.

    Model providers need to prove themselves too. When users complain that “quality suddenly dropped,” without evidence bound to a specific release version, the provider cannot easily distinguish whether the cause is a prompt change, a sampling parameter change, a data distribution shift, or an actual change of weights or inference configuration on the server. Without a cryptographic anchor, both sides can only rely on contracts and logs as a matter of mutual trust.

    Why Existing Detection Isn’t Enough

    Identity interrogation depends on the model obeying prompts, and the prompt itself can be injected by an intermediate layer. Style comparison depends on corpora and subjective thresholds; the same model can write very differently at different temperatures or under different system prompts, while different models can converge toward similar styles after alignment. The model name field in response headers is filled in by the server, so intermediaries can forge it verbatim. Chain-of-thought text or internal markers, if they are just text, can likewise be generated or stitched together. These methods are fine for routine monitoring and anomaly alerts, but not suitable as the final basis for billing, compliance, or vendor assessment.

    More fundamentally, the goal is proof, not detection. What callers really need to confirm is usually not “does this sound like model X,” but “was this output produced by the agreed release identity, under the agreed request commitment, without being swapped in transit?” That is an authentication problem, not a style-classification problem.

    What Provenance Attestation Does Conceptually

    The general approach worth discussing in the industry is for the model publisher to compute a digital signature over the canonicalized request commitment and output content, using a signing key only it holds, and to hand the verification public key, key identifier, and algorithm identifier to callers. Anyone holding the public key can verify the signature without contacting the issuer. A passing signature means the material has not been altered since signing, and that the signing key corresponds to the claimed release identity. A failed signature—or no signature at all—means the response cannot be attributed to that identity.

    It does not automatically prove “the answer is high quality,” nor that “no cheaper model could produce similar text.” It proves a cryptographic binding between identity and content, not semantic merit. If the publisher itself signs a downgraded service with the same key, verification will still pass—so the key must be bound to an auditable release unit, not just a brand slogan.

    Conceptually, the material should include at least:

    • Release identifier: a stable identifier for the model family, version, or inference configuration, defined by the issuer with its meaning published.
    • Request commitment: a canonicalized digest of the user-visible input, such as a hash of the message sequence, key sampling parameters, and tool definitions—avoiding repeated propagation of full private plaintext.
    • Output commitment: a canonicalized representation of the assistant-visible output, including the final text and any structured fields the agreement requires to be bound.
    • Signature and key reference: the algorithm, key identifier, signature value, and optionally a signing time and nonce for replay prevention.
    • Public key distribution record: how to obtain the public key or certificate chain, its validity window, and revocation status.

    Canonicalization must precede signing. If whitespace, field ordering, encoding, or optional metadata are unstable, the same response yields different byte strings, and verification fails meaninglessly. The specification should be written as public, implementation-language-independent rules, with fixed test vectors for self-checking.

    How to Implement Verification

    Callers should not merely display a “verified” badge in the UI. Make verification an independent step, decoupled from business parsing. The following sketch illustrates the data relationships only; it is not the interface of any specific product:

    1. canonical = canonicalize(release_id, request_commitment, output)
    2. assert verify(public_key[key_id], canonical, signature)
    3. assert key_id in published_keys(release_id)
    4. assert not revoked(key_id, signed_at)
    5. assert request_commitment == hash(local_request_view)

    The local request view must match exactly what was sent. If the gateway injects dates, user identifiers, or hidden prompts, those fields must either be included in the mutually agreed commitment or explicitly excluded from the signing scope. The more exclusions, the more room for substitution—exclusions belong in your threat model, not in defaults to be ignored.

    Enterprise deployments typically also need:

    1. Key acquisition and pinning. Fetch public keys from a read-only channel announced by the publisher, pinned by content hash or certificate, so that verification does not re-trust the same potentially malicious proxy.
    2. Failure policies. Count missing signatures, corrupted signatures, expired keys, and mismatched request commitments separately. Billing and pass-through decisions are business choices, but the technical side should at least retain the original material.
    3. Sampling versus full coverage. High-value endpoints can verify every response; low-value traffic can be sampled—but sampling cannot replace a contractual requirement of “must be verifiable.”
    4. Audit trails. Store canonicalized bytes, signatures, and verification results in object storage or a log service. Monitor alerting should watch for spikes in verification failure rates, not just API success rates.
    5. Key rotation. When a new version ships or key compromise is suspected, old keys move to verify-only or are revoked outright. Historical responses must remain re-verifiable with the public key that was valid at signing time.

    What It Catches, and What It Doesn’t

    Assuming the publisher signs honestly and the caller verifies independently, an intermediary substituting an unauthorized model’s output will be exposed by the missing valid signature. Intercepting a real response and tampering with the text also breaks the signature. Replaying an old response against a new request fails on the request commitment mismatch, so commitments should include a call-unique identifier or time boundary to prevent cross-request reuse.

    Signature verification cannot help in the following cases; other controls are needed:

    • The publisher willingly signs a wrong upstream. Cryptography cannot force issuers to be honest; it only pins responsibility on whoever holds the private key.
    • Under the same release identifier, the server changes decoding strategy, tool execution, or retrieval results, and those factors are not in the commitment. The signature remains valid while behavior has changed. The specification must state clearly which side effects fall within the commitment.
    • A fully offline counterfeit service that never provides signatures. If callers treat “no signature, allow anyway” as the default, anti-fraud is effectively switched off.
    • Privacy and compliance. If the request commitment uses a weak hash over a small input space, it may still be enumerable. For personal data, store only commitments and necessary metadata, and limit retention periods.

    Provenance attestation is therefore a necessary condition for vendor governance, not a substitute for model evaluation. Quality regressions still require fixed evaluation suites, human spot checks, and business metrics.

    Design Trade-offs for Adoption

    Latency. Signing and verification cost far less than large-model inference itself; the bottlenecks are usually the canonicalization implementation and key state lookups. Do not synchronously fetch remote revocation lists on the hot path—use a local cache with short refresh cycles, and treat “revocation status unconfirmed” as an explicit degradation branch.

    Compatibility. For streaming output, specify whether the signature covers the final aggregated result or each chunk. If only the final result is signed, callers must buffer chunks and verify at the end frame; before verification, the text must not be written into non-rollbackable business state as authenticated content. For tool calls and multi-turn conversations, agree on whether each turn’s commitment includes history, preventing an intermediary from swapping only the last turn.

    Organization. Procurement terms should require: publishing the verification material format, providing test vectors, documenting the key lifecycle, and granting callers the right to refuse payment or switch vendors when no valid proof exists. Engineering teams should treat verification failures as first-class errors, not debug-log lines followed by using the text anyway.

    Summary

    Trust in LLM delivery cannot rest on a model’s self-introduction or stylistic similarity. Signing the canonicalized release identifier, request commitment, and output commitment—and having callers verify with independently obtained public keys—turns model substitution, content swapping, and cross-request replay into detectable events. The scheme’s strength depends on whether the issuer binds keys to real release units, whether commitments cover inputs that change behavior, and whether callers reject results that fail verification. Quality, pricing, and compliance still need evaluation, contracts, and audits—but without this layer, all other checks lack a footing that can stand up to scrutiny.