diff --git a/README.md b/README.md index 3facf4a..0c844dd 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,7 @@ pricer, err = doubleclick.NewDoubleClickPricer( "vQo9-4KtlcXmPhWaYvc8asqYuiSVMiGUdZ1RLXfrK7U", // Integrity key true, // Keys are base64 helpers.Utf8, // Keys should be ingested as Utf-8 - 1000000, // Price scale Factor Micro - false, // No debug + 1000000 // Price scale Factor Micro ) ``` ##### Encrypting a clear price diff --git a/doubleclick/doubleclick_pricer.go b/doubleclick/doubleclick_pricer.go index 3f572a9..60f2044 100644 --- a/doubleclick/doubleclick_pricer.go +++ b/doubleclick/doubleclick_pricer.go @@ -5,9 +5,7 @@ import ( "crypto/md5" "encoding/base64" "encoding/binary" - "encoding/hex" "errors" - "fmt" "hash" "strings" @@ -20,17 +18,13 @@ var ErrWrongSignature = errors.New("Failed to decrypt") // DoubleClickPricer implementing price encryption and decryption // Specs : https://developers.google.com/ad-exchange/rtb/response-guide/decrypt-price type DoubleClickPricer struct { - encryptionKeyRaw string - integrityKeyRaw string - encryptionKey hash.Hash - integrityKey hash.Hash - keyDecodingMode helpers.KeyDecodingMode - scaleFactor float64 - isDebugMode bool + encryptionKey hash.Hash + integrityKey hash.Hash + scaleFactor float64 } // NewDoubleClickPricer returns a DoubleClickPricer struct. -// Keys are either base 64 websafe of hexa. keyDecodingMode +// Keys are either Base64Url (websafe) of hexa. keyDecodingMode // should be used to specify how keys should be decoded. // Factor the clear price will be multiplied by before encryption. // from specs, scaleFactor is 1,000,000, but you can set something else. @@ -42,8 +36,7 @@ func NewDoubleClickPricer( integrityKey string, isBase64Keys bool, keyDecodingMode helpers.KeyDecodingMode, - scaleFactor float64, - isDebugMode bool) (*DoubleClickPricer, error) { + scaleFactor float64) (*DoubleClickPricer, error) { var err error var encryptingFun, integrityFun hash.Hash @@ -56,30 +49,10 @@ func NewDoubleClickPricer( return nil, err } - if isDebugMode { - fmt.Println("Keys decoding mode : ", keyDecodingMode) - fmt.Println("Encryption key : ", encryptionKey) - encryptionKeyHexa, err := hex.DecodeString(encryptionKey) - if err != nil { - encryptionKeyHexa = []byte(encryptionKey) - } - fmt.Println("Encryption key (bytes) : ", []byte(encryptionKeyHexa)) - fmt.Println("Integrity key : ", integrityKey) - integrityKeyHexa, err := hex.DecodeString(integrityKey) - if err != nil { - integrityKeyHexa = []byte(integrityKey) - } - fmt.Println("Integrity key (bytes) : ", []byte(integrityKeyHexa)) - } - return &DoubleClickPricer{ - encryptionKeyRaw: encryptionKey, - integrityKeyRaw: integrityKey, - encryptionKey: encryptingFun, - integrityKey: integrityFun, - keyDecodingMode: keyDecodingMode, - scaleFactor: scaleFactor, - isDebugMode: isDebugMode}, + encryptionKey: encryptingFun, + integrityKey: integrityFun, + scaleFactor: scaleFactor}, nil } @@ -91,37 +64,21 @@ func (dc *DoubleClickPricer) Encrypt(seed string, price float64) (string, error) signature []byte ) - data := helpers.ApplyScaleFactor(price, dc.scaleFactor, dc.isDebugMode) + data := helpers.ApplyScaleFactor(price, dc.scaleFactor) // Create Initialization Vector from seed iv = md5.Sum([]byte(seed)) - if dc.isDebugMode { - fmt.Println("Seed : ", seed) - fmt.Println("Initialization vector : ", iv) - } //pad = hmac(e_key, iv), first 8 bytes pad := helpers.HmacSum(dc.encryptionKey, iv[:], nil)[:8] - if dc.isDebugMode { - fmt.Println("// pad = hmac(e_key, iv), first 8 bytes") - fmt.Println("Pad : ", pad) - } // signature = hmac(i_key, data || iv), first 4 bytes signature = helpers.HmacSum(dc.integrityKey, data[:], iv[:])[:4] - if dc.isDebugMode { - fmt.Println("// signature = hmac(i_key, data || iv), first 4 bytes") - fmt.Println("Signature : ", signature) - } // enc_data = pad data for i := range data { encoded[i] = pad[i] ^ data[i] } - if dc.isDebugMode { - fmt.Println("// enc_data = pad data") - fmt.Println("Encoded price bytes : ", encoded) - } // final_message = WebSafeBase64Encode( iv || enc_price || signature ) return base64.RawURLEncoding.EncodeToString(append(append(iv[:], encoded[:]...), signature...)), nil @@ -143,11 +100,6 @@ func (dc *DoubleClickPricer) Decrypt(encryptedPrice string) (float64, error) { return errPrice, err } - if dc.isDebugMode { - fmt.Println("Encrypted price : ", encryptedPrice) - fmt.Println("Base64 decoded price : ", decoded) - } - // Get elements var ( iv []byte @@ -163,13 +115,6 @@ func (dc *DoubleClickPricer) Decrypt(encryptedPrice string) (float64, error) { // pad = hmac(e_key, iv) pad := helpers.HmacSum(dc.encryptionKey, iv, nil)[:8] - if dc.isDebugMode { - fmt.Println("IV : ", hex.EncodeToString(iv)) - fmt.Println("Encoded price : ", hex.EncodeToString(p)) - fmt.Println("Signature : ", hex.EncodeToString(signature)) - fmt.Println("Pad : ", hex.EncodeToString(pad)) - } - // priceMicro = p pad for i := range p { priceMicro[i] = pad[i] ^ p[i] diff --git a/doubleclick/doubleclick_pricer_test.go b/doubleclick/doubleclick_pricer_test.go index 4471a4b..20dd9f8 100644 --- a/doubleclick/doubleclick_pricer_test.go +++ b/doubleclick/doubleclick_pricer_test.go @@ -8,8 +8,23 @@ import ( "github.com/benjaminch/pricers/helpers" ) -func buildNewDoubleClickPricer(encryptionKey string, integrityKey string, isBase64Keys bool, keyDecodingMode helpers.KeyDecodingMode, scaleFactor float64, isDebugMode bool) (*DoubleClickPricer, error) { - return NewDoubleClickPricer(encryptionKey, integrityKey, isBase64Keys, keyDecodingMode, scaleFactor, isDebugMode) +// Create a pricer with: +// - HEX keys +// - Price scale factor as micro +func buildPricer() (*DoubleClickPricer, error) { + return buildPricerWithScale(1000000) +} + +func buildPricerWithScale(scaleFactor float64) (*DoubleClickPricer, error) { + var pricer *DoubleClickPricer + var err error + pricer, err = NewDoubleClickPricer( + "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", + "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", + false, + helpers.Hexa, + scaleFactor) + return pricer, err } type priceTestCase struct { @@ -23,21 +38,10 @@ func newPriceTestCase(encrypted string, clear float64, scaleFactor float64) pric } func TestDecryptEmpty(t *testing.T) { - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "6356770B3C111C07F778AFD69F16643E9110090FD4C479D91181EED2523788F1", - "3588BF6D387E8AEAD4EEC66798255369AF47BFD48B056E8934CEFEF3609C469E", - false, // Keys are not base64 - helpers.Utf8, - 1000000, - false, - ) + pricer, _ := buildPricer() - assert.Nil(t, err, "Error creating new Pricer : ", err) // Execute: - var result float64 - result, err = pricer.Decrypt("") + result, err := pricer.Decrypt("") // Verify: assert.Equal(t, err, ErrWrongSize) assert.Equal(t, float64(0), result) @@ -50,14 +54,12 @@ func TestDecryptGoogleOfficialExamples(t *testing.T) { // Setup: var pricer *DoubleClickPricer var err error - pricer, err = buildNewDoubleClickPricer( + pricer, err = NewDoubleClickPricer( "ZS-DraBUUVeht_sMDgn1nnM3My_nq9TrEESbjubDkTU", "vQo9-4KtlcXmPhWaYvc8asqYuiSVMiGUdZ1RLXfrK7U", - true, // Keys are base64 + true, helpers.Utf8, - 1000000, - false, - ) + 1000000) assert.Nil(t, err, "Error creating new Pricer : ", err) @@ -84,24 +86,8 @@ func TestDecryptGoogleOfficialExamples(t *testing.T) { } func TestDecryptWithHexaKeys(t *testing.T) { - // Create a pricer with: - // - HEX keys - // - Price scale factor as micro - // - No debug mode - // Setup: - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", - "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", - false, // Keys are not base64 - helpers.Hexa, - 1000000, - false, - ) - - assert.Nil(t, err, "Error creating new Pricer : ", err) + pricer, _ := buildPricer() // Encrypted prices we will try to decrypt var pricesTestCase = []priceTestCase{ @@ -129,19 +115,16 @@ func TestDecryptWithUtf8Keys(t *testing.T) { // Create a pricer with: // - UTF-8 keys // - Price scale factor as micro - // - No debug mode // Setup: var pricer *DoubleClickPricer var err error - pricer, err = buildNewDoubleClickPricer( + pricer, err = NewDoubleClickPricer( "6356770B3C111C07F778AFD69F16643E9110090FD4C479D91181EED2523788F1", "3588BF6D387E8AEAD4EEC66798255369AF47BFD48B056E8934CEFEF3609C469E", - false, // Keys are not base64 - helpers.Utf8, - 1000000, false, - ) + helpers.Utf8, + 1000000) assert.Nil(t, err, "Error creating new Pricer : ", err) @@ -177,26 +160,10 @@ func TestDecryptWithScaleFactor(t *testing.T) { } for _, priceTestCase := range pricesTestCase { - // Create a pricer with: - // - HEX keys - // - Price scale factor as micro - // - No debug mode - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", - "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", - false, // Keys are not base64 - helpers.Hexa, - priceTestCase.scaleFactor, - false, - ) - - assert.Nil(t, err, "Error creating new Pricer : ", err) + pricer, _ := buildPricerWithScale(priceTestCase.scaleFactor) // Execute: - var result float64 - result, err = pricer.Decrypt(priceTestCase.encrypted) + result, err := pricer.Decrypt(priceTestCase.encrypted) // Verify: assert.Nil(t, err, "Decryption failed. Error : %s", err) @@ -204,29 +171,9 @@ func TestDecryptWithScaleFactor(t *testing.T) { } } -func TestDecryptWithDebug(t *testing.T) { - // TODO: To be implemented -} - func TestEncryptWithHexaKeys(t *testing.T) { - // Create a pricer with: - // - HEX keys - // - Price scale factor as micro - // - No debug mode - // Setup: - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", - "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", - false, // Keys are not base64 - helpers.Hexa, - 1000000, - false, - ) - - assert.Nil(t, err, "Error creating new Pricer : ", err) + pricer, _ := buildPricer() // Clear prices we will try to encrypt var pricesTestCase = []priceTestCase{ @@ -255,7 +202,6 @@ func TestEncryptWithUtf8Keys(t *testing.T) { // Create a pricer with: // - UTF-8 keys // - Price scale factor as micro - // - No debug mode var pricer *DoubleClickPricer var err error pricer, err = buildNewDoubleClickPricer( @@ -311,26 +257,10 @@ func TestEncryptWithScaleFactor(t *testing.T) { } for _, priceTestCase := range pricesTestCase { - // Create a pricer with: - // - HEX keys - // - Price scale factor as micro - // - No debug mode - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", - "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", - false, // Keys are not base64 - helpers.Hexa, - priceTestCase.scaleFactor, - false, - ) - - assert.Nil(t, err, "Error creating new Pricer : ", err) + pricer, _ := buildPricerWithScale(priceTestCase.scaleFactor) // Execute: - var result string - result, err = pricer.Encrypt("", priceTestCase.clear) + result, err := pricer.Encrypt("", priceTestCase.clear) // Verify: assert.Nil(t, err, "Encryption failed. Error : %s", err) @@ -338,29 +268,9 @@ func TestEncryptWithScaleFactor(t *testing.T) { } } -func TestEncryptWithDebug(t *testing.T) { - // TODO : To be implemented -} - func TestEncryptDecryptWithHexaKeys(t *testing.T) { - // Create a pricer with: - // - HEX keys - // - Price scale factor as micro - // - No debug mode - // Setup: - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", - "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", - false, // Keys are not base64 - helpers.Hexa, - 1000000, - false, - ) - - assert.Nil(t, err, "Error creating new Pricer : ", err) + pricer, _ := buildPricer() // Clear prices to encrypt var pricesTestCase = []priceTestCase{ @@ -384,7 +294,7 @@ func TestEncryptDecryptWithHexaKeys(t *testing.T) { // Decrypt decrypted, err = pricer.Decrypt(encrypted) - assert.Nil(t, err, "EncryDecryptionption failed. Error : %s", err) + assert.Nil(t, err, "Decryption failed. Error : %s", err) // Verify: // Assert that the decrypted price is the one with encrypted in a first place @@ -396,19 +306,16 @@ func TestEncryptDecryptWithUtf8Keys(t *testing.T) { // Create a pricer with: // - UTF-8 keys // - Price scale factor as micro - // - No debug mode // Setup: var pricer *DoubleClickPricer var err error - pricer, err = buildNewDoubleClickPricer( + pricer, err = NewDoubleClickPricer( "6356770B3C111C07F778AFD69F16643E9110090FD4C479D91181EED2523788F1", "3588BF6D387E8AEAD4EEC66798255369AF47BFD48B056E8934CEFEF3609C469E", - false, // Keys are not base64 - helpers.Utf8, - 1000000, false, - ) + helpers.Utf8, + 1000000) assert.Nil(t, err, "Error creating new Pricer : ", err) @@ -434,7 +341,7 @@ func TestEncryptDecryptWithUtf8Keys(t *testing.T) { // Decrypt decrypted, err = pricer.Decrypt(encrypted) - assert.Nil(t, err, "EncryDecryptionption failed. Error : %s", err) + assert.Nil(t, err, "Decryption failed. Error : %s", err) // Verify: // Assert that the decrypted price is the one with encrypted in a first place @@ -457,22 +364,7 @@ func TestEncryptDecryptWithSeed(t *testing.T) { newPriceTestCase("", 1000, 1000000), } - // Create a pricer with: - // - HEX keys - // - Price scale factor as micro - // - No debug mode - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", - "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", - false, // Keys are not base64 - helpers.Hexa, - 1000000, - false, - ) - - assert.Nil(t, err, "Error creating new Pricer : ", err) + pricer, _ := buildPricer() var encryptedPrices []string @@ -490,7 +382,7 @@ func TestEncryptDecryptWithSeed(t *testing.T) { // Decrypt decrypted, err = pricer.Decrypt(encrypted) - assert.Nil(t, err, "EncryDecryptionption failed. Error : %s", err) + assert.Nil(t, err, "Decryption failed. Error : %s", err) // Verify: // Assert that the decrypted price is the one with encrypted in a first place @@ -526,22 +418,7 @@ func TestEncryptDecryptWithScaleFactor(t *testing.T) { for _, scaleFactor := range scaleFactorsToTest { - // Create a pricer with: - // - HEX keys - // - Price scale factor as micro - // - No debug mode - var pricer *DoubleClickPricer - var err error - pricer, err = buildNewDoubleClickPricer( - "652f83ada0545157a1b7fb0c0e09f59e7337332fe7abd4eb10449b8ee6c39135", - "bd0a3dfb82ad95c5e63e159a62f73c6aca98ba2495322194759d512d77eb2bb5", - false, // Keys are not base64 - helpers.Hexa, - scaleFactor, - false, - ) - - assert.Nil(t, err, "Error creating new Pricer : ", err) + pricer, _ := buildPricerWithScale(scaleFactor) for _, price := range pricesTestCase { // Execute: @@ -555,7 +432,7 @@ func TestEncryptDecryptWithScaleFactor(t *testing.T) { // Decrypt decrypted, err = pricer.Decrypt(encrypted) - assert.Nil(t, err, "EncryDecryptionption failed. Error : %s", err) + assert.Nil(t, err, "Decryption failed. Error : %s", err) // Verify: // Assert that the decrypted price is the one with encrypted in a first place diff --git a/go.mod b/go.mod index eabcec5..d509bc4 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,4 @@ module github.com/benjaminch/pricers go 1.12 -require ( - github.com/benjaminch/openrtb-pricers v0.2.0 - github.com/stretchr/testify v1.4.0 -) +require github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 3263b4a..acb88a4 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,11 @@ -github.com/benjaminch/openrtb-pricers v0.2.0 h1:rEoZbSsa47sprVLE6qjSXsq9ROUGAAsKjFOV0gtzUH0= -github.com/benjaminch/openrtb-pricers v0.2.0/go.mod h1:/I+cVRYTUI3TkNxO3bvIzC7E6NcEzsDsdNxZt6J6RVI= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/helpers/helpers.go b/helpers/helpers.go index ff64388..1b41da8 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -7,7 +7,6 @@ import ( "encoding/binary" "encoding/hex" "errors" - "fmt" "hash" "strings" ) @@ -89,13 +88,9 @@ func HmacSum(hmac hash.Hash, buf, buf2 []byte) []byte { // ApplyScaleFactor : Applies a scale factor to a given price. // Scaled price will be represented on 8 bytes. -func ApplyScaleFactor(price float64, scaleFactor float64, isDebugMode bool) [8]byte { +func ApplyScaleFactor(price float64, scaleFactor float64) [8]byte { scaledPrice := [8]byte{} binary.BigEndian.PutUint64(scaledPrice[:], uint64(price*scaleFactor)) - if isDebugMode { - fmt.Printf("Micro price bytes: %v", scaledPrice) - } - return scaledPrice }