verifySignatureBytes method
Like verifySignature, for a body given as the raw bytes of the request.
Implementation
void verifySignatureBytes({
required List<int> body,
required Map<String, String> headers,
}) {
final id = _header(headers, idHeader);
final timestampText = _header(headers, timestampHeader);
final signatures = _header(headers, signatureHeader);
if (!_timestampPattern.hasMatch(timestampText)) {
throw const InvalidSignatureException(
'The "webhook-timestamp" header is not a Unix timestamp in seconds.',
);
}
final timestamp = DateTime.fromMillisecondsSinceEpoch(
int.parse(timestampText) * 1000,
isUtc: true,
);
final now = _clock();
if (now.difference(timestamp).abs() > tolerance) {
throw TimestampOutOfToleranceException(
timestamp: timestamp,
now: now,
tolerance: tolerance,
);
}
final expected = _compute(_hmac, id, timestampText, body);
var matched = false;
// The header holds space-separated `version,signature` pairs. Some
// frameworks join repeated headers with commas, so split on both and
// read the tokens in pairs: base64 never contains a comma.
final tokens = signatures.split(_separators);
for (var i = 0; i + 1 < tokens.length; i++) {
if (tokens[i] != 'v1') continue;
// Check every candidate so the time taken does not reveal which one
// matched.
if (_constantTimeEquals(tokens[++i], expected)) matched = true;
}
if (!matched) throw const InvalidSignatureException();
}