Whisper · Docs
Automotive · Recipes

V2X · OTA · anti-counterfeit

Three copy-paste recipes put a forge-proof, revocable network identity under a vehicle, an ECU, and a genuine part. Each one runs today against the keyless verify surface anyone can reach.

They share one primitive: a routable IPv6 /128 that a device derives from a key it already holds, DNSSEC-signed and DANE-pinned so anyone can verify it and nobody can forge it. Everything below is built from shipped parts: the device /128, keyless verify, and one-call revoke. Where a step is a pattern you assemble rather than a single command, or a connector still on the roadmap, it says so in plain words.

What's shipped, stated honestly. The vehicle/ECU /128 derivation, the keyless verify / RDAP surface, and one-call revoke are live. Two caveats these recipes are written around: there is no --vin CLI flag yet, so vehicle provisioning is shown via the control-plane API (which is live); and the SIEM/threat-intel export connectors called out at the end are roadmap, not shipped. Whisper anchors the cloud/IP boundary. It is not in the V2X air interface, not in SecOC, and not in the charging handshake. Each recipe names exactly where it stops.

The shared primitive: an identity a device derives, not one you hand it

A vehicle, an ECU, or a smart component already carries a hardware key from the factory: an 802.1AR IDevID, a TPM, or a secure-element key. Whisper takes only its public SubjectPublicKeyInfo (SPKI) and, together with the VIN (and optionally an ECU or part serial), deterministically derives a /128 under 2a04:2a01::/32 (AS219419). The private key never leaves the device.

The derivation has four properties that make it useful as an identity rather than just an address:

Provision one with your API key. The vehicle submits its device public key and VIN, and gets back its deterministic /128 plus a WireGuard config:

# Provision a vehicle's identity from the device key it already holds + its VIN.
# Re-running with the same key+VIN returns the SAME /128 (idempotent).
curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.agents({op:'"'"'connect'"'"', args:{tier:'"'"'wireguard'"'"', identity_public_key:'"'"'<base64 SPKI of the device key>'"'"', vin:'"'"'1HGCM82633A004352'"'"'}}) YIELD op, ok, status, result, error RETURN op, ok, status, result, error"}' | jq .

# For a specific ECU, add ecu_serial as the domain separator for a distinct /128 per ECU:
#   args:{tier:'wireguard', identity_public_key:'…', vin:'1HGCM82633A004352', ecu_serial:'ADAS-7F31'}
i

A supplied VIN is checked against a reused identity: the same device key with a different VIN on your tenant is a 409, and a non-string VIN is a clear 400. Liberal in what it accepts, strict and unambiguous in what it commits. The server only ever derives a public address; it never sees or reconstructs the device's private key.

Once provisioned, every check in the three recipes below is keyless: no account, no API key, just DNS and TLS that any counterparty already has.

Recipe 1: Roadside & back-office peer verification

V2X safety messages ride SCMS on the air interface; the internet-side endpoints those messages flow to and from (a roadside unit reporting to a traffic-management backend, a misbehavior-authority service, an MEC application a fleet talks to) have no such identity. Give each one a /128 and either peer confirms the other with a stock DNS lookup, no shared CA list.

Boundary. Whisper is not in the PC5 / DSRC / C-V2X air interface and issues no IEEE 1609.2 pseudonym certificates. This complements SCMS: it authenticates the IP-facing peers (RSU↔backend, the enrollment/misbehavior report a vehicle fetches over cellular, the cloud service a fleet dials) that SCMS was never designed to cover. It does not touch the safety channel.

