Whisper · Docs
Agriculture

Equipment & ECU identity

Give a machine or an ECU a routable IPv6 /128 derived from the hardware key it already holds and its equipment PIN. The address is the machine: forge-proof, tenant-private, DNSSEC-anchored, and revocable by the owner in one publicly verifiable call.

This is the spine of the agriculture vertical, and it is shipped and live. Everything else (the equipment-API-abuse cure, the agritech integrations, the compliance evidence) builds on the one idea below: a machine's network address stops being a disposable label a proxy can rotate and becomes a cryptographic fact only that machine's silicon can stand behind.

Two tiers, per Postel's Law. With no API key anyone, including the farmer who owns the machine, can verify its identity from stock tools (dig, curl, RDAP) because the identity is public by design. With your key you provision and govern: mint the /128, source-bind its egress, pull its logs, and revoke it. Verification never needs an account; the control plane does.

The address is the machine

Almost every farm-data backend authenticates a claim, never a machine. A bearer token, a static API-key header, a grower password: each says "the holder of this string may act," and a string travels. It can be phished, replayed, lifted from a reverse-engineered app, and carried to any IP on earth. That is the root cause behind the whole family of farm-platform abuses: organization enumeration, broken object-level authorization (BOLA), one operator quietly harvesting a whole co-op's agronomic data from a residential-proxy swarm. The API is used exactly as designed; the last IP your SOC records means nothing, because the caller was never the machine.

Whisper closes the gap by making the network address itself the credential. A machine gets a real, routable /128 out of 2a04:2a01::/32 (announced by AS219419) that is a deterministic function of the hardware key the device was born with and its equipment PIN. Because the address is derived from a key only that device holds, you cannot present a machine identity whose key you don't have. One IP mapping to a whole fleet becomes physically impossible; a harvested grant off the wrong address is inert; and every forgery is a DNSSEC/DANE inconsistency any verifier catches for free.

One more thing the bus can't give you: on ISOBUS (ISO 11783 over J1939/CAN), a device identifies itself with a 64-bit NAME, manufacturer code, function, identity number. It is a self-declared claim, and AEF Guideline 040's ISOBUS security principles name exactly that class of gap. The derived /128 is the same machine's cryptographically provable public counterpart, at the IP boundary where proof is possible.

How the derivation works

The /128 is not assigned from a pool and written into a database. It is computed, the same way on every node, from inputs the machine already has. Three things go in:

