What ETSI TS 103 097 specifies
TS 103 097 is the wire-level cryptographic contract for C-ITS. It defines:
- The certificate format: Explicit vs Implicit ECC certs, COER-encoded, with a strictly enumerated set of subject attributes (PSIDs allowed to sign, SSPs constraining each PSID, geographic validity region, time validity window).
- SignedData: the wrapper that surrounds every signed application message (CAM, DENM, CPM, signed EC/AT requests). It carries the signer reference (digest, hashedId8 or certificate-by-value), the signature, and the payload.
- EncryptedData: the wrapper used for confidentiality-bearing payloads, notably the inner enrolment and authorization requests of TS 102 941.
- Header fields: generationTime, expiryTime, generationLocation, the signer identifier and the PSID/SSP claim used to authorize the message.
The spec builds on IEEE 1609.2 cryptographic primitives. Where 1609.2 defines how you sign with ECDSA on a given curve, TS 103 097 defines what a signed CAM looks like on the wire and what its issuer cert looks like.
Explicit vs implicit certificates
TS 103 097 inherits two cert flavours from 1609.2.
Explicit certs
The public key sits directly in the cert body, as a PublicVerificationKey CHOICE holding the curve and the encoded point. Verification is the plain ECDSA flow. Hash the to-be-signed bytes, run ecdsa-verify with the carried key, accept or reject.
Implicit certs
The cert body carries a reconstructionValue instead of a key. The verifier derives the actual public key by combining that value with the issuer's public key, an ECQV (Elliptic Curve Qu-Vanstone) reconstruction. Implicit certs are smaller on the wire, a single point rather than a full pubkey, at the cost of one reconstruction step before any signature can be verified.
Castell issues Explicit only. Implicit is not implemented, a deliberate scope choice. Explicit certs cover the integrator workflows the testbed serves, and implicit reconstruction adds real complexity for marginal wire savings. It also sidesteps the IEEE 1609.2 P-384 implicit constraint, covered on the multi-curve page.
How Castell signs to TS 103 097
Wire version
Castell declares conformance to TS 103 097 v1.3.1 cert format COER. v1.3.1 is the wire-stable cert encoding the deployed ITS-G5 ecosystem produces today. Newer versions (v2.1.1, v2.2.1) add fields and CHOICE entries while staying backward compatible with the v1.3.1 subset. Pinning to v1.3.1 lets anything in the wild parse Castell's certs without spec version negotiation.
What gets signed
Every artefact Castell publishes is signed end-to-end:
- Root CA cert at
/trustanchor: Explicit, self-signed under the Root CA's own key. - TLM cert at
/tlm: Explicit, self-signed under the TLM's own key (TS 102 940 §6.2.4). - MA cert at
/ma: Explicit, signed by the Root CA. - EC and AT certs issued via
POST /ec-requestandPOST /at-request: Explicit, signed by the EA and AA respectively. - The ECTL at
/getectl: wrapped in SignedData with the TLM as signer.
PSID and SSP: what each cert can sign
Every cert carries an appPermissions field. It enumerates the PSIDs (Provider Service Identifiers) the cert may claim, each with an SSP (Service-Specific Permissions) that constrains what the cert can do within that PSID. A signed CAM must reference a PSID the signing cert holds permission for. Receivers reject signatures whose PSID isn't covered.
Castell's AT-2 release (v0.6.1, see changelog) widened the AA's certIssue permission set to cover every Day-1 service (CAM, DENM, SPATEM, MAPEM, IVIM, SREM, SSEM, VAM, CPM, GN-MGMT). A stack running VAM (PSID 638), for one, can now request an AT from Castell without tripping strict subset-chain validation.
generationTime and the freshness window
Every signed message carries generationTime. A receiver rejects signatures whose generationTime falls outside an acceptable window from local time, typically ±5 minutes. Castell enforces this on incoming requests too. See Castell v0.8.3 in the changelog for the default window and the rationale.
Decoding TS 103 097 messages
Castell exposes two debug endpoints that parse incoming TS 103 097 wire bytes and return their structure as JSON. They are public on purpose, so any integrator can check what their stack produces:
# Decode an EC request you just built — see what the wire looks like
curl -X POST https://pki.skyv2x.com/v221/ec-request-decode \
-H 'Content-Type: application/octet-stream' \
--data-binary @your-ec-request.coer
# Same for AT request (v2.2.1 strict decode)
curl -X POST https://pki.skyv2x.com/v221/at-request-decode \
-H 'Content-Type: application/octet-stream' \
--data-binary @your-at-request.coer
The decoded JSON shows every CHOICE tag, every option field, the signer reference and the PSIDs/SSPs the signing cert holds. It's the fastest way to debug a v2.2.1 conformance failure without standing up your own parser.
Related material
- ETSI TS 102 941: the trust management protocol that uses these cert and message formats.
- Multi-curve support: which ECC curves Castell accepts in the
PublicVerificationKeyCHOICE. - Trust anchors: the explicit Root CA, TLM and MA certs all conform to this format.
- Integration walkthrough: end-to-end EC + AT + sign-a-CAM showing the wire shape live.