The two directions are the same one-line check, run by each side. A roadside unit (or a vehicle's telematics stack) confirms a back-office endpoint before trusting a command from it:

# The client side: prove the back-office endpoint is who it claims, trustless and
# re-derived against the IANA DNSSEC root, no Whisper API trusted as an authority.
whisper verify --trustless roadside-backend.demo.agents.whisper.online

dnssec   pass   DNSSEC-root   AAAA, PTR and TLSA(3 1 1) all DNSSEC-validated to the IANA root
dane     pass   DNSSEC-root   served leaf SPKI-SHA256 == TLSA pin
ledger   pass   DNSSEC-root   entry present, signature verifies
CRYPTOGRAPHICALLY PROVEN. Trust anchor: DNSSEC root (IANA) + DANE-EE. Whisper API NOT trusted

The backend, in turn, verifies the vehicle a report claims to come from. It's one keyless HTTPS call, no software to install:

# The server side: is this address a real, DANE-anchored vehicle identity?
curl -s https://whisper.online/verify-identity/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
{"is_whisper_agent":true,"dane_ok":true,"jws_ok":true,
 "evidence":{"address":"2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4",
   "ptr":"…","forward_aaaa":"2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4"}}

Because the reverse is forward-confirmed (PTR ⇄ AAAA), the same fact is checkable with nothing but dig, the tool already in every ops toolbox:

dig +short -x 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
acef2002a323d40d4.demo.agents.whisper.online.

That is mutual, forge-proof peer verification at the layer SCMS leaves open: neither side depends on a token that could be replayed from another host, and neither side has to trust a CA the other one chose.

Recipe 2: Bidirectional OTA-target verification

An OTA update is two trust questions, not one: is this really the OEM's update server, and is this really the ECU that's allowed to receive the image. Whisper answers both at the transport layer, keyless, before a single byte of firmware moves, and both answers are forge-proof.

Boundary. The firmware image itself stays signed by your existing update framework: Uptane, and the process discipline UNECE R156 SUMS requires. Whisper does not replace image signing; it authenticates the two endpoints and the ECU's network identity, so "who am I talking to" becomes as strong as "is this image signed." It complements R156; it is not a substitute for it.

Direction A: the ECU verifies the update server. Before it downloads, the ECU trustlessly confirms the update host's DANE-pinned identity, so a rogue or MITM'd server answering on that name fails immediately. It cannot present the OEM's pinned key:

# On the ECU, before fetching the image: is this the genuine update server?
whisper verify --trustless ota.demo.agents.whisper.online
dane   pass   DNSSEC-root   served leaf SPKI-SHA256 == TLSA pin

# Same check with stock tools, comparing the live SPKI hash to the DNSSEC-signed TLSA pin:
dig +short TLSA _443._tcp.ota.demo.agents.whisper.online
3 1 1 b653a4ef…fcb82d1d
openssl s_client -connect ota.demo.agents.whisper.online:443 </dev/null 2>/dev/null \
  | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der \
  | openssl dgst -sha256        # must equal the TLSA pin above

Direction B: the backend verifies the ECU. Before it authorizes or serves the image, the update backend confirms the requesting ECU's derived /128 is real and DANE-anchored. A cloned ECU can neither source packets from the genuine /128 nor DANE-prove it:

# On the update backend, before serving: is this the ECU we allocated?
curl -s https://whisper.online/verify-identity/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
{"is_whisper_agent":true,"dane_ok":true,"jws_ok":true, …}

Two keyless checks, one in each direction, and the update only proceeds when both pass. A stolen session token buys an attacker nothing: the identity is a network fact, not a bearer string, and it can't be lifted off the wire and replayed from elsewhere.

Recipe 3: The anti-counterfeit part

A genuine component holds a secure-element key from the factory; a counterfeit doesn't hold the one that was registered. Bind the genuine key to a Whisper /128 at manufacture and that difference collapses into a one-line network check anyone in the supply chain can run, plus a single revoke that blacklists a burned key worldwide.

Boundary. This complements the secure element / 802.1AR IDevID already in the part. It does not replace the chip. It makes the chip's identity network-verifiable and instantly revocable, with no air interface and no plug involved.

At manufacture, the part's secure-element public SPKI plus its part serial (the ecu_serial/device slot) derive its /128, DANE-pinned and RDAP-registered, using the same shared primitive above. From then on, the genuine part proves its identity and the counterfeit simply can't:

# Genuine part: a registered, DANE-anchored identity. It proves itself:
curl -s https://whisper.online/verify-identity/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
{"is_whisper_agent":true,"dane_ok":true,"jws_ok":true, …}

# Counterfeit: no registered /128 for its key, no DANE pin it can present.
# The public surface says so plainly, no account required:
curl -s https://whisper.online/verify-identity/2a04:2a01::1
{"is_whisper_agent":false,
 "detail":"no Whisper agent identity anchors this address"}

A distributor, a service centre, or a downstream integrator confirms genuineness with that one call (or an RDAP lookup for the assignment record), and never has to phone home to the OEM or hold a shared secret:

curl -s https://whisper.online/ip/2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
# RDAP: the DNSSEC-anchored assignment record for the genuine part's /128

One revoke, blacklisted worldwide

When a part is flagged counterfeit, a key is burned, or a vehicle is decommissioned or compromised, a single control-plane call tears down its /128, its PTR, and its DANE pin everywhere at once, bounded only by DNS TTL. No CRL to distribute, no per-vendor blocklist to push, no fleet-wide firmware flash:

# Kill an identity worldwide. Every keyless check above starts returning "not a
# Whisper identity" within the DNS TTL. No coordination, no distribution list.
curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.agents({op:'"'"'revoke'"'"', args:{agent:'"'"'2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4'"'"'}})"}'

# With the CLI, the same teardown is one verb:
whisper kill --revoke 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4

After that, Recipe 3's genuine-part check flips to is_whisper_agent:false for that address everywhere on the planet: the same negative result a counterfeit gets. Revocation and counterfeit-detection are, deliberately, the same mechanism.

Attribution: which fleet, which destinations (keyed)

The three recipes above need no key. If you hold one, the same public API answers a deeper question: the attribution graph. Passing an address to whisper.identify over POST https://graph.whisper.security/api/query returns what the graph knows about it (tenant/fleet, origins, history) as read-only Cypher:

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(\"2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4\")"}' | jq .

This is the graph API, not a CLI subcommand: there is no whisper identify verb; the call above is the interface. It feeds a UNECE R155 vehicle SOC: which destinations a fleet's telematics units resolve, OTA-CDN reputation, an ECU beaconing somewhere it shouldn't.

Where each recipe stops (and what's roadmap)

Honest scoping, one row per recipe. Whisper anchors the cloud/IP boundary; the safety, update-integrity, and charging layers stay exactly where they are.

RecipeComplementsDoes not touch / replace
Roadside & back-office SCMS / IEEE 1609.2 on the air interface the PC5 / DSRC / C-V2X safety channel; no pseudonym certs issued
Bidirectional OTA Uptane, UNECE R156 SUMS firmware image signing, which stays with your update framework
Anti-counterfeit part the secure element / 802.1AR IDevID in the part the chip itself, SecOC, and the ISO 15118 charging handshake

Roadmap, clearly labelled. Streaming this evidence into a SIEM ships today for Splunk, Microsoft Sentinel and OpenCTI. A STIX/TAXII feed and an Auto-ISAC ATM JSON export for sharing revocation and attribution evidence are proposed, not yet available. And the --vin CLI flag is roadmap: provision vehicles via the control-plane API shown above, which is live. Nothing on this list is required for the three recipes; they run on shipped primitives alone.

Next