Signature generation

All humm APIs are publicly accessible. In order to prevent against request-tampering, man-in-the-middle attacks, and other malicious behavior, humm requires all API requests to include a digital signature and will include a digital signature on all API responses.

For all API requests to humm, the digital signature will be verified. Responses should always be verified on the POS side before continuing.

The signing mechanism used by humm is based on HMAC-SHA256. Every individual device that communicates with humm must use its cryptographic signing-key known as the 'device-signing-key' to generate the HMAC (hash-based message authentication code). The device-signing-key is installed securely during the one-time 'device initialisation' operation.

To generate a digital signature, do the following steps:

  1. Create a string of all "x_" fields (i.e. with a name starting with "x_") in the request as key-value pairs, sorted alphabetically, and concatenated without separators.
  2. Sign the message using HMAC_SHA256 to produce a signature.

Add the 'signature' to the request and that's it!

On the humm side, we'll perform the same algorithm with the same device-signing-key for the HMAC_SHA256 to produce a matching signature. If anything changes on the request, even just a single character, then a completely different signature would be generated. A non-matching signature would result in an authorisation error.

Below is a C#.NET code snippet that demonstrates how a signature might be generated:

public static string GenerateHMAC(string apiKey, IDictionary<string,string> payloadValues)
  using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiKey)))
      string payloadSignature = 
          .Where(kvp=> kvp.Key.StartsWith("x_"))
          .Select(kvp => $"{kvp.Key}{kvp.Value}")
          .Aggregate((current, next) => $"{current}{next}");

      var rawHmac = hmac.ComputeHash(Encoding.UTF8.GetBytes(payloadSignature));

      return BitConverter.ToString(rawHmac).Replace("-", string.Empty).ToLower();