HMAC and AES Authentication
The following article outlines the details for HMAC authentication and AES encryption. HMAC authentication is used for authenticating API calls as well as authenticating logged-in users to view their subscriptions within the My Account section of your site. Please refer to the specific documentation flow to determine how this authentication is used (for example, API header, cookie, etc). AES encryption is typically used solely for encrypting the credit card expiration date when that data is passed to and from Ordergroove via API.
HMAC Authentication
Item | Definition |
RAW_DATA_POINT | One data point used as the input for the signature generation function. For the purpose of this integration, this will always be the user ID. |
SECONDS_SINCE_EPOCH | The Unix epoch (or Unix time, POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT). This will be a 10-digit number. |
SHA-256 | The hash function set as a parameter of the HMAC signature generation function. |
HASH_KEY | Secret hash key provided to you by your Ordergroove team, unique to your merchant. |
The signature is created in the following way:
Using the HMAC hash function, generate a signature using SHA-256. The function input also includes the concatenation of RAW_DATA_POINT and SECONDS_SINCE_EPOCH (see definition above) with a pipe character in between, and the secret hash key.
If you are sending the signature in an HTTP request, you must URL encode it before sending.
Example:
signature=hash_hmac("sha256","<RAW_DATA_POINT>|<SECONDS_SINCE_EPOCH>","<HASH_KEY>");
The HMAC Signature Tool
The HMAC Generator tool contains a form with which you can create a valid HMAC signature. This tool is most often helpful to confirm that your integration is correctly generating the signature that Ordergroove is anticipating.
You’ll find this utility within Ordergroove under Developers > HMAC Generator.
Using the Tool
In the Unique Identifier field, enter the customer ID from your e-commerce platform. If no hash key is entered, Ordergroove will use the merchant-level hash key configured for your account in the Ordergroove environment in which you are using the utility.
Finally, the timestamp will automatically generate with the current 10-digit Unix timestamp but can be updated to match the one used in your test request.
When using an HMAC signature for API requests and setting the og_auth cookie, Ordergroove requires that the timestamp is within the last two hours.
AES Encryption
Item | Description |
Algorithm | AES |
Mode | ECB |
Padding | Right-padded with '{' characters |
Block-size | 32 bytes |
First, with the hash key, generate an AES cipher using ECB mode. ie: cipher - AES.new(hash_key)
To encode data:
- Pad the data you want to encode with the "{" character so that it is a multiple of 32 characters in length.
- Pseduo code example: (data + (32 - length(data) modulus 32) * "{" )
- If data="something" the result of padding data would be "something{{{{{{{{{{{{{{{{{{{{{{{"
- Encrypt the padded data with the cipher
- Pseudo code example: cipher.encrypt(padded_data)
To decode data:
- Decrypt with the cipher
- Pseudo code example: cipher.decrypt()
- Remove all the padding characters
- Pseudo code example: decrypted_data.rstrip("{")
Examples:
<?php
class Example {
const CYPHER = MCRYPT_RIJNDAEL_128;
const MODE = MCRYPT_MODE_ECB;
const BLOCK_SIZE = 32;
const PADDING = '{';
protected $_hashKey = null;
public function setHashKey($data) {
$this->_hashKey = $data;
}
public function getHexHashKey() {
return pack('H*', bin2hex($this->_hashKey));
}
public function pad($data) {
$data . str_repeat(self::PADDING,(self::BLOCK_SIZE - (strlen($data) % self::BLOCK_SIZE)));
}
public function strip($data) {
return str_replace(self::PADDING, '', $data);
}
public function encrypt($data) {
return trim(base64_encode(mcrypt_encrypt(self::CYPHER, $this->getHexHashKey(), $data, self::MODE)));
}
public function decrypt($data)
{
return $this->strip(mcrypt_decrypt(self::CYPHER,$this->getHexHashKey(),base64_decode($data),self::MODE));
}
}
$obj = new Example;
$obj->setHashKey('Mt!ZQ45q&GHsgiRD8{NB-_h87#rjvbn0');
$ccNumber = '4111111111111111';
echo "Original credit card number: $ccNumber<BR>";
$encryptedCcNumber = $obj->encrypt($ccNumber);
echo "Encrypted credit card number: $encryptedCcNumber<BR>";
$unencryptedCcNumber = $obj->decrypt($encryptedCcNumber);
echo "Unencrypted credit card number: $unencryptedCcNumber";
BLOCK_SIZE = 32
PADDING = '{'
def pad(s):
return s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
def EncodeAES(c, s):
return base64.b64encode(c.encrypt(pad(s)))
def DecodeAES(c, e):
return c.decrypt(base64.b64decode(e)).rstrip(PADDING)
hash_key = 'Mt!ZQ45q&GHsgiRD8{NB-_h87#rjvbn0'
cipher = AES.new(hash_key)
encoded = EncodeAES(cipher, "something")
something = DecodeAES(cipher, encoded)
Updated 9 months ago