# 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](/docs/dane) 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](/docs/verify) / RDAP surface, and one-call [revoke](/docs/control-plane) 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](https://1.ieee802.org/security/802-1ar/), 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:

- **Deterministic & idempotent:** the same key + VIN always yields the same `/128`. Re-provisioning a replacement head unit for the same VIN returns the same address; there's no registry to keep in sync.
- **Tenant-bound & fleet-unlinkable:** the derivation folds in your tenant, so an outsider deriving under a different tenant gets a *different* address. The same key+VIN isn't linkable across fleets by suffix, and there's no enumeration oracle.
- **Forge-proof:** the `/128` is [DANE-EE `3 1 1`](/docs/dane)-pinned to that device's key and has DNSSEC-signed reverse DNS. A cloned device with a different key derives a different address and can't present the pinned key.
- **Revocable worldwide:** one control-plane call tears the `/128`, its PTR, and its DANE pin down everywhere at DNS-TTL speed.

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:

```bash
# 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'}
```

> 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](https://standards.ieee.org/ieee/1609.2/10258/) 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:

```bash
# 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:

```bash
# 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:

```bash
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](https://uptane.org/), 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:

```bash
# 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:

```bash
# 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*:

```bash
# 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](/docs/rdap) lookup for the assignment record), and never has to phone home to the OEM or hold a shared secret:

```bash
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:

```bash
# 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:

```bash
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.

| Recipe | Complements | Does *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

- [Vehicle & ECU identity](/docs/industries/auto/vehicle-identity): the full derivation the `/128` above comes from, key + VIN to address
- [DANE & TLSA](/docs/dane): the `3 1 1` pin every check here rests on, byte for byte
- [Verify an agent](/docs/verify): the full keyless proof chain `whisper verify --trustless` walks
- [R155 · ISO 21434 · ATM](/docs/industries/auto/automotive-compliance): where these recipes map into type-approval evidence
