解密价格确认

当您的广告素材在竞价中胜出时,Google 可以告知您 如果广告素材包含相关宏,则价格为原始价格。

如果您的出价工具配置为使用 OpenRTB 协议,相应广告素材 应使用 IAB 的${AUCTION_PRICE} 宏。

如果您的出价工具使用已弃用的 Google RTB 协议,则广告素材应 使用 Google 的%%WINNING_PRICE%% 宏。

<ph type="x-smartling-placeholder">

当这些宏展开时,它们会在 加密形式。它们可包含在广告素材中,例如,通过 作为广告的一部分呈现的不可见像素请求:

<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>

${AUCTION_PRICE} 宏还可以添加到 视频广告素材,但 VAST 中的展示网址中未包含:

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

场景

  1. 您的 OpenRTB 出价应用包含 ${AUCTION_PRICE} 宏包含在返回给 Google 的 HTML 代码段或 VAST 网址中。
  2. 在未填充网络安全的内容中,Google 会将胜出价格替换为宏 base64 编码 (RFC 3548)。
  3. 该代码段以您选择的格式传递确认信息。对于 例如,确认信息可能会通过不可见像素的网址传递 作为广告的一部分呈现
  4. 在服务器上,您的应用网络安全 base64 对胜出价格进行解码 并对结果进行解密。

依赖项

您需要一个支持 SHA-1 HMAC 的加密库,例如 Openssl。

示例代码

我们提供 Java 和 C++ 示例代码,您可以通过 privatedatacommunicationprotocol 项目

  • Java 示例代码使用来自 Apache 的 base64 解码器 Commons 项目。您不需要下载 Apache Commons 代码, 因为参考实现包含必要的部分,因此 都是独立的。

  • C++ 示例代码使用 OpenSSL base64 BIO 方法。它接受一个可在 web 环境中安全使用的 base64 编码字符串 (RFC 3548) 并对其进行解码。 通常,网络安全 base64 字符串会替换“=”填充内容为“.”(请注意, 为清晰起见而添加引号,且引号未包含在 协议),但宏替换不会填充加密价格。通过 由于 OpenSSL 无法处理 字符串。

编码

加密和解密胜出价格需要两个密钥,但它们是共享的 键。完整性密钥和加密密钥(称为 i_key) 和 e_key。这两个密钥都是在账号开设时提供的, 网络安全 base64 字符串,可在 Authorized Buyers 页面上找到 在出价方下 设置 >实时出价设置 >加密密钥

完整性和加密密钥示例:

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

密钥应通过网络安全解码,然后再由您的 应用:

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

加密架构

价格使用自定义加密方案加密 最大限度地减少大小开销,同时确保足够的安全性。加密架构 使用密钥的 HMAC 算法 展示事件 ID。

加密价格的固定长度为 28 个字节。它由 16 字节初始化矢量,8 字节密文,4 字节完整性 签名。根据 RFC,加密的价格采用可在网络上安全使用的 base64 编码 3548 个(省略了填充字符)。因此,28 字节的加密价格 编码为一个 38 个字符的网络安全 base-64 字符串,与胜出无关 支付的价格。

加密价格示例:

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

加密格式为:

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

价格已加密为 <price xor HMAC(encryption_key, initialization_vector)>,因此解密计算结果为 HMAC(encryption_key,initialization_vector) 和 xor 与 以逆转加密。完整性阶段会使用 4 个字节的 <HMAC(integrity_key, price||initialization_vector)>,其中 || 是串联。

输入
iv 初始化矢量(16 个字节 - 展示独有)
e_key 加密密钥(32 个字节 - 在创建账号时提供)
i_key 完整性密钥(32 个字节 - 在设置账号时提供)
price (8 个字节 - 以账号币种的微单位表示)
Notation
hmac(k, d) 数据 d 的 SHA-1 HMAC,使用密钥 k
a || b 字符串 a 与字符串 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 )

解密机制

您的解密代码必须使用加密密钥对价格进行解密;并且 使用完整性密钥验证完整性位。密钥将提供给 。在 构建您的实现。在大多数情况下,您应该能够 示例代码,并根据需要进行调整。

输入
e_key 加密密钥,32 个字节 - 在设置账号时提供
i_key 完整性密钥,32 个字节 - 在设置账号时提供
final_message 使用网络安全 base64 编码的 38 个字符
伪代码
// 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)

检测过时响应攻击

要检测过时响应攻击或重放攻击,建议您 过滤时间戳与系统显著不同的响应 然后再考虑时区差异。

初始化矢量的前 8 个字节包含时间戳。它可以 由以下 C++ 函数读取:

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)
}

可以使用以下代码将时间戳转换为人类可读形式 C++ 代码:

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 库

无需实现加密算法来编码和解码 您可以使用 <ph type="x-smartling-placeholder"></ph> DoubleClickCrypto.java.如需了解详情,请参阅 加密