12 October 2023
11 months ago by Encoding.com Product Team #2
HTTP(s) Notification Signature
Added custom request header for security check of HTTP(s) notifications.
For each HTTP(s) notification we add special HTTP header VG-Signature which contains at least 2 comma separated parameters (in future we may add more):
- t – timestamp
- v1 – hash-based message authentication code (HMAC) with SHA-256
VG-Signature: t=[TimeStamp],v1=[Signature]
To verify signature, you should complete the following steps:
- Split the header using the
,
character as the separator to get a list of elements. Split each element using the=
character as the separator to get a prefix and value pair. The value for the prefixt
corresponds to the timestamp, andv1
corresponds to the signature. - Prepare the
signed_message
string. Thesigned_message
string is created by concatenating:- the timestamp (
t
value) - the
.
character - request body
- the timestamp (
- Compute an HMAC with the SHA256 hash function. Use your api key as the
key
, and use thesigned_message
string as the message. - Compare the signature in the header to the expected signature.
You may also compute the difference between the current timestamp and the received timestamp, and decide if the difference is within your tolerance.
Implementation samples
const {createHmac} = require('crypto');
function verify_signature (header, request) {
const [[,timestamp],[,signature]] = header.split(',').map(p => p.split('='))
const signed_message = `${timestamp}.${request}`;
const hmac = createHmac('sha256', '<<key>>');
const expected_signature = hmac.update(signed_message).digest('hex');
return expected_signature === signature;
}
const header = 't=[timestamp],v1=[signature]';
const request = '[HTTPRequestBody]';
console.log(verify_signature(header, request) ? 'ok' : 'fail');
function verify_signature (string $header, string $request)
{
[[$t, $timestamp], [$sgn, $signature]] = array_map(
fn ($p) => explode('=', $p),
explode(',', $header)
);
$signed_message = sprintf('%s.%s', $timestamp, $request);
$expected_signature = hash_hmac(
'sha256',
$signed_message,
'<<key>>'
);
return $expected_signature === $signature;
}
$header = 't=[timestamp],v1=[signature]';
$request = '[HTTPRequestBody]';
echo verify_signature($header, $request) ? 'ok' : 'fail';
import hmac
import hashlib
def verify_signature(header, request):
ts, sgn, * other = header.split(',')
t, timestamp, * other = ts.split('=');
v, signature, * other = sgn.split('=');
signed_message = '{}.{}'.format(timestamp,request)
expected_signature = hmac.new(
bytes("<<key>>", 'utf-8'),
bytes(signed_message, 'latin-1'),
hashlib.sha256
).hexdigest()
return expected_signature == signature
header = "t=[timestamp],v1=[signature]"
request = "[HTTPRequestBody]"
print("ok" if verify_signature(header, request) else "fail")