Construct Messages Using HTTP Signature Security

HTTP signatures use a digital signature to enable the receiver to validate the sender's authenticity and ensure that the message was not tampered with during transit. For more information about HTTP signatures, see the IETF Draft that is maintained by the IETF HTTP Working Group.
Follow these steps to implement HTTP signatures:
  1. Set the known HTTP header values.
  2. Calculate the digest HTTP header hash value.
  3. Calculate the signature hash value.
  4. Construct the
    signature
    HTTP header value using all of the other header values and the signature hash.
  5. Combine the HTTP headers and HTTP message body.
This is an example of a possible HTTP message after completing the above steps.
curl --request POST \ --url https://apitest.cybersource.com/pts/v2/payments \ --header 'content-type: application/json' \ --header 'host: apitest.cybersource.com' \ --header 'v-c-date: Thu, 01 Jan 1970 00:00:00 GMT' \ --header 'v-c-merchant-id: transacting-merchant-id' \ --header 'digest: SHA-256=tJF34ot6+Ogqc4g5SGvR63q/+hh0ptLt14=' \ --header 'signature: keyid="your-key-id", algorithm="HmacSHA256", headers="host v-c-date request-target digest v-c-merchant-id", signature="txzaNvg8S6tRtvJ9OobCEOaQTwlsT1Q73f77uqf0Idc="' \ --data '{api-request-message}'

Overview of HTTP Message Elements

An HTTP message is constructed using HTTP headers and a body.
HTTP Message Headers
Your message header must include these HTTP header fields:
HTTP Header Fields
HTTP Header Field
Description
v-c-merchant-id
Your
Cybersource
transacting merchant ID (MID).
If you are a portfolio or merchant account user, this is the transacting merchant ID that you are sending requests on behalf of.
v-c-date
The date of the transaction in the RFC1123 format. Example:
Thu, 18 Jul 2019 00:18:03 GMT
Content-Type
Also known as the Multipurpose Internet Mail Extension (MIME) type, the identifier of the media or file type resource. You can set the value to:
application/json
Host
The transaction endpoint. (
api.cybersource.com
)
signature
The digital signature, which is constructed using the values of the other headers and secured by your private key.
Digest
A hash of the message body.
Digest is not applicable for
GET
requests.
HTTP Message Body
Your API request.

Digest Hash Calculation

The value of the
digest
HTTP header is a hash that you must calculate. This hash value is used to validate the integrity of your message by the receiver.
Follow these steps to calculate the digest hash:
  1. Generate the SHA-256 hash of the JSON payload (body of the message).
  2. Encode the hashed string to Base64.
  3. Prepend
    SHA-256=
    to the front of the hash.
  4. Add the message body hash to the
    digest
    header field.
