文档:https://developers.google.com/ad-exchange/rtb/response-guide/decrypt-price#sample_code
golang中没有官方的“Double Click Crypto”示例代码,所以我尝试自己实现。但是我无法通过doc中的测试。请帮助我!
skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o= // Encryption key (e_key)
arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo= // Integrity key (i_key)
WEp8wQAAAABnFd5EkB2k1wJeFcAj-Z_JVOeGzA // 100 CPI micros
WEp8sQAAAACwF6CtLJrXSRFBM8UiTTIyngN-og // 1900 CPI micros
WEp8nQAAAAADG-y45xxIC1tMWuTjzmDW6HtroQ // 2700 CPI micros
这是我的代码:
package main
// https://developers.google.com/ad-exchange/rtb/response-guide/decrypt-price?hl=zh-CN
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/binary"
"fmt"
)
var base64Codec = base64.URLEncoding.WithPadding(base64.NoPadding)
func safeXORBytes(dst, a, b []byte) int {
n := len(a)
if len(b) < n {
n = len(b)
}
for i := 0; i < n; i++ {
dst[i] = a[i] ^ b[i]
}
return n
}
func EncryptPrice(eKey []byte, iKey []byte, price uint64, iv []byte) (finalMessage string, err error) {
if len(iv) != 16 {
err = fmt.Errorf("len(iv) = %d != 16", len(iv))
return
}
h1 := hmac.New(sha1.New, eKey)
h1.Write(iv)
pad := h1.Sum(nil)[:8]
priceBytes := make([]byte, 8)
binary.BigEndian.PutUint64(priceBytes, price)
encPrice := make([]byte, 8)
n := safeXORBytes(encPrice, priceBytes, pad)
if n != 8 {
err = fmt.Errorf("safeXORBytes n != %d", n)
return
}
h2 := hmac.New(sha1.New, iKey)
h2.Write(priceBytes)
h2.Write(iv)
signature := h2.Sum(nil)[:4]
finalMessage = base64Codec.EncodeToString(append(append(iv, encPrice...), signature...))
return
}
func DecryptPrice(eKey []byte, iKey []byte, finalMessage string) (price uint64, err error) {
finalMessageBytes, err := base64Codec.DecodeString(finalMessage)
if err != nil {
return
}
if len(finalMessageBytes) != 28 {
err = fmt.Errorf("len(finalMessageBytes) = %d != 28", len(finalMessageBytes))
return
}
iv := finalMessageBytes[:16]
encPrice := finalMessageBytes[16:24]
signature := finalMessageBytes[24:]
h1 := hmac.New(sha1.New, eKey)
h1.Write(iv)
pad := h1.Sum(nil)[:8]
priceBytes := make([]byte, 8)
n := safeXORBytes(priceBytes, encPrice, pad)
if n != 8 {
err = fmt.Errorf("safeXORBytes n != %d", n)
return
}
h2 := hmac.New(sha1.New, iKey)
h2.Write(priceBytes)
h2.Write(iv)
confSignature := h2.Sum(nil)[:4]
if bytes.Compare(confSignature, signature) != 0 {
err = fmt.Errorf("sinature mismatch: confSignature = %s, sinature = %s", confSignature, signature)
return
}
price = binary.BigEndian.Uint64(priceBytes)
return
}
package main
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestEncryptPrice(t *testing.T) {
eKeyBase64Encoded := "skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o"
eKey, err := base64Codec.DecodeString(eKeyBase64Encoded)
assert.Nil(t, err)
iKeyBase64Encoded := "arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo"
iKey, err := base64Codec.DecodeString(iKeyBase64Encoded)
assert.Nil(t, err)
finalMessage, err := EncryptPrice(eKey, iKey, uint64(100), []byte{88, 74, 124, 193, 0, 0, 0, 0, 103, 21, 222, 68, 144, 29, 164, 215})
assert.Nil(t, err)
assert.Equal(t, "WEp8wQAAAABnFd5EkB2k1wJeFcAj-Z_JVOeGzA", finalMessage)
}
func TestDecryptPrice(t *testing.T) {
eKeyBase64Encoded := "skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o"
eKey, err := base64Codec.DecodeString(eKeyBase64Encoded)
assert.Nil(t, err)
iKeyBase64Encoded := "arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo"
iKey, err := base64Codec.DecodeString(iKeyBase64Encoded)
assert.Nil(t, err)
price, err := DecryptPrice(eKey, iKey, "WEp8wQAAAABnFd5EkB2k1wJeFcAj-Z_JVOeGzA")
assert.Nil(t, err)
assert.Equal(t, uint64(100), price)
}
测试结果:
--- FAIL: TestEncryptPrice (0.00s)
Error Trace: price_test.go:19
Error: Not equal:
expected: "WEp8wQAAAABnFd5EkB2k1wJeFcAj-Z_JVOeGzA"
actual: "WEp8wQAAAABnFd5EkB2k1wf7jAcG7gZ9tPUnAA"
--- FAIL: TestDecryptPrice (0.00s)
Error Trace: price_test.go:32
Error: Expected nil, but got: &errors.errorString{s:"sinature mismatch: confSignature = \xbe\xaa\xf6h, sinature = T\xe7\x86\xcc"}
Error Trace: price_test.go:33
Error: Not equal:
expected: 0x64
actual: 0x0
FAIL
最佳答案
这段代码可以通过https://github.com/google/openrtb-doubleclick/blob/0.9.0/doubleclick-core/src/test/java/com/google/doubleclick/crypto/DoubleClickCryptoTest.java中的测试 , 所以我猜文档中的加密价格没有被文档中的 e_key 和 i_key 解密。
关于go - 在 Golang 中双击加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47332451/