Skip to main content

Authentication

Most interactions with the BVNK Crypto Payments API require the use of the API keys.

Before moving forward, make sure you have already created your Hawk Auth ID and Hawk Auth Key as described in Generate API Keys, as you won't be able to progress without them.

HAWK Authentication

BVNK employs Hawk Authentication to ensure the authenticity of requests made to our APIs. The Hash-based Message Authentication Code (HMAC) is calculated using SHA256.

While HAWK supports optional payload validation for POST and PUT data, along with response payload validation, these features are not activated for the BVNK API and can be disregarded.

Below, you will find code examples for the most commonly used programming languages.

warning

These snippets are ready to use but to reflect your specific requirements, adjust the following:

  • method
  • url
  • Hawk Auth ID
  • Hawk Auth Key
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.http.client.utils.URIBuilder;

import java.net.URI;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Random;

/**
* Main class demonstrates the generation of a Hawk authentication header.
*/
public class Main {
// The credentials used to generate the Auth headers
static String id = "<<Hawk Auth ID>>";
static String key = "<<Hawk Auth Key>>";
static String algorithm = "HmacSHA256"; // The hashing algorithm used.

// The request to be performed
static String method = "GET";
static String url = "https://api.sandbox.bvnk.com/api/v1/merchant";

public static void main(String[] args) throws Exception {
String header = hawkHeader(url, method, id, key, algorithm);
System.out.println(header);
}

/**
* This method generates a timestamp of the current time in seconds
*
* @return A timestamp in seconds
*/
public static long getTimestampInSeconds() {
return System.currentTimeMillis() / 1000;
}

/**
* This method creates a string of random alphanumeric characters
*
* @param length The required length of the string
* @return A string of random characters
*/
public static String generateNonce(int length) {
String possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

StringBuilder text = new StringBuilder(length);
Random rnd = new SecureRandom();
for (int i = 0; i < length; i++) {
text.append(possible.charAt(rnd.nextInt(possible.length())));
}
return text.toString();
}

/**
* This method generates a normalized string out of the header options
*
* @param type The request type
* @param ts The timestamp in seconds
* @param nonce The generated nonce
* @param method The HTTP method of the call
* @param url The URL of the request
* @param host The host
* @param port The port
* @param hash The hash
* @return A normalized string containing all parts to be hashed
*/
public static String generateNormalizedString(String type, long ts, String nonce, String method, String url, String host, String port, String hash) {
String headerVersion = "1";

return "hawk." + headerVersion + "." +
type + "\n" +
ts + "\n" +
nonce + "\n" +
method.toUpperCase() + "\n" +
url + "\n" +
host.toLowerCase() + "\n" +
port + "\n" +
hash + "\n" +
"\n";
}

/**
* This method generates the request Message Authentication Code (MAC) using the MAC-SHA256 hashing algorithm
*
* @param type The type to generate
* @param key The key used to generate the Auth header
* @param options The options used to generate the code
* @return a request MAC
*/
public static String generateRequestMac(String type, String key, String options) {
byte[] hmacSha256 = HmacUtils.hmacSha256(key, options);
return Base64.getEncoder().encodeToString(hmacSha256);
}

/**
* This method generates the Hawk authentication header
*
* @param uri A full URI string
* @param method The HTTP method (GET, POST, etc.)
* @param id The ID from the credentials
* @param key The key from the credentials
* @param algorithm The algorithm from the credentials
* @throws URISyntaxException Will throw an error if the provided URI string is of an invalid type.
* @return The Hawk authorization header
*/
public static String hawkHeader(String uri, String method, String id, String key, String algorithm) throws URISyntaxException {
// Application time
long timestamp = getTimestampInSeconds();

// Generate the nonce
String nonce = generateNonce(6);

// Parse URI
URI parsedUri = new URIBuilder(uri).build();
String host = parsedUri.getHost();
String port = String.valueOf(parsedUri.getPort() == -1 ? (parsedUri.getScheme().equals("http") ? 80 : 443) : parsedUri.getPort());
String resource = parsedUri.getPath() + (parsedUri.getQuery() != null ? "?" + parsedUri.getQuery() : "");

// Prepare artifacts object to be used in MAC generation
String options = generateNormalizedString("header", timestamp, nonce, method, resource, host, port, "");

// Generate the MAC
String mac = generateRequestMac("header", key, options);

// Construct Authorization header
return "Hawk id=\"" + id + "\", ts=\"" + timestamp + "\", nonce=\"" + nonce + "\", mac=\"" + mac + "\"";
}
}
warning

The HTTP method and endpoint URL significantly influence the generation of the correct hash values in your authorization header. It's crucial to ensure these values are dynamically updated to align with your actual requests. Otherwise, your requests may fail.