import time from infrasynth.webhooks.signature import sign_payload, verify_signature class TestSignPayload: def test_signature_format(self): signature = sign_payload("secret", '{"a": 1}') assert signature.startswith("t=") assert ",v1=" in signature def test_signature_changes_with_payload(self): sig1 = sign_payload("secret", "payload-one") sig2 = sign_payload("secret", "payload-two") assert sig1 != sig2 def test_signature_changes_with_secret(self): sig1 = sign_payload("secret-a", "payload") sig2 = sign_payload("secret-b", "payload") assert sig1 != sig2 def test_timestamp_param(self): signature = sign_payload("secret", "payload", timestamp=1000) assert signature.startswith("t=1000,") class TestVerifySignature: def test_verify_roundtrip(self): payload = '{"event": "ticket.created"}' signature = sign_payload("secret", payload) assert verify_signature("secret", payload, signature) is True def test_wrong_secret_rejected(self): payload = "payload" signature = sign_payload("secret-a", payload) assert verify_signature("secret-b", payload, signature) is False def test_tampered_payload_rejected(self): signature = sign_payload("secret", "original") assert verify_signature("secret", "tampered", signature) is False def test_expired_timestamp_rejected(self): old_timestamp = int(time.time()) - 600 signature = sign_payload("secret", "payload", timestamp=old_timestamp) assert verify_signature("secret", "payload", signature, tolerance_seconds=300) is False def test_fresh_timestamp_accepted(self): signature = sign_payload("secret", "payload") assert verify_signature("secret", "payload", signature, tolerance_seconds=300) is True def test_malformed_header_rejected(self): assert verify_signature("secret", "payload", "garbage") is False assert verify_signature("secret", "payload", "") is False assert verify_signature("secret", "payload", "t=x,v1=y") is False