Please visit https://iabtechlab.com/ads-cert for more information about the ads.cert 2.0 suite of protocols.
Please review the IAB Tech Lab Open Source Initiative Governance guidelines here for contributing to this project.
This is a proof of concept and not meant for use in its current form.
This open-source library implements the Authenticated Connections protocol, published by IAB Tech Lab let advertising industry participants secure programmatic ad buying and selling using industry-standard cryptographic security protocols.
Authenticated Connections uses a standardized HTTP request header containing a signature that secures:
- URL being invoked
- Body of POST requests
- Timestamp, origin, and destination values
The signature and these factors show that the request came from the originator as claimed and hasn't been tampered with. The request header looks like the following:
X-Ads-Cert-Auth:
from=ssai-serving.tk&from_key=w8f316&invoking=ad-exchange.tk&nonce=u_sDzKMIp0eD&status=0×tamp=210519T174337&to=exchange-holding-company.ga&to_key=bBvfZU; sigb=t1TupK6wn8pn&sigu=FQ5OQ6TmF2xU
Field | Description |
---|---|
from | The domain of the party sending the request |
from_key | The first 6 characters of the sending party’s public key |
invoking | The domain for the URL hostname being invoked |
nonce | Randomly generated number from the sending party in base64 encoded. |
timestamp | The time of generating signature in format: YYMMDDTHHMMSS. This should be in UTC. |
to | The domain of the party receiving the signature |
to_key | The first 6 characters of the receiving party’s public key |
sigb | The signature over the message and body of the request |
sigu | The signature over the message, body, and URL of the request |
- Signatory`- Main library that handles signing and verification operations.
- Dns Resolver - Discovers TXT records for a domain name (with the appropriate subdomains for policy and key records)
- Domain Store - Stores domain information for invoking and identity domains and the associated keys
- Domain Indexer - Uses the above components to maintain a list of domains used in signing/verification operations, runs background crawls to update domain records, stores private keys, calculates shared secrets for use by the Signatory.
The Signatory
is available as a standalone GRPC server. See the GRPC/Protobuf interface for the full API details. The main function defintions are below:
rpc SignAuthenticatedConnection(AuthenticatedConnectionSignatureRequest) returns (AuthenticatedConnectionSignatureResponse) {}
rpc VerifyAuthenticatedConnection(AuthenticatedConnectionVerificationRequest) returns (AuthenticatedConnectionVerificationResponse) {}
Clients are available for various langauges:
- Golang - GRPC client available here or the Signatory can be use as an in-process Go library directly.
- Java - Coming soon...
- C++ - Coming soon...
The Signatory
can be run from inside a Docker container:
$ make build-grpc-server-container
$ docker run -p 3000:3000 -p 3001:3001 adscert:latest --origin publica-ssai.com --private_key "${ADSCERT_SECRET}"
--host_callsign is the domain of the verifying server
In this example we use exchange-holding-company.ga which is leveraged in this insecure example to generate a consistent private key.
Note: The private key generated here should never be used in a production environment. This is for demo purposes only.
Its corresponding public key can be found by looking it up
dig TXT _delivery._adscert.exchange-holding-company.ga
TXT "v=adcrtd k=x25519 h=sha256 p=bBvfZUTPDGIFiOq-WivBoOEYWM5mA1kaEfpDaoYtfHg"
Start the verifying server
go run examples/verifier/server/verifier-server.go --host_callsign=exchange-holding-company.ga --logtostderr
The signer willl periodically send requests to the verifying server.
--origin-callsign is the domain of the signer.
Like above, we use the domain to generate an inconsistent consistent private key for ssai-serving.tk
--url is the full url that we wish to send a signed request too. This gets signed along with the --body in the request.
In this example we use ads.ad-exchange.tk which is not exchange-holding-company.ga. We can see the link between the two based on the TXT records.
dig TXT _adscert.ad-exchange.tk
TXT "v=adpf a=exchange-holding-company.ga"
dig TXT _delivery._adscert.exchange-holding-company.ga
TXT "v=adcrtd k=x25519 h=sha256 p=bBvfZUTPDGIFiOq-WivBoOEYWM5mA1kaEfpDaoYtfHg"
Start the signing server in a second shell.
go run examples/signer/example-signer.go --frequency 5s --logtostderr --body '{"sample": "request"}' --origin_callsign=ssai-serving.tk --url='http://ads.ad-exchange.tk:8090/request?param1=example¶m2=another' --send_requests
The two services will output log to stderr
Alternatively, you can start the signing server to periodically log the invocating url, signature, hashed url, and hashed request to a log file that can be verified offline.
Start the signing server to log to signature_log_file path.
go run examples/signer/example-signer.go --frequency 1s --logtostderr --body '{"sample": "request"}' --origin_callsign=ssai-serving.tk --url='http://ads.ad-exchange.tk:8090/request?param1=example¶m2=another' --signature_log_file=requests.log
The log parser verifier will verify all entries in the log file and output a summary.
go run examples/verifier/log-parser/verifier-parser.go --origin_callsign=ssai-serving.tk --host_callsign=exchange-holding-company.ga --logtostderr --signature_log_file=requests.log
./pkg/adscert/logger
directory holds global logger interface along with a standard_golang_logger
implementation which is being used as default logger. Default log level is INFO. Using the SetLoggerImpl()
method in ./pkg/adscert/logger/logger.go
interface you can implement any custom logger and set it as global logger in your application.
You can add custom workflows and github actions to .github/workflows
folder. Currently go.yml
includes the build and release steps including creating and pushing a new tag. A new release and tag only gets created only on main branch and push event.
More info.
Report bugs, request features and suggest improvements on Github
Or open up a pull request