Skip to content

Commit

Permalink
Add RSA validation to Criteo FastBid (prebid#3110)
Browse files Browse the repository at this point in the history
* Pass Prebid version to Criteo direct bidder

* Update Criteo profile IDs

* Add RSA verification to Criteo FastBid

* Update package-lock with jsencrypt and crypto-js

* Replacing all arrow functions in Mocha function calls

* Update Adapter Version to 14
  • Loading branch information
jsfaure authored and Isaac Dettman committed Nov 12, 2018
1 parent b9764c0 commit 9e1a9af
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 5 deletions.
49 changes: 45 additions & 4 deletions modules/criteoBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { registerBidder } from 'src/adapters/bidderFactory';
import { parse } from 'src/url';
import * as utils from 'src/utils';
import find from 'core-js/library/fn/array/find';
import JSEncrypt from 'jsencrypt/bin/jsencrypt';
import sha256 from 'crypto-js/sha256';

const ADAPTER_VERSION = 11;
const ADAPTER_VERSION = 14;
const BIDDER_CODE = 'criteo';
const CDB_ENDPOINT = '//bidder.criteo.com/cdb';
const CRITEO_VENDOR_ID = 91;
Expand All @@ -17,6 +19,13 @@ const PROFILE_ID_PUBLISHERTAG = 185;
// Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js
const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js';

export const FAST_BID_PUBKEY = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO1BjAITkFTtP0IMzmF7qsqhpu
y1dGaTPHnjMU9mRZsrnfR3C0sEN5pYEzEcFRPnkJjJuhH8Rnh5+CE+LcKg0Z8ZZ7
OmOSj0/qnYTAYCu0cR5LiyWG79KlIgUyMbp92ulGg24gAyGrVn4+v/4c53WlOEUp
4YWvb82G0CD5NcDNpQIDAQAB
-----END PUBLIC KEY-----`;

/** @type {BidderSpec} */
export const spec = {
code: BIDDER_CODE,
Expand Down Expand Up @@ -251,20 +260,52 @@ function createNativeAd(id, payload, callback) {
</script>`;
}

export function cryptoVerify(key, hash, code) {
var jse = new JSEncrypt();
jse.setPublicKey(key);
return jse.verify(code, hash, sha256);
}

function validateFastBid(fastBid) {
// The value stored must contain the file's encrypted hash as first line
const firstLineEnd = fastBid.indexOf('\n');
const firstLine = fastBid.substr(0, firstLineEnd).trim();
if (firstLine.substr(0, 9) !== '// Hash: ') {
utils.logWarn('No hash found in FastBid');
return false;
}

// Remove the hash part from the locally stored value
const fileEncryptedHash = firstLine.substr(9);
const publisherTag = fastBid.substr(firstLineEnd + 1);

// Verify the hash using cryptography
try {
return cryptoVerify(FAST_BID_PUBKEY, fileEncryptedHash, publisherTag);
} catch (e) {
utils.logWarn('Failed to verify Criteo FastBid');
return undefined;
}
}

/**
* @return {boolean}
*/
function tryGetCriteoFastBid() {
try {
const fastBid = localStorage.getItem('criteo_fast_bid');
if (fastBid !== null) {
eval(fastBid); // eslint-disable-line no-eval
return true;
if (validateFastBid(fastBid) === false) {
utils.logWarn('Invalid Criteo FastBid found');
localStorage.removeItem('criteo_fast_bid');
} else {
utils.logInfo('Using Criteo FastBid');
eval(fastBid); // eslint-disable-line no-eval
}
}
} catch (e) {
// Unable to get fast bid
}
return false;
}

registerBidder(spec);
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@
"dependencies": {
"babel-plugin-transform-object-assign": "^6.22.0",
"core-js": "^2.4.1",
"crypto-js": "^3.1.9-1",
"gulp-sourcemaps": "^2.6.0",
"jsencrypt": "^3.0.0-rc.1",
"just-clone": "^1.0.2"
}
}
19 changes: 18 additions & 1 deletion test/spec/modules/criteoBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import { spec } from 'modules/criteoBidAdapter';
import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter';
import * as utils from 'src/utils';

describe('The Criteo bidding adapter', function () {
Expand Down Expand Up @@ -294,4 +294,21 @@ describe('The Criteo bidding adapter', function () {
expect(bids[0].height).to.equal(90);
});
});

describe('cryptoVerify', function () {
const TEST_HASH = 'vBeD8Q7GU6lypFbzB07W8hLGj7NL+p7dI9ro2tCxkrmyv0F6stNuoNd75Us33iNKfEoW+cFWypelr6OJPXxki2MXWatRhJuUJZMcK4VBFnxi3Ro+3a0xEfxE4jJm4eGe98iC898M+/YFHfp+fEPEnS6pEyw124ONIFZFrcejpHU=';

it('should verify right signature', function () {
expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test')).to.equal(true);
});

it('should verify wrong signature', function () {
expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test wrong')).to.equal(false);
});

it('should return undefined with incompatible browsers', function () {
// Here use a null hash to make the call to crypto library fail and simulate a browser failure
expect(cryptoVerify(FAST_BID_PUBKEY, null, 'test')).to.equal.undefined;
});
});
});

0 comments on commit 9e1a9af

Please sign in to comment.