verifySignature static method

VerificationResult verifySignature(
  1. Map<String, dynamic> payload,
  2. String secretKey,
  3. String receivedSignature,
  4. dynamic receivedTimestamp,
  5. String receivedNonce, {
  6. VerificationConfig config = const VerificationConfig(),
})

Verify a signature against expected values

payload - The original payload secretKey - The secret key receivedSignature - The signature to verify receivedTimestamp - The timestamp from request receivedNonce - The nonce from request config - Configuration (must match generation config) Returns Verification result

Example:

final verification = HmacOperations.verifySignature(
  payload,
  secretKey,
  receivedSignature,
  receivedTimestamp,
  receivedNonce,
);

if (!verification.valid) {
  print(verification.error);
}

Implementation

static VerificationResult verifySignature(
  Map<String, dynamic> payload,
  String secretKey,
  String receivedSignature,
  dynamic receivedTimestamp,
  String receivedNonce, {
  VerificationConfig config = const VerificationConfig(),
}) {
  try {
    // Generate expected signature with same config
    final expectedResult = generateSignature(
      payload,
      secretKey,
      config: config.copyWith(
        customTimestamp: receivedTimestamp,
        customNonce: receivedNonce,
      ),
    );

    // Check timestamp age
    int timestampAge = 0;

    if (receivedTimestamp is int ||
        (receivedTimestamp is String &&
            int.tryParse(receivedTimestamp) != null)) {
      final now = DateTime.now().millisecondsSinceEpoch;
      final timestampNum = receivedTimestamp is int
          ? receivedTimestamp
          : int.parse(receivedTimestamp);
      final timestampMs = timestampNum > 9999999999
          ? timestampNum
          : timestampNum * 1000;
      timestampAge = (now - timestampMs).abs();

      if (timestampAge > config.timestampTolerance) {
        return VerificationResult(
          valid: false,
          error:
              'Timestamp expired. Age: ${timestampAge}ms, Tolerance: ${config.timestampTolerance}ms',
          timestampAge: timestampAge,
        );
      }
    }

    // Timing-safe comparison
    final signatureMatch = _timingSafeEqual(
      receivedSignature,
      expectedResult.signature,
    );

    if (!signatureMatch) {
      return VerificationResult(
        valid: false,
        error: 'Signature mismatch',
        expected: expectedResult.signature,
        received: receivedSignature,
        timestampAge: timestampAge,
      );
    }

    return VerificationResult(valid: true, timestampAge: timestampAge);
  } catch (e) {
    return VerificationResult(
      valid: false,
      error: 'Verification failed: $e',
      timestampAge: 0,
    );
  }
}