# Device & IDevID identity

**Give a device a routable IPv6 `/128` derived from the IEEE 802.1AR IDevID key it already holds and its serial. The address *is* the device: forge-proof, tenant-private, DNSSEC-anchored, and revocable by the owner in one publicly verifiable call.**

This is the spine of the embedded vertical, and it is **shipped and live**. Everything else (the passwordless-auth story, the platform integrations, the compliance evidence) builds on the one idea below: a device's network address stops being a disposable label a proxy can rotate and becomes a cryptographic fact only that device's silicon can stand behind.

> Two tiers, per Postel's Law. **With no API key** anyone, including the customer who owns the device, 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 device

Almost every device backend authenticates a *claim*, never a *device*. A bearer token, a static API-key header, a certificate chain: each says "the holder of this artifact may act," and an artifact travels. It can be dumped over UART or JTAG, lifted from a firmware image, and presented from any IP on earth. That is the root cause behind the whole family of device-fleet abuses: fleet-scale impersonation, poisoned telemetry, BOLA, one operator quietly wearing thousands of copied faces from a residential-proxy swarm.

Whisper closes the gap by making the **network address itself the credential**. A device 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 serial. Because the address is *derived from* a key only that device holds, you cannot present a device identity whose key you don't have.

The key already has a name in your architecture documents: the **802.1AR IDevID**, the initial device identifier your secure element (ATECC608, SE050, OPTIGA Trust M) or on-chip OTP/PUF storage was put on the board to hold. BRSKI (RFC 8995) bootstraps that IDevID into an owner relationship; Whisper projects the same key onto the public namespace, where anyone can check it.

## 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 device already has:

| Input | What it is | Where it lives |
|---|---|---|
| **Device public key** | the `SubjectPublicKeyInfo` (SPKI) of the key the device was born with: the 802.1AR IDevID key in the secure element or OTP | the **public** half is submitted; the private key **never leaves the device** |
| **Device identifier** *(optional)* | a canonical identifier as the domain separator. Today this rides the live `device_id` argument, held to **17 characters** in the VIN alphabet (`A-H J-N P R-Z 0-9`; the same shipped derivation the automotive vertical uses). A variable-length `serial`/EUI-64 form is **roadmap**. | submitted with the request; the public index |
| **Component serial** *(optional)* | a per-component separator (`ecu_serial`: free-form printable US-ASCII), so one device can hold many addressable identities | optional; omit it for a single per-device address |

```
# inputs -> a stable, forge-proof interface identifier
derive( device public key,  device_id [, component 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:

- **Deterministic.** The same `(key, id)` yields a byte-identical `/128` every time, on every server. A reconnecting device re-derives its own address; both authoritative nodes mint the identical identity with zero replication between them.
- **Forge-proof.** The address is a function of a key only the device holds, and the device's proof is a signature only the chip can make.
- **Tenant-bound & fleet-unlinkable.** The same key+id under a *different* tenant produces a *different* address; the classic serial-enumeration walk is a dead end.
- **Liberal in, strict out.** The identifier is accepted generously, then held to its canonical form. A malformed identifier fails closed with a clear message, never a silent wrong address.

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](/docs/rdap). See [DANE & TLSA](/docs/dane) and [DNSSEC](/docs/dnssec).

> **The private key never moves.** The device submits only its public SPKI. The server derives a public *address* from public inputs plus a server-side secret; it never sees, holds, or derives the device's private key.

## Provision a device identity

One control-plane call: `whisper.agents` with `op:'connect'`, `tier:'wireguard'`, the device's public SPKI, and optionally the device identifier. 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>',
  device_id:           'GW00427A310B55EF2'   // optional: the 17-character device identifier rides here today
  // ecu_serial: 'MOD-7F31'   // optional: a distinct /128 per sub-module
}}) YIELD op, ok, status, result, error
   RETURN op, ok, status, result, error
```

**With stock tools:** just `curl`, no Whisper software:

```sh
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>...', device_id:'GW00427A310B55EF2'}}) YIELD op, ok, status, result, error RETURN op, ok, status, result, error"}
JSON
```

The response carries the derived address and the transport. Because the device holds its own key, no private key is ever returned:

```
{
  "op": "connect", "ok": true, "status": 200,
  "result": {
    "tier":              "wireguard",
    "address":           "2a04:2a01:e5a7:41c9:04d0:c85f:3a1b:77e2",
    "fqdn":              "04d0c85f3a1b77e2.<tenant>.agents.whisper.online",
    "server_public_key": "…",
    "endpoint":          "…:51820",
    "dns":               "2a04:2a01:0:53::53",
    "wireguard_config":  "[Interface] …"
  },
  "error": null
}
```

On an embedded-Linux device or gateway, drop the returned `wireguard_config` in place (or feed it to `wireproxy` for a no-root, userspace tunnel) and every packet it sends now sources from its own `/128`. See [Connect & egress](/docs/connect) and the [Control plane](/docs/control-plane) reference.

> The `whisper` CLI ships `create --register`, `verify --trustless`, `policy`, `logs`, and `kill --revoke`. A dedicated `--serial` flag is **on the roadmap, not shipped**. Provision devices today via the control-plane call above, which is live.

## Idempotent, with honest errors

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

## Verify: keyless, no account

Four independent checks; the first three need nothing but a TLS-capable HTTP client, which is exactly what makes them reachable from most embedded systems today:

```sh
# 1. Forward-confirmed reverse DNS
dig -x 2a04:2a01:e5a7:41c9:04d0:c85f:3a1b:77e2 +short
04d0c85f3a1b77e2.<tenant>.agents.whisper.online.

# 2. The keyless verdict endpoint (address or FQDN; ?ip=<target> also accepted)
curl -s https://whisper.online/verify-identity/2a04:2a01:e5a7:41c9:04d0:c85f:3a1b:77e2 | jq .
{ "is_whisper_agent": true, "dane_ok": true, "jws_ok": true, "evidence": { … } }

# 3. The registry record: RDAP, IP-anchored to the /128
curl -s https://whisper.online/ip/2a04:2a01:e5a7:41c9:04d0:c85f:3a1b:77e2 | jq '.handle, .parentHandle'

# 4. The full chain re-derived on YOUR machine, against the IANA root
whisper verify --trustless 04d0c85f3a1b77e2.<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. The full seven-proof walk lives in [Verify an agent](/docs/verify).

## Revoke: worldwide, owner-thrown, in one call

```
CALL whisper.agents({op:'revoke', args:{agent:'2a04:2a01:e5a7:41c9:04d0:c85f:3a1b:77e2'}})

# prove it, zero Whisper software:
dig -x 2a04:2a01:e5a7:41c9:04d0:c85f:3a1b:77e2 +short           # -> nothing
curl -s https://whisper.online/verify-identity/2a04:2a01:e5a7:41c9:04d0:c85f:3a1b:77e2
# -> {"is_whisper_agent": false, ...}
```

Compare the alternatives an embedded fleet actually has: a CRL that most verifiers soft-fail past, or a shared-secret rotation that means a recall-grade OTA campaign. On resale or RMA, one `revoke` plus a re-register under the new owner moves the trust relationship with the title.

## Where this fits (and where it doesn't)

- **Secure element / TPM / OTP.** The device's birth key is the *input* to the derivation. Whisper complements the silicon root of trust; it does not replace it.
- **802.1AR / BRSKI.** The IDevID stays the initial device identifier; BRSKI stays the onboarding ceremony. The derived `/128` is the same identity's public, internet-facing counterpart.
- **Cloud DPS / device clouds.** Whisper adds an *out-of-tenancy* identity any third party can verify against DANE without cross-signing. It complements the vendor CA.
- **Where Whisper does not go.** Not into secure boot, not into the RTOS, not into a radio protocol's own security layer (Matter fabric credentials, LoRaWAN OTAA, Thread).

For the compliance mapping see [Embedded compliance](/docs/industries/embed/embedded-compliance). No specific vendor or platform is named, endorsed, or implicated as a breach victim anywhere in these docs.

## Next

- [Passwordless device auth](/docs/industries/embed/device-secret-cure): this identity, applied as the DANCE-style TLS client credential it was built to be
- [Platform integrations](/docs/industries/embed/embedded-integrations): dropping the `/128` into cloud DPS, Matter, MQTT, LPWAN
- [DANE & TLSA](/docs/dane): the byte-for-byte record that makes the address provable against the device key
