API Security - HMAC Hash

Introduction

Beginning with v12 of the API, an SHA-1 HMAC hash calculation is offered to increase the security of transaction processing through this interface. Use of this hash value is mandatory for every transaction when utilizing the v12 version of the WS API. 

HMAC Key & Calculator

The key used for the HMAC calculation can be obtained through the Realtime Payment Manager interface when using a Merchant Administrator account. To access the key, navigate to the Administration -> Terminals area, then by clicking on the desired terminal. Note that each terminal will have a key unique to it.

Clicking "Generate New Key" will generate a new key, and an email notice will be sent to all Merchant Administrators of that account alerting them of this change. The key will be displayed in plain text when it is generated but will not be saved until the "Update" button is clicked. Note:  After this step has been taken, it will not be possible to view the key in plain text again so if this value is not stored it will be necessary to generate a new key.

 

 

HMAC Signature Calculator Notes:

  • The "Request Content Type" options in the calculator have the following equivalencies: SOAP ("text/xml"), REST ("application/xml"), JSON ("application/json")
  • If a character set is included in the Content Type header, it must be used in the calculation as well (there is no provision for this in the calculator)

 

HMAC Calculation

The HMAC hash calculation itself is done with the SHA-1 algorithm. The calculation itself is done on the concatenation of the following:

Request Method + \n
+ Content-type + \n
+ Content Digest (SHA-1) + \n
+ Sending Time + \n
+ Request URL

The key used for the hash calculation is the API key discussed earlier. Note that the result of the HMAC calculation needs to be output in binary format, then base64 encoded.

The Content Digest header, which is part of the hash calculation, is a SHA-1 hash of the content of the request (for example, the XML or JSON data itself) in hexadecimal format using lowercase letters. Note that this calculation does not use a key and shouldn't be confused with the authorization hash calculation. Payeezy Gateway also performs this calculation on the API response messages returned to the merchant if they optionally wish to check use it to check data integrity.

The hash calculation is submitted as part of an "authorization" HTML header. The format of the authorization header can be seen in the cURL example below. Note that the text "Payeezy_Gateway_API" needs to be submitted after the authorization declaration, followed by the key ID separated from the hash calculation with a colon (":") character.

curl -i \
     -H 'authorization: GGE4_API 14:VH+8ZLHqn9aSkfEOMeVzpM2xr20=' \
     -H 'x-gge4-date: 2012-09-24T23:43:23Z' \
     -H 'x-gge4-content-sha1: 26750e3c729b87418691c703ce44c18ff8b88201' \ -H "Content-Type: application/xml" \ -H "Accept: text/xml" \ -d '<?xml version="1.0" encoding="UTF-8"?> <Transaction> <Transaction_Type>00</Transaction_Type> <DollarAmount>10.00</DollarAmount> <Expiry_Date>0415</Expiry_Date> <CardHoldersName>Official Keef</CardHoldersName> <Reference_No>Jigsaw Puzzle</Reference_No> <Customer_Ref>Factory Girl</Customer_Ref> <Reference_3>Salt of the Earth</Reference_3> <ExactID>A02345-01</ExactID> <Password>Password1</Password> <Card_Number>4111111111111111</Card_Number> </Transaction>' \ https://api.gateway.firstdata.com/transaction/v12

 

Date Header

The final piece of the authorization process is the inclusion of the "x-gge4-date" header which is used to supply the current UTC time in ISO-8601 format. This time must be within 5 minute of the current time in order for authorization to be accepted.

 

Python HMAC Calculation Code Sample

from hashlib import sha1
from time import gmtime, strftime
import base64
import hmac
import httplib

payeezy_gateway_date = strftime("%Y-%m-%dT%H:%M:%S", gmtime()) + 'Z'
uri = '/transaction/v12'
key_id = '111'
key = '_qu347dd5h~n5sGtInzEi0Bv4u82E41R'
transaction_body = 'Some XML here'
method = 'POST'
content_digest = sha1(transaction_body).hexdigest()
content_type = 'text/xml'
host = 'api.gateway.payeezy.com'
headers = { 'Content-Type': content_type,
	    'x-gge4-content-sha1': content_digest,
	    'x-gge4-date': payeezy_date, 'Authorization': 'Payeezy_Gateway_API ' + key_id + ':' + base64.b64encode(hmac.new(key, method + "\n" + content_type + "\n" + content_digest + "\n" + payeezy_gateway_date + "\n" + uri.split('?')[0], sha1).digest()) } conn = httplib.HTTPSConnection(host) conn.request(method, uri, transaction_body, headers) print conn.getresponse().read()
Powered by Zendesk