Ads.cert 2.0 Call Signs and Authenticated Connections: Securing Server-to-Server CTV Inventory
In an OpenRTB 2.6 server-to-server (S2S) auction, every identity attribute inside the JSON payload, including app.bundle, device.ip, device.ua, and the

In an OpenRTB 2.6 server-to-server (S2S) auction, every identity attribute inside the JSON payload, including app.bundle, device.ip, device.ua, and the source.ext.schain node array, is transmitted as unverified plain text over hop-by-hop TLS connections. While TLS 1.3 enforces transport encryption between immediate network peers, it provides zero cryptographic proof that the upstream server initiating a Connected TV (CTV) ad request actually operates on behalf of the publisher or Server-Side Ad Insertion (SSAI) platform declared in the payload. When a tier-1 DSP receives a bid request claiming to originate from a premium streaming application on Roku OS, Samsung Tizen, or Apple tvOS, standard transport security cannot confirm whether that packet was generated by an authorized SSAI stitcher or fabricated by a data-center spoofing cluster.
Static authorization frameworks such as app-ads.txt and sellers.json solved the directory lookup problem by allowing buyers to verify which exchange accounts are permitted to sell a publisher's inventory. However, these text and JSON manifests are passive public ledgers. Any malicious intermediary can scrape a publisher's app-ads.txt file, copy a legitimate SupplyChain (schain) path, and inject those exact strings into synthetic S2S bid requests. Closing this authentication gap in CTV and mobile app environments requires binding every HTTP transaction to a verifiable cryptographic identity at line rate.
Why IP and Domain Headers Are Easily Spoofed in S2S Bidding
In traditional client-side web header bidding, the user's browser establishes a direct TLS connection to each supply-side platform endpoint. The Chromium or WebKit networking stack enforces the Origin and Referer HTTP headers, and the TCP socket exposes the residential or cellular IP address of the end-user device directly to the receiving server. Spoofing client-side web traffic at scale requires either controlling a residential proxy botnet or compromising client-side JavaScript execution environments.
Server-to-server CTV architectures dismantle these implicit browser guarantees. To deliver a seamless, television-grade viewing experience without client-side buffering or codec mismatches, streaming publishers rely on SSAI stitchers and server-side bidding wrappers such as Prebid Server. When a viewer reaches an ad break marker (EXT-X-CUE-OUT in HLS or an SCTE-35 splice info section in MPEG-DASH), the media player does not call ad exchanges directly. Instead, the cloud-hosted SSAI stitcher initiates outbound S2S HTTP requests to participating monetization partners.
Because the TCP connection terminates at the SSAI provider's cloud egress gateway rather than the household smart TV, the receiving ad platform sees a data-center source IP address (for example, an AWS or Google Cloud subnet) rather than the viewer's residential IP. To pass targeting and fraud-verification signals downstream, the SSAI platform populates forwarding headers and OpenRTB fields manually:
- Forwarded IP Headers: The originating smart TV IP address is passed inside
X-Forwarded-FororX-Device-IPHTTP headers and mirrored in the OpenRTBdevice.ipordevice.ipv6fields. - User-Agent Forwarding: The hardware user-agent string (such as
Roku/DVP-12.5orAppleTV14,1/17.4) is injected viaX-Device-User-Agentand written todevice.ua. - Application and Supply Path Metadata: The streaming channel identifier (
app.bundle,app.storeurl) and thesource.ext.schainobject are serialized into the request body by each hop in the auction chain.
Without cryptographic message authentication, none of these headers or JSON attributes are tamper-resistant. A compromised intermediary or fraudulent S2S proxy can harvest legitimate residential IP ranges and CTV user-agent strings, construct valid OpenRTB 2.6 JSON payloads, and replay legitimate schain trajectories toward downstream buyers. Even when an exchange audits static supply paths against its published sellers.json and enforces strict HUMAN and Pixalate pre-bid Invalid Traffic (IVT) filtering, verifying the origin of every individual S2S request requires cryptographic signing at the transport and application layers.
Cryptographic Call Signs: How ads.cert 2.0 Works
Early industry attempts to sign OpenRTB payloads (specifically ads.cert 1.0) relied on asymmetric public-key signatures calculated per bid request over selective JSON fields. That approach proved computationally prohibitive at scale: executing elliptic-curve digital signature algorithms (ECDSA) on every outbound request across high fan-out auctions saturated CPU cores and introduced unacceptable auction latency. Furthermore, signing only a subset of OpenRTB fields failed to secure downstream VAST 4.3 XML fetches and impression measurement beacons.
To solve both the computational bottleneck and the protocol coverage gap, the IAB Tech Lab ads.cert 2.0 specification comprises two core protocols: ads.cert Call Signs (decentralized DNS publication of cryptographic public keys to establish corporate identity) and ads.cert Authenticated Connections (origin authentication and tamper-resistance for S2S HTTP bid requests, creative fetches, and impression pings).
Rather than running an expensive asymmetric signature operation on every single HTTP request, ads.cert 2.0 separates identity discovery from per-request message authentication. Participating platforms publish their static public keys in the Domain Name System (DNS). Counterparties discover these keys asynchronously, perform an elliptic-curve Diffie-Hellman (X25519) key agreement to establish a shared symmetric secret in memory, and then use fast symmetric Hashed Message Authentication Codes (HMAC-SHA256) to sign individual HTTP requests in flight.
Publishing Public Keys via DNS Records for Counterparty Discovery
The Call Signs protocol uses existing DNS authority (ideally hardened with DNSSEC) instead of relying on a centralized certificate authority that could become a single point of failure. Each participating entity in the programmatic supply chain, including the SSAI provider, the SSP infrastructure, and the receiving DSP, publishes its X25519 public keys as DNS TXT records under the _adscert subdomain of its corporate root domain.
For platforms that segregate their bidding infrastructure from their creative delivery and measurement infrastructure, ads.cert 2.0 supports sub-scoped DNS records such as _delivery._adscert.<domain> alongside the primary _adscert.<domain> record. During key rotation, an operator publishes both its active primary key and its upcoming standby key within the same DNS record set so counterparties can synchronize the new public key before it begins signing live traffic:
; Primary ads.cert 2.0 Call Sign record for SSP bidding endpoints
_adscert.skyboosts.com. 3600 IN TXT "v=adsc2; k=x25519; h=sha256; p=K8p9mX2vL4qR7wN1zB5tY8cE3fG6hJ0kM9nP2sV5xZ8="
; Delivery-scoped Call Sign record for VAST 4.3 SSAI and impression beacons
_delivery._adscert.skyboosts.com. 3600 IN TXT "v=adsc2; a=delivery01.skyboosts.com; k=x25519; h=sha256; p=R4t7yU0iO3pA6sD9fG2hJ5kL8zX1cV4bN7mQ0wE3rT6="
In this DNS record format, v=adsc2 declares the protocol version, k=x25519 specifies the Curve25519 key exchange algorithm, h=sha256 defines the hashing algorithm used for key derivation and message digests, and p= contains the base64url-encoded 32-byte public key. Background workers inside each platform poll and cache these DNS records according to their Time-To-Live (TTL) values, mapping every counterparty's root domain (which matches the domain field in sellers.json and schain nodes) to its verified public key ring.
Authenticated Connections: X25519 Key Exchange and Per-Request HMAC Signing
Once two programmatic counterparties have resolved each other's public keys via DNS Call Signs, they establish an Authenticated Connection without requiring an interactive TLS-style handshake on the critical bidding path. Using the mathematical properties of Curve25519, the sending party combines its local 32-byte private key with the receiving party's 32-byte DNS public key (ECDH(private_sender, public_receiver)), while the receiving party combines its local private key with the sender's DNS public key (ECDH(private_receiver, public_sender)). Both operations yield the exact same 32-byte shared secret. That raw shared secret is then passed through an HMAC-based Extract-and-Expand Key Derivation Function (HKDF-SHA256) to generate a directional symmetric signing key.
For every outbound OpenRTB 2.6 bid request, VAST 4.3 creative fetch, or SSAI impression ping, the sender calculates a SHA-256 digest of the HTTP request body and the destination URL path. It then constructs an X-Ads-Cert-Auth HTTP header containing the protocol version, key identifiers, a UTC timestamp (ts), a random nonce to prevent replay attacks, truncated base64url digests of the body (bd) and URL (ud), and the resulting HMAC-SHA256 signature (sig):
package adscert
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/http"
"time"
)
func SignOpenRTBRequest(req *http.Request, body []byte, sharedKey []byte, fromCallSign, toCallSign, nonce string) {
bodyHash := sha256.Sum256(body)
urlHash := sha256.Sum256([]byte(req.URL.String()))
bd := base64.RawURLEncoding.EncodeToString(bodyHash[:16])
ud := base64.RawURLEncoding.EncodeToString(urlHash[:16])
ts := time.Now().UTC().Format("060102T150405")
message := fmt.Sprintf("v=adsc2;from=%s;to=%s;ts=%s;nonce=%s;bd=%s;ud=%s",
fromCallSign, toCallSign, ts, nonce, bd, ud)
mac := hmac.New(sha256.New, sharedKey)
mac.Write([]byte(message))
sig := base64.RawURLEncoding.EncodeToString(mac.Sum(nil)[:16])
req.Header.Set("X-Ads-Cert-Auth", fmt.Sprintf("%s;sig=%s", message, sig))
}
When the receiving DSP ingests the bid request, it looks up the cached symmetric key for the from Call Sign, recomputes the SHA-256 digests of the incoming HTTP payload and request URI, and validates the sig value in constant time. If any intermediary alters the app.bundle, mutates the device.ip, strips a floor price, or tampers with the schain array in transit, the bd digest and HMAC signature fail verification immediately.
Performance Impact of Cryptographic Signing at High QPS
Deploying cryptographic verification across a global CTV monetization platform requires strict latency discipline. In a server-side auction with a 150-millisecond total timeout budget, an exchange handling 200,000 inbound QPS with a 25x DSP fan-out generates 5,000,000 outbound HTTP requests per second. If cryptographic signing adds even 50 microseconds of CPU time per outbound request, an exchange would burn 250 CPU cores per cluster solely on header generation.
Because ads.cert 2.0 offloads the asymmetric X25519 scalar multiplication to an asynchronous background cache that refreshes only when DNS keys rotate, the hot-path per-request operations consist solely of SHA-256 hashing and HMAC-SHA256 generation. On modern x86_64 processors equipped with Intel SHA Extensions (SHA-NI) or ARM64 Neoverse cores with Cryptography Extensions, hashing a typical 4 KB OpenRTB 2.6 CTV payload takes approximately 1.2 microseconds, and computing the 64-byte HMAC-SHA256 tag takes less than 0.4 microseconds.
To minimize CPU utilization and garbage collection pressure during peak live-sports CTV traffic spikes, production ad servers should implement three architectural optimizations:
- Single-Pass Body Digest Reuse Across Fan-Out: When an exchange serializes an OpenRTB 2.6 bid request for 20 downstream DSPs that share an identical request payload, the server should compute the SHA-256 body digest (
bd) once per auction rather than once per DSP. The pre-computedbdstring is then passed into the per-DSP signing loop, where only the lightweight URL digest (ud) and the counterparty-specific HMAC signature (sig) are calculated. - Lock-Free In-Memory Key Ring Caching: Derived HKDF symmetric keys should be stored in a read-optimized, lock-free atomic lookup table indexed by the counterparty's
todomain and active key ID, eliminating mutex contention across thousands of concurrent Go routines or worker threads. - Zero-Allocation Header Formatting: Pre-allocating fixed-size byte buffers from a memory pool (
sync.Poolin Go or thread-local arenas in C++ and Rust) for formatting theX-Ads-Cert-Authstring prevents heap escapes and keeps p99 signing latency under 2 microseconds per outbound bid request.
By combining DNS-anchored X25519 key discovery with hardware-accelerated symmetric HMAC signing, engineering teams can cryptographically authenticate every CTV bid request, VAST 4.3 tag fetch, and SSAI impression beacon without degrading auction timeouts or inflating compute infrastructure costs.