Real-Time Bidding Protocol Decrypt Price Confirmations 谷歌实时竞价文档

加密结果格式

1
{初始化向量 (16 bytes)}{加密的价格(8 bytes)}{完整性签名(4 bytes)}

加密价格的长度固定为 28 个字节,其中包含 16 个字节的初始化矢量、8 个字节的密 文以及 4 个字节的完整性签名。

加密方式

使用基于SHA-1 HMAC算法的加密解密示例如下:
加密阶段伪代码:

1
2
3
4
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 )

解密阶段伪代码

1
2
3
4
5
(iv || enc_price || signature) = WebSafeBase64Decode(final_message)
pad = hmac(e_key, iv)
price = enc_price <xor> pad
conf_sig = hmac(i_key, price || iv)
success = (conf_sig == signature)

字符与表达式解释

iv: 初始化矢量(16 个字节)
e_key: 加密密钥(32 个字节)
i_key: 完整性密钥(32 个字节)
price: 价格 (8 个字节)
hmac(k, d): 数据 d 的 SHA-1 HMAC,使用密钥 k
a || b: 字符串 a 和字符串 b 并列

解密算法nodejs版示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const crypto = require('crypto');
const e_key = "";
const i_key = "";
function WebSafeBase64Decode(base) {
var s = base.replace(/\-/g, '+').replace(/\_/g, '/');
if ((s.length % 4) == 2) {
s += "==";
} else if ((s.length % 4) == 3) {
s += "=";
}
return s;
}
function decodePrice(e_enc) {
let buffer = new Buffer(WebSafeBase64Decode(e_enc), 'base64'); // base64解码
let iv = buffer.slice(0, 16); // 初始化矢量数组
let en_price = buffer.slice(16, 24); // 加密的价格数组
let integrity = buffer.slice(24, 28).toString('hex'); // 完整性签名的前4位, 转换成16进制字符串
let de_byte = crypto.createHmac('sha1', e_key).update(iv).digest().slice(0, 8); // HmacSHA1 加密得到加密数组, 取前8个字节
let dec_price = new Buffer.allocUnsafe(8); // 创建一个长度为8的buffer
for (let i = 0; i < 8; i++) {
dec_price[i] = en_price[i] ^ de_byte[i] // 将异或运算后的新值存入dec_price
}
let price = parseInt(dec_price.toString("hex"), 16) / 1000000; // 转换成价格
// 加密签名验证
let o_ikey = crypto.createHmac('sha1', i_key).update(Buffer.concat([dec_price, iv])).digest().slice(0, 4).toString('hex');
if (integrity == o_ikey) { // 比较两个签名数组是否相同
return price;
} else {
return -1;
}
}
decodePrice("加密价格字符串");
—-publish by CEditor