When your creative wins an auction, Google can inform you what the winning
price was if the creative includes the `${AUCTION_PRICE}` macro.

When the macro is expanded, it returns the winning price in an encrypted
form. It can be included in a creative, for example, with an invisible pixel
request rendered as part of the ad:

```
<div>
  <script language='JavaScript1.1' src='https://example.com?creativeID=5837243'/>
  <img src='https://example.com/t.gif?price=${AUCTION_PRICE}' width='1' height='1'/>
</div>
```

The `${AUCTION_PRICE}` macro can also be included in the VAST URL of
a video creative, but not in the impression URL in the VAST:

```
https://example.com/vast/v?price=${AUCTION_PRICE}
```

## Scenario

1. Your OpenRTB bidding application includes the `${AUCTION_PRICE}` macro in the HTML snippet or VAST URL it returns to Google.
2. Google substitutes the winning price for the macro in unpadded web-safe base64 encoding ([RFC 3548](https://tools.ietf.org/html/rfc3548)).
3. The snippet passes the confirmation in the format you have chosen. For example, the confirmation might be passed in the URL of an invisible pixel request rendered as part of the ad.
4. On the server, your application web-safe base64 decodes the winning price information and decrypts the result.

## Dependencies

You will need a crypto library that supports SHA-1 HMAC, such as
Openssl.

## Sample code

Sample code is provided in Java and C++ and can be downloaded from the [privatedatacommunicationprotocol
project](https://code.google.com/p/privatedatacommunicationprotocol).

- The Java sample code uses the base64 decoder from the [Apache
  commons project](https://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html). You will not need to download the Apache commons code,
  as the reference implementation includes the necessary part and is therefore
  self-contained.

- The C++ sample code uses the [OpenSSL
  base64 BIO method](https://www.openssl.org/docs/man1.1.0/crypto/BIO_f_base64.html). It takes a web-safe base64 encoded string ([RFC 3548](https://tools.ietf.org/html/rfc3548)) and decodes it.
  Normally, web-safe base64 strings replace "=" padding with "." (note that
  quotation marks are added for reading clarity and are not included in the
  protocol) but the macro substitution does not pad the encrypted price. The
  reference implementation adds padding because OpenSSL has trouble with
  unpadded strings.

## Encoding

Winning price encryption and decryption requires two secret, but shared,
keys. An integrity key, and encryption key, referred to as `i_key`,
and `e_key` respectively. Both keys are provided at account setup as
web-safe base64 strings, and can be found on the Authorized Buyers page
under [**Bidder
settings \> RTB settings \> Encryption keys**](https://support.google.com/authorizedbuyers/answer/10858928).

Example integrity and encryption keys:

```
skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=  // Encryption key (e_key)
arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=  // Integrity key (i_key)
```

Keys should be web-safe decoded and then base64 decoded by your
application:

```
e_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=')
i_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')
```

## Encryption scheme

The price is encrypted using a custom encryption scheme that is designed to
minimize size overhead while ensuring adequate security. The encryption scheme
uses a keyed HMAC algorithm to generate a secret pad based on the unique
impression event ID.

The encrypted price has a fixed length of 28 bytes. It is comprised of a
16-byte initialization vector, 8 bytes of ciphertext, and a 4-byte integrity
signature. The encrypted price is web-safe base64-encoded, according to RFC
3548, with padding characters omitted. Thus, the 28-byte encrypted price is
encoded as a 38 character web-safe base-64 string irrespective of the winning
price paid.

Example encrypted prices:

```
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw  // 100 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA  // 1900 CPI micros
YWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw  // 2700 CPI micros
```

The encrypted format is:

```
{initialization_vector (16 bytes)}{encrypted_price (8 bytes)}
{integrity (4 bytes)}
```

The price is encrypted as `<price xor HMAC(encryption_key,
initialization_vector)>` so decryption calculates
`HMAC(encryption_key,initialization_vector)` and xor's with the
encrypted price to reverse the encryption. The integrity stage takes 4 bytes of
`<HMAC(integrity_key, price||initialization_vector)>` where
`||` is concatenation.

| Inputs ||
|---|---|
| `iv` | initialization vector (16 bytes - unique to the impression) |
| `e_key` | encryption key (32 bytes - provided at account set up) |
| `i_key` | integrity key (32 bytes - provided at account set up) |
| `price` | (8 bytes - in micros of account currency) |
| `hmac(k, d)` | SHA-1 HMAC of data `d`, using key `k` |
| `a || b` | string `a` concatenated with string `b` |
| ``` pad = hmac(e_key, iv)  // first 8 bytes enc_price = pad <xor> price signature = hmac(i_key, price || iv)  // first 4 bytes final_message = WebSafeBase64Encode( iv || enc_price || signature ) ``` ||

## Decryption scheme

Your decryption code must decrypt the price using the encryption key, and
verify the integrity bits with the integrity key. The keys will be provided to
you during setup. There aren't any restrictions on the details of how you
structure your implementation. For the most part, you should be able to take
the sample code and adapt it according to your needs.

| Inputs ||
|---|---|
| `e_key` | encryption key, 32 bytes - provided at account set up |
| `i_key` | integrity key, 32 bytes - provided at account set up |
| `final_message` | 38 characters web-safe base64 encoded |
| ``` // Base64 padding characters are omitted. // Add any required base64 padding (= or ==). final_message_valid_base64 = AddBase64Padding(final_message) // Web-safe decode, then base64 decode. enc_price = WebSafeBase64Decode(final_message_valid_base64) // Message is decoded but remains encrypted. (iv, p, sig) = enc_price // Split up according to fixed lengths. price_pad = hmac(e_key, iv) price = p <xor> price_pad conf_sig = hmac(i_key, price || iv) success = (conf_sig == sig) ``` ||

## Detect stale response attacks

To detect stale response, or replay, attacks, it's recommended that you
filter responses with a timestamp that differs significantly from the system
time, after accounting for timezone differences.

The initialization vector contains a timestamp in the first 8 bytes. It can
be read by the following C++ function:

```
void GetTime(const char* iv, struct timeval* tv) {
    uint32 val;
    memcpy(&val, iv, sizeof(val));
    tv->tv_sec = htonl(val);
    memcpy(&val, iv+sizeof(val), sizeof(val));
    tv->tv_usec = htonl(val)
}
```

The timestamp can be converted to a human readable form using the following
C++ code:

```
struct tm tm;
localtime_r(&tv->tv_sec, &tm);

printf("%04d-%02d-%02d|%02d:%02d:%02d.%06ld",
       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
       tm.tm_hour, tm.tm_min, tm.tm_sec,
       tv_.tv_usec);
```

## Java library

Instead of implementing the crypto algorithms to encode and decode
the winning price, you can use
[DoubleClickCrypto.java](https://github.com/google/openrtb-doubleclick/blob/master/doubleclick-core/src/main/java/com/google/doubleclick/crypto/DoubleClickCrypto.java). For more information, see
[Cryptography](https://github.com/google/openrtb-doubleclick/wiki#cryptography).