Input What it is Where it lives
Device public key the SubjectPublicKeyInfo (SPKI) of the key the device was born with: a secure-element or TPM key in the telematics gateway the public half is submitted; the private key never leaves the device
Equipment PIN the 17-character product identification number stamped on the frame, canonicalized (it shares the road-vehicle VIN's 17-character format, and rides in the vin argument today) submitted with the request; the public index
Implement / ECU serial (optional) a per-component domain separator, so one machine can hold many addressable identities (telematics gateway, rate controller, a specific implement) optional; omit it for a single per-machine address

Those inputs are combined by a one-way derivation (with a Whisper-held secret mixed in) into a stable, unguessable interface identifier scoped to your fleet:

# inputs -> a stable, forge-proof interface identifier
derive( device public key,  PIN [, ECU serial],  your fleet )  -->  64 uniform bits

# the /64 prefix is your tenant block; the low 64 bits are the derived id
/128 = < your tenant /64 prefix > : < derived interface id >

Four properties fall straight out of that derivation, and each one is load-bearing:

The moment the address is derived it is published as a full identity, atomically: an AAAA, a forward-confirmed PTR, and a DANE-EE TLSA 3 1 1 record that pins the device's leaf key directly. All of it is DNSSEC-signed to the IANA root and registered in RDAP. That TLSA pin is what turns "the address is derived from a key" into "the address is provable against that key by anyone." See DANE & TLSA for the byte-for-byte record and DNSSEC for the chain it hangs from.

The private key never moves. The device submits only its public SPKI: the same public half of the secure-element / TPM key it holds. The server derives a public address from public inputs plus a server-side secret; it never sees, holds, or derives the machine's private key. The machine proves ownership later by presenting its own key against the DANE pin.

Provision a machine identity

Provisioning is one control-plane call: whisper.agents with op:'connect', tier:'wireguard', the device's public SPKI, and the PIN. It returns the deterministic /128 and a ready WireGuard configuration so the machine's traffic sources from its own identity. The endpoint is POST https://graph.whisper.security/api/query, authed with an X-API-Key header. No key ever travels in the body.

CALL whisper.agents({op:'connect', args:{
  tier:                'wireguard',
  identity_public_key: '<base64 SubjectPublicKeyInfo of the device key>',
  vin:                 '1AGCM82633A004352'   // the 17-character equipment PIN rides here today
  // ecu_serial: 'RC-0007'   // optional: a distinct /128 per implement ECU
}}) YIELD op, ok, status, result, error
   RETURN op, ok, status, result, error

With stock tools: just curl, no Whisper software. A quoted heredoc keeps the Cypher single-quotes intact so it pastes and runs as-is:

curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d @- <<'JSON' | jq .
{"query":"CALL whisper.agents({op:'connect', args:{tier:'wireguard', identity_public_key:'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...<SPKI>...', vin:'1AGCM82633A004352'}}) YIELD op, ok, status, result, error RETURN op, ok, status, result, error"}
JSON

The response is the standard envelope; result carries the derived address and the transport. Because the device holds its own key, no private key is ever returned. Only the public identity and the config that binds egress to it:

{
  "op": "connect", "ok": true, "status": 200,
  "result": {
    "tier":               "wireguard",
    "address":            "2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8",   // the deterministic /128
    "fqdn":               "a6f1007b9e2d30c8.<tenant>.agents.whisper.online",
    "server_public_key":  "…",
    "endpoint":           "…:51820",
    "dns":                "2a04:2a01:0:53::53",
    "wireguard_config":   "[Interface]\nAddress = 2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8/128\n…"
  },
  "error": null
}

Drop the returned wireguard_config onto the machine's telematics gateway (or feed it to wireproxy for a no-root, userspace tunnel) and every packet it sends now sources from its own /128. The backend authorizes on that address (a forge-proof, attributable, revocable network identity) instead of a token anyone could carry. For the full transport mechanics and the SOCKS5 / AnyIP alternatives, see Connect & egress; for every other op on this same endpoint, the Control plane reference.

The whisper CLI ships create --register, verify --trustless, policy, logs, and kill --revoke. A dedicated --pin flag is on the roadmap, not shipped. Provision machines today via the control-plane call above, which is live. When the flag lands it will be a thin wrapper over exactly this call.

Idempotent, with honest errors

Because the address is derived, provisioning is naturally idempotent, and the failure modes are clear rather than surprising, Postel all the way down:

You send You get
the same key + PIN again (same tenant) the same /128: a re-derivation, not a new allocation
the same key with a different PIN (same tenant) 409: the reused identity is never silently re-pinned to a mismatched address
a non-string identifier (or ecu_serial) 400 with a helpful detail, never an opaque 500
a PIN without identity_public_key 400: a device derives its address from its own key

Verify: keyless, no account

The identity half is public on purpose: anyone (a platform allowlisting a sanctioned consumer, an auditor, a dealer, the farmer who owns the machine) can prove a machine's /128 without a Whisper account and without trusting Whisper's word. Four independent checks, all from tools already on the machine:

# 1. Forward-confirmed reverse DNS: the address names the machine, the name resolves back
dig -x 2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8 +short
a6f1007b9e2d30c8.<tenant>.agents.whisper.online.

# 2. The keyless verdict endpoint (takes an address or an FQDN; ?ip=<target> also accepted)
curl -s https://whisper.online/verify-identity/2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8 | jq .
{
  "is_whisper_agent": true,
  "dane_ok": true,
  "jws_ok": true,
  "evidence": { "aaaa": "...", "ptr": "...", "tlsa": "3 1 1 b653a4ef…fcb82d1d" }
}

# 3. The registry record: RDAP, IP-anchored to the /128
curl -s https://whisper.online/ip/2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8 | jq '.handle, .parentHandle'

# 4. The full chain re-derived on YOUR machine, against the IANA root: Whisper NOT in the trust path
whisper verify --trustless a6f1007b9e2d30c8.<tenant>.agents.whisper.online

A target that isn't a Whisper identity gets a clean 200 {"is_whisper_agent": false}. A negative verdict is a successful answer, not an error; only genuinely malformed input draws a 400, never a 500. --trustless is the strong form: it validates DNSSEC from the root in-process, on your resolver, so the proof holds even for a party that won't take Whisper's word for anything. The full seven-proof walk lives in Verify an agent.

Revoke: worldwide, owner-thrown, in one call

A compromised, traded-in or decommissioned machine is one revoke away from having no network identity anywhere. The call tears down the /128, its PTR, and its DANE pin across both authoritative servers, and the change propagates at DNS-TTL speed:

CALL whisper.agents({op:'revoke', args:{agent:'2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8'}})

# prove it, zero Whisper software, the same stock tools that proved it existed:
dig -x 2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8 +short           # -> nothing
curl -s https://whisper.online/verify-identity/2a04:2a01:e5a7:41c9:a6f1:7b:9e2d:30c8
# -> {"is_whisper_agent": false, ...}

Revocation isn't a database flag you have to trust; it's provable the same way the identity was: the reverse lookup goes empty and the keyless verdict flips to false for everyone, everywhere, at once. That's the difference between this and the kill-switches agriculture already knows: the act is taken by the registered holder and is publicly checkable, never a covert lockout, and never a shared bearer token whose rotation reaches only the callers you can still reach. On resale, one revoke plus a re-register under the new owner moves the data trail with the title.

Attribution: name whoever already scraped you

Identity stops the next forgery. To name whoever already scraped a platform (across rotating clouds and residential proxies), the same API key opens the read-only attribution graph on the same endpoint. whisper.identify takes an address and returns the operator behind it, stitched across Amazon → Google → Azure hops that a raw last-IP loses:

curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.identify(\"203.0.113.45\")"}' | jq .

The read-only Cypher surface (identify, origins, walk, variants, history) runs over the same POST https://graph.whisper.security/api/query with your key. There is no whisper identify CLI subcommand. This is the API call, and it is live. Full verbs and shapes in Graph & cognition.

Where this fits (and where it doesn't)

Whisper anchors the machine's identity at the machine↔cloud IP boundary: the network endpoint your backend authorizes. It is additive: it complements the roots of trust you already run and does not try to replace them, and it deliberately stops at the hitch.

For mapping these identities to ISO 24882, AEF Guideline 040, the EU Data Act and Ag Data Transparent evidence and SOC export, see Agriculture compliance. The Splunk, Microsoft Sentinel and OpenCTI connectors are shipped; STIX/TAXII export is on the roadmap and labelled as such there. No specific OEM or platform is named, endorsed, or implicated as a breach victim anywhere in these docs; the abuse patterns cited are the public, cross-industry ones.

Next