Creating Access Signature

The Displayable Content Export (DCE) uses an access signature to verify that an incoming request originated from a trusted source. The access signature is a hash-based message authentication code (HMAC) consisting of values used in the request encrypted with a shared secret.

Bazaarvoice will use the values in the request along with our version of the shared secret to create our own access signature. If ours matches the one in the request, then we can be reasonably confident the request came from a trusted source.

Signature contents

The message to be encrypted will vary based on the DCE request. The two possible variations are demonstrated below:

Without path passkey={DCE_PASSKEY}&timestamp={TIMESTAMP}
With path path={PATH_VALUE}&passkey={DCE_PASSKEY}&timestamp={TIMESTAMP}

The tokens above should be replaced with the appropriate values as described below:

Name Description
{PATH_VALUE}

This is the same value communicated in the path query string parameter. Refer to the Workflow Walk-Through for more information.

{DCE_PASSKEY}

This is the same value communicated with the X-Bazaarvoice-Passkey header.

{TIMESTAMP}

A Unix timestamp in milliseconds. This is the same value communicated by the X-Bazaarvoice-Timestamp header.

📘 Using seconds or any increment other than milliseconds will cause your request to fail

Pseudo-code implementation

This pseudo-code demonstrates how to create an access signature:

message = utf8_encode("{MESSAGE}")  
shared_secret = utf8_encode("{SHARED_SECRET}")  
hmac =  hmac_sha256(shared_secret, message)  
access_signature = hex(hmac)

Defer to your programming language's documentation for the exact implementation.

Verification values

Use the following values to verify your implementation:

Token Value
{MESSAGE}

passkey=3412n4c4n243023nc03924nc0&timestamp=1502488941011

{SHARED_SECRET}

c73270c70932n09n09rn0r9n7

Using the verification values above in your implementation should output the following:

b6a597270d65be4e57de826ef10ac670c6fb195c09a0c4b488f51ab32f278ac9

Code samples

🚧

The code samples below are for educational purposes only. They are not intended to be used in a production environment and are provided "as is" without warranty of any kind.

The following code samples demonstrate how to encrypt the access signature. Defer to your programming language's documentation for the exact implementation.

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class Main {
    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        String passkey = "{enter your passkey}";
        String sharedSecret = "{enter your sharedSecret}";
      	
      	//passkey and timestamp to be passed for step 1 - Request Manifest File List. Comment this and use next line of code for Step 2 and 4.
        String message = "passkey=" + passkey + "&timestamp=" + time;
      
      	//passkey,timestamp and path to be passed for step 2 - Request Manifest File Location and 4 - Request UGC data file location
      	//String message = "passkey=" + passkey + "&timestamp=" + time + "&path=" + path;
      
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(sharedSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            sha256_HMAC.init(secret_key);

            String digest = bytesToHex(sha256_HMAC.doFinal(message.getBytes(StandardCharsets.UTF_8)));
            System.out.println("accessSignature:- " + digest);
            System.out.println("Timestamp:- " + time);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder(2 * bytes.length);
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
}


using System;
using System.Security.Cryptography;
using System.Text;

public class MainClass {
    public static void Main(string[] args) {
        long time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
        string passkey = "{enter your passkey}";
        string sharedSecret = "{enter your sharedSecret}";
      	//passkey and timestamp to be passed for step 1 - Request Manifest File List.Comment this and use next line of code for Step 2 and 4.
        string message = "passkey=" + passkey + "&timestamp=" + time;
      	//passkey,timestamp and path to be passed for step 2 - Request Manifest File Location and 4 - Request UGC data file location
      	//string message = "passkey=" + passkey + "&timestamp=" + time + "&path=" + path;
      
        try {
            using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(sharedSecret))) {
                byte[] digestBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
                string digest = BytesToHex(digestBytes);
                Console.WriteLine("accessSignature:- " + digest);
                Console.WriteLine("Timestamp:- " + time);
            }
        } catch (Exception e) {
            Console.WriteLine(e.Message);
        }
    }

    private static string BytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder(2 * bytes.Length);
        foreach (byte b in bytes) {
            hexString.AppendFormat("{0:x2}", b);
        }
        return hexString.ToString();
    }
}
const crypto = require('crypto');

function bytesToHex(bytes) {
  return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
}

const time = Date.now();
const passkey = "{enter your passkey}";
const sharedSecret = "{enter your sharedSecret}";
<!-- passkey and timestamp to be passed for step 1 - Request Manifest File List.Comment this and use next line of code for Step 2 and 4. -->
const message = `passkey=${passkey}&timestamp=${time}`;
<!-- passkey,timestamp and path to be passed for step 2 - Request Manifest File Location and 4 - Request UGC data file location -->
<!-- const message = `passkey=${passkey}&timestamp=${time}&path=${path}`; -->

try {
  const hmac = crypto.createHmac('sha256', sharedSecret);
  hmac.update(message);
  const digest = bytesToHex(hmac.digest());
  console.log("accessSignature:- " + digest);
  console.log("Timestamp:- " + time);
} catch (e) {
  console.error(e);
}
import sys
import hmac
import hashlib
import time

time = 	int(round(time.time() * 1000))
passkey = '{enter your passkey}'
sharedSecret = "{enter your sharedSecret}"

#passkey and timestamp to be passed for step 1 - Request Manifest File List.Comment this and use next line of code for Step 2 and 4.
message = "passkey="+passkey+"&timestamp="+str(time)

#passkey,timestamp and path to be passed for step 2 - Request Manifest File Location and 4 - Request UGC data file location
#message = "passkey="+passkey+"&timestamp="+str(time)+"&path="+path

digest = hmac.new(sharedSecret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256).hexdigest()

print("accessSignature:- "+digest)
print("Timestamp:- "+str(time))
<?php
// You may need to enable the 'openssl' extension in your php.ini file.
$time = round(microtime(true) * 1000);
$passkey = "{enter your passkey}";
$sharedSecret = "{enter your sharedSecret}";
// passkey and timestamp to be passed for step 1 - Request Manifest File List.Comment this and use next line of code for Step 2 and 4.
$message = "passkey=" . $passkey . "&timestamp=" . $time;

// passkey,timestamp and path to be passed for step 2 - Request Manifest File Location and 4 - Request UGC data file location
// $message = "passkey=" . $passkey . "&timestamp=" . $time . "&path=" . $path ;

try {
    $digest = hash_hmac('sha256', $message, $sharedSecret);
    echo "accessSignature:- " . $digest . "\n";
    echo "Timestamp:- " . $time . "\n";
} catch (Exception $e) {
    error_log($e->getMessage());
}

function bytesToHex($bytes) {
    $hexString = '';
    foreach (str_split($bytes) as $byte) {
        $hex = dechex(ord($byte) & 0xff);
        $hexString .= str_pad($hex, 2, '0', STR_PAD_LEFT);
    }
    return $hexString;
}
?>