(1) an attacker is unable to replay a previous request
(2) an attacker is unable to modify the API request during transmission
Algorithm
To sign a request, you’ll need a few things:
- a crypto library that supports HMAC-SHA-256;
- your secret HMAC signing key;
- your HTTP request contents; and
- the current time (from a reasonably accurate clock).
The signature is calculated using the following fields:
FIELD | TYPE | VALUE | EXAMPLE |
---|---|---|---|
secret | string | HMAC secret key from SVB, provided as a string | FNAqNywCi0hmo845Ni43p06mx3l4ub7C |
timestamp | int | Number of seconds since the Unix epoch | 1490041002 |
method | string | HTTP method as an upper case string | POST |
path | string | Path to the resource | /v1/vcn |
params | string | Params passed in the URL (if any) | foo=bar&baz=quux |
body | string | Body of the request (if any) | See below |
Using this Algorithm
- Let
+
be a function that concatenates strings, and let"\n"
indicate a newline character; - Let
HMAC
be a function that calculates an HMAC from a string and a secret key, and letHEX
be a function that returns the string hexadecimal representation of its input; then
The signature is:
HEX( HMAC( your_secret_key,
timestamp + "\n" +
method + "\n" +
path + "\n" +
query + "\n" +
body ))
Notes:
body
is only used for JSON bodies with theapplication/json
type. if the body is any other type or is missing, then an empty string should be used instead.path
always begins with a slash.query
omits the leading question mark, and is an empty string if there is no query string.
Headers
After calculating the signature, add the following two HTTP headers to your request:
X-Timestamp
:timestamp
, from step (2) aboveX-Signature
: the request signature
For a request to be considered valid, it must have a timestamp within 30 seconds of the server’s time as well as a valid signature.
Code Samples and Examples
SVB API documentation includes Python and Postman examples to simplify client integrations. There are sample Python code snippets and Postman collections for each API product, on the respective API product page.
HMAC Postman Pre-Request Script
HMAC signing is a required step when accessing SVB APIs from Postman.
-
SVB Postman collections already include the HMAC signing script as a "pre-request" script.
The script can be accessed through clicking"Edit"
on collection and navigating to"pre-request script"
tab.For reference, pre-request script is included below:
Note: Signature variable on the below Postman script is the secret that is shared by the SVB team. If Postman script is used, there is no need to manually add X-Signature and X-Timestamp on the request headers.
let apigee = 1; var signature = ""; const { Property, Url } = require('postman-collection'); var moment = require("moment") var requestTimeStamp = moment(new Date().toUTCString()).valueOf() / 1000; let resolvedUrl = Property.replaceSubstitutions(pm.request.url.toJSON(), pm.variables.toObject()),newUrl = new Url(resolvedUrl); var dataUrl = requestTimeStamp + "\n" + pm.request.method + "\n" + newUrl.getPath() + "\n" + newUrl.getQueryString() + "\n"; while (dataUrl.indexOf("{{") >= 0) { var variableName = dataUrl.substring(dataUrl.indexOf("{{") + 2, dataUrl.indexOf("}}")); var variableValue = pm.globals.get(variableName); dataUrl = dataUrl.replace("{{" + variableName + "}}", variableValue); } while (apigee && dataUrl.indexOf("[") >= 0) { dataUrl = dataUrl.replace("[", "%5B") } while (apigee && dataUrl.indexOf("]") >= 0) { dataUrl = dataUrl.replace("]", "%5D") } while (apigee && dataUrl.indexOf("\"") >= 0) { dataUrl = dataUrl.replace("\"", "%22") } if (pm.request.body) dataUrl = dataUrl.concat(pm.request.body); console.log(dataUrl) var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, signature); var hash = hmac.update(dataUrl).finalize(); pm.request.headers.add({ 'key': 'X-Timestamp', 'value': requestTimeStamp }); pm.request.headers.add({ 'key': 'X-Signature', 'value': '' + hash });
Once the account is ready, update credentials (api_key and secret) on the sandbox or production environment variables.
Note: Production api key will be denoted by the "live_" string in the beginning of the api key.