Creating a Message Hash Using the Command Line
shasum
Tool
echo -n "{"clientReferenceInformation":{"code":"TC50171_3"},"paymentInformation":{"card":{"number": "4111111111111111","expirationMonth":"12","expirationYear":"2031"}},"orderInformation":{"amountDetails": {"totalAmount":"102.21","currency":"USD"},"billTo”:{“firstName":"John","lastName":"Doe","address1": "1MarketSt","locality":"sanfrancisco","administrativeArea":"CA","postalCode":"94105","country":"US", "email":"","phoneNumber":"4158880000"}}}" | shasum -a 256
echo -n "6ae5459bc8a7d6a4b203e8a734d6a616725134088e13261f5bbcefc1424fc956" | base64
Creating a Message Hash Using the Command Line
base64
Tool
echo -n "6ae5459bc8a7d6a4b203e8a734d6a616725134088e13261f5bbcefc1424fc956" | base64
Creating a Message Hash Using C#
public static string GenerateDigest() { var digest = ""; var bodyText = "{ your JSON payload }"; using (var sha256hash = SHA256.Create()) { byte[] payloadBytes = sha256hash .ComputeHash(Encoding.UTF8.GetBytes(bodyText)); digest = Convert.ToBase64String(payloadBytes); digest = "SHA-256=" + digest; } return digest; }
Creating a Message Using Java
public static String GenerateDigest() throws NoSuchAlgorithmException { String bodyText = "{ your JSON payload }"; MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(bodyText.getBytes(StandardCharsets.UTF_8)); byte[] digest = md.digest(); return "SHA-256=" + Base64.getEncoder().encodeToString(digest); }

Signature Hash Calculation

Before you can construct the signature HTTP header value, you must first calculate the signature hash. To generate the signature hash value, you must use a Base64-encoded HMAC SHA-256 hash of the signature fields and their values.
This table describes the signature field values that you must use to calculate the signature hash.
Signature Fields
Signature Fields
Description
v-c-date
From the header, the date and time in the RFC1123 format.
For example:
Date: Thu, 18 Jul 2023, 22:18:03.
Digest
The Base64-encoded SHA-256 hash of the message body. For more information, see Digest Hash Calculation.
Example:
Digest: SHA-256=gXWufV4Zc7VkN9Wkv9jh/JuAVclqDusx3vkyo3uJFWU=
Do not include the digest with GET requests.
Host
From the header, the endpoint host.
For example:
apitest.cybersource.com
.
v-c-merchant-id
From the header, the merchant ID associated with the request.
For example:
v-c-merchant-id: mymerchantid
.
request-target
The HTTP method and endpoint resource path.
For example:
request-target: post /pts/v2/payments
.
IMPORTANT
Verify that your request-target values matches exactly the resource path. For example,
/pts/v2/payments
is not the same as
/pts/v2/payments/
.
Follow these steps to generate the signature hash value:
  1. Generate a byte array of the secret key generated previously. For more information, see Shared Secret Key Pair.
  2. Generate the HMAC SHA-256 key object using the byte array of the secret key.
  3. Concatenate a string of the required information listed above.
    For more information, see
    Creating the Validation String
    below.
  4. Generate a byte array of the validation string.
  5. Use the HMAC SHA-256 key object to create the HMAC SHA-256 hash of the validation string byte array.
  6. Base64 encode the HMAC SHA-256 hash.
Signature Hash
signature=”OuKeDxj+Mg2Bh9cBnZ/25IXJs5n+qj93FvPKYpnqtTE=”

Creating the Validation String

To create the validation string, concatenate the required information in the same order as listed in the signature header field parameter. Each item must be on a separate line, and each line should be terminated with a new line character
\n
.
Validation String Example
host:
apitest.cybersource.com
\n date: Thu, 18 Jul 2019 00:18:03 GMT\n request-target: post /pts/v2/payments/\n digest: SHA-256=gXWufV4Zc7VkN9Wkv9jh/JuAVclqDusx3vkyo3uJFWU=\n v-c-merchant-id: mymerchantid
Generating a Signature Hash in C#
private static string GenerateSignatureFromParams(string signatureParams, string secretKey) { var sigBytes = Encoding.UTF8.GetBytes(signatureParams); var decodedSecret = Convert.FromBase64String(secretKey); var hmacSha256 = new HMACSHA256(decodedSecret); var messageHash = hmacSha256.ComputeHash(sigBytes); return Convert.ToBase64String(messageHash); }
Generating a Signature Hash in Java
public static String GenerateSignatureFromParams(String keyString, String signatureParams) throws InvalidKeyException, NoSuchAlgorithmException { byte[] decodedKey = Base64.getDecoder().decode(keyString); SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "HmacSHA256"); Mac hmacSha256 = Mac.getInstance("HmacSHA256"); hmacSha256.init(originalKey); hmacSha256.update(signatureParams.getBytes()); byte[] HmachSha256DigestBytes = hmacSha256.doFinal(); return Base64.getEncoder().encodeToString(HmachSha256DigestBytes);}

Constructing the Signature Header

After you generate a signature hash, you can construct the
signature
HTTP header value.
IMPORTANT
If you are using a meta-key, set the
v-c-merchant-id
signature-header value to the meta-key creator's portfolio ID or merchant account ID. Set the
v-c-merchant-id
HTTP header value to the transacting merchant ID (MID) that you are sending a request on-behalf of.
The
signature
header field includes these parameters:
Signatures
Signature Parameter
Description
keyid
The serial number of the signing certificate/key pair. Obtain this in the
Business Center
Key Management area. For more information, see Create a Shared Secret Key Pair.
algorithm
The HMAC SHA256 algorithm used to encrypt the signature. It should be formatted:
HmacSHA256
.
headers
The signed-header values calculated in the signature:
  • host
  • v-c-date
  • request-target
  • digest
  • v-c-merchant-id
signature
The signature hash.

Signature Field Format

Signature:"keyid:"[keyid]",algorithm="[encryption algoritm]",headers="field1" "field2" "field3" "etc.", signature="[signature hash]"

Signature Example

Signature:"keyid="123abcki-key1-key2-key3-keyid1234567", algorithm="HmacSHA256", headers="host date request-target digest v-c-merchant-id", signature="hrptKYTtn/VfwAdUqkrQ0HT7jqAbagAbFC6nRGXrNzE="