解密价格确认

在您的广告素材赢得竞价后,如果定义该广告素材的 HTML 代码段包含 WINNING_PRICE 宏,Google 可以将胜出价格通知给您。Google 会以加密格式返回胜出价格。下列主题将介绍您的应用如何解密胜出价格信息。

    情形
    依赖关系
    示例代码
    加密机制
    解密机制
    检测过期响应***

情形

    您的应用在返回给 Google 的 HTML 代码段中加入 WINNING_PRICE 宏。
    Google 以未填补的网络安全 base64 编码形式 (RFC 3548),使用胜出价格替换该宏。
    代码段以您选择的任意格式传递确认信息,例如将其放入作为广告内容显示的隐藏像素请求的网址中。
    在服务器上,您的应用将胜出价格信息转换为 base64 编码,然后解密结果。

依赖关系

您需要支持 SHA-1 HMAC 的 Crypto 库,例如 Openssl。
示例代码

我们提供 Java 和 C++ 的示例代码,您可以访问 http://code.google.com/p/privatedatacommunicationprotocol 下载这些示例。

    Java 示例代码使用 Apache Commons 项目的 base64 ×××。您不需要下载 Apache Commons 代码,因为参考实施已包括必要的代码,可以自行运作。

    C++ 示例代码使用 OpenSSL base64 BIO 方法。该方法会获取以网络安全 base64 编码的字符串 (RFC 3548),并对其进行解码。网络安全 base64 字符串通常会使用“.”来替换“=”(请注意,在此加入引号是为了阅读方便,引号并不是协议的一部分);不过,这样替换宏时并不会填补已加密的价格。由于 OpenSSL 无法处理未填补的字符串,因此参考实施会添加填补内容。

加密机制

Google 使用自定义的加密机制对价格进行加密,其设计可尽量缩减加密文件的大小,同时保证所需的安全性。这项加密机制使用密钥验证 HMAC 算法,可根据唯一展示活动 ID 来生成秘密的填补内容。

加密价格的长度固定为 28 个字节,其中包含 16 个字节的初始化矢量、8 个字节的密文以及 4 个字节的完整性签名。加密的价格根据 RFC 3548 使用网络安全 base64 方式编码,会省略填补的字符。因此,28 个字节的加密价格会被编成 38 个字符的网络安全 base-64 字符串。

加密格式如下:

        {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 个字节 - 以帐户币种的百万分之一表示)

表示法
hmac(k, d)     数据 d 的 SHA-1 HMAC,使用密钥 k。
a || b     字符串 a 和字符串 b 并列

伪代码

pad = hmac(e_key, iv)  // 前 8 个字节
enc_price = pad <xor> price
signature = hmac(i_key, price || iv)  // 前 4 个字节

final_message = WebSafeBase64Encode( iv || enc_price || signature )

解密机制

您的解密代码必须使用加密密钥对价格进行解密,并使用完整性密钥验证完整性位元。您在设置时就会获得密钥。至于如何组织实施,则完全由您决定。您应该可以直接引用绝大多数示例代码,然后再根据需要进行修改。

输入内容
e_key     加密密钥,32 个字节 - 在创建帐户时提供
i_key     完整性密钥,32 个字节 - 在创建帐户时提供
final_message     使用网络安全 base64 编码的 38 个字符

伪代码

enc_price = WebSafeBase64Decode(final_message)
(iv, p, sig) = dec_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);


来源:https://developers.google.com/ad-exchange/rtb/response-guide/decrypt-price?hl=zh-cn