API Authentication: Generating HMAC digest in PHP and Java


May 20, 2015 2 minutes read

User authentication is an important part of the web service API design. One of the common approach is the Hash-based Message Authentication Code – HMAC. Used together with transport level security it provides reliable mechanizm of user authentication and message integrity validation.

Imagine, we want to create java web service for our customers. Data encryption will be guaranteed by using https connection with TLS. We will implement API user authentication by using public API Key ID and a API Key Secret. User should generate an API Key: unique pair of Key ID and a Key Secret for his application. User should send that Key ID, message payload and a digest with every request. Digest is generated by signing all HTTP headers and message payload with Key Secret. (see Amazon’s recommendations)

In PHP there is a function hash_hmac for generating keyed hash value using the HMAC method. Here is the example:

<?php

$keyId = 'd36cb306-9341-466f-a794-d49fbc485d8b';
$payload = '{"command": "buy", "amount":10, currency":"EURUSD"}';
$secret = 'se1cr2et3w0r4d';

echo 'SHA-512 HMAC Digest: ', hash_hmac('sha512', $keyId . $payload, $secret);

Output:

SHA-512 HMAC Digest: 577a7927f55bc6ed1eaec08f7298e7c7596b6f951c4c6e8f24324fd9a1f0790adfdecbbd5ab73ad543fec7e6c3c23246a5dd8fae526e0b802ae99faccd06a29c

Call PHP function hash_algos to get a list of supported algorithms.

How to validate the digest in Java:

String apiKey = ... // X-KEY
byte[] secret = ... //
String rawPayload = ...
String receivedDigest = ... //
...

Mac digest = Mac.getInstance("HmacSHA512");
SecretKeySpec secretKey = new SecretKeySpec(secret, HMAC_SHA_512);

digest.init(secretKey);
digest.update(apiKey.getBytes(StandardCharsets.UTF_8));
digest.update(rawPayload.getBytes(StandardCharsets.UTF_8));
final byte[] expectedDigest = digest.doFinal();
digest.reset();

final byte[] receivedDigestBytes = DatatypeConverter.parseHexBinary(receivedDigest);
if (!MessageDigest.isEqual(receivedDigestBytes, expectedDigest)) {
    // invalid digest
}

References

See Also

Web Security Resources

Here are some useful links to security resources: OWASP to 10 v.2013– A list of the 10 Most Critical Web Application Security Risks. OWASP: list of website security attacks OWASP: list of website vulnerabilities OWASP Development Guide – The OWASP Developer Guide 2014 is a dramatic re-write of one of OWASP’s first and most downloaded projects. The focus moves from countermeasures and weaknesses to secure software engineering. The Developer Guide 2014 is a «first principles» book - it’s not specific to any one language or framework, as they all borrow ideas and syntax from each other.

Booting Spring Webapp

Spring Boot is an excellent tool to bootstrap java application. Most of the references mention how to create a standalone java application, optionally with embedded web server (tomcat or jetty). But Spring Boot supports also creating web applications intended to run within servlet container.

Base64 Variants in Java 8

You most likely used Base64 encoding. It’s about encoding any sequence of data as a printable string (digits, lower case and upper case letters). But Base64 has variations. E.g., not every Base64 variant allows safe transfer of any data as URL parameters. For that purpose there is a special dialect of Base64: Url-safe encoding.

logo   Never miss a story, subscribe to our newsletter