HTTP Headers
In addition to the method call, format and variables sent on the URL line (discussed in yesterday’s article), you are required to send some extra information in the headers of the outgoing HTTP request.
From the API Documentation:
- X-Searunner-apikey Your public API key you were given when signing
up for a developer account.- X-Searunner-time A float representation of “now” including
milliseconds (like that produced by the php function microtime(true))- X-Searunner-hmac-algo The algorithm used for generating the HMAC,
like sha1, sha256, MD5 etc.- X-Searunner-hmac The HEX representation of the HMAC signing the
request.The following headers are only required when sending POST data:
- X-Searunner-posthash A hash of the POST data packet.
- X-Searunner-posthash-algo The algorithm used to create the POST
hash, eg md5, sha1 etc.- Content-type The content type of the data (default:
application/octet-stream)- Content-Length The length of the POST data in bytes.
Initially, this may look like rather a lot to take in, but it is actually quite simple.
The two algorithm selection fields X-Searunner-hmac-algo
and X-Searunner-posthash-algo
give the name of the algorithm used – md5
, sha1
, sha256
etc. Letting the client specify the algorithm used lets us get around issues with buggy/missing algorithm implementations. For example, we use MD5 for the Java library as this removes the need to install a third party JCE.
Where possible you should probably try and use “sha256
” for HMAC and “sha1
” for hashing your post data, since over time we will likely “retire” the weaker algorithms.
X-Searunner-time
timestamps the request, while Content-type
and Content-Length
(for POST requests) are pretty much self explanatory.
The field X-Searunner-posthash
ensures that the POST body can not be modified, and it is a lower case hexadecimal representation of the desired HASH algorithm, taken over all the data in the POST body, take a look at this pseudo code:
hash = algorithmFactory( //X-Searunner-posthash-algo// );
hash.update( //POST DATA// );
return hex_encode(hash.final());
Finally, the field X-Searunner-hmac
contains a signature which lets the elggVoices server guarantee that it was you that sent the request (rather than someone pretending to be you) and that the contents of the request have not been modified. This is where your secret key comes in, and is the reason why it is important that you keep it safe!
From the manual:
A HMAC is a simple cryptographic signature, in this case is formed over the
following information:
- The time header eg,
12345678.90
- Your API key
- The GET query string, eg “
format=xml&method.example&variable=foo
“. It is
important to note two things, firstly that the preceding “?” character has
been dropped, and second that the order is identical to the order they
appear on the URL line.- If this is a POST request, the hash of the POST data.
Take a look at this pseudo code:
hmac_cipher = algorithmFactory( //X-Searunner-hmac-algo// );
hmac_cipher.init(//SECRET KEY//);
hmac_cipher.update( //X-Searunner-time// );
hmac_cipher.update( //X-Searunner-apikey// );
hmac_cipher.update( //GET VARIABLES IN CALL ORDER// );
if (POST CALL) hmac_cipher.update( //X-Searunner-posthash// );
return hex_encode(hmac_cipher.final());
To form the HMAC, each variable’s string representation is turned into a string of bytes. This byte string is fed in turn into the HMAC algorithm which spits out a HMAC signature which is then converted into a lower case hexadecimal string. These are Octet strings, ensure that when adding the strings to the cipher that your language doesn’t convert it into unicode!
Note that the order in which you add each field is VERY IMPORTANT.
Next comes the server response…