"""Tests for raycast_api.signing.hmac.""" from __future__ import annotations import hashlib import hmac as _hmac import pytest from raycast_api.signing.hmac import HMACSigner, encode_key, encode_output, hash_body FAKE_SECRET = "DEAD" + "BEEF" * 15 class TestEncodeKey: def test_utf8_passes_secret_through_as_bytes(self) -> None: assert encode_key(FAKE_SECRET, "utf-8") == FAKE_SECRET.encode("utf-8") def test_hex_decoding_supported_for_other_specs(self) -> None: assert encode_key("deadbeef", "hex") == bytes.fromhex("deadbeef") def test_unsupported_encoding_raises(self) -> None: with pytest.raises(ValueError): encode_key(FAKE_SECRET, "rot13") class TestEncodeOutput: def test_hex_lower(self) -> None: assert encode_output(b"\xde\xad\xbe\xef", "hex-lower") == "deadbeef" def test_hex_upper(self) -> None: assert encode_output(b"\xde\xad\xbe\xef", "hex-upper") == "DEADBEEF" def test_base64(self) -> None: assert encode_output(b"\x00\x01\x02\x03", "base64") == "AAECAw==" def test_unsupported_encoding_raises(self) -> None: with pytest.raises(ValueError): encode_output(b"abc", "rot13") class TestHashBody: def test_sha256_lowercase_hex(self) -> None: assert hash_body(b"hello", "SHA-256") == hashlib.sha256(b"hello").hexdigest() def test_empty_body_hash(self) -> None: assert hash_body(b"", "SHA-256") == hashlib.sha256(b"").hexdigest() def test_bad_algorithm(self) -> None: with pytest.raises(ValueError): hash_body(b"x", "MD-not-a-thing") class TestHMACSigner: def test_known_vector(self) -> None: signer = HMACSigner( FAKE_SECRET, algorithm="SHA-256", key_encoding="utf-8", output_encoding="hex-lower", ) message = b"some.canonical.string" expected = _hmac.new( FAKE_SECRET.encode("utf-8"), message, hashlib.sha256 ).hexdigest() assert signer.sign(message) == expected def test_signer_is_reusable(self) -> None: signer = HMACSigner( FAKE_SECRET, algorithm="SHA-256", key_encoding="utf-8", output_encoding="hex-lower", ) a = signer.sign(b"first message") b = signer.sign(b"second message") assert a != b assert signer.sign(b"first message") == a def test_algorithm_name_is_normalised(self) -> None: a = HMACSigner( FAKE_SECRET, algorithm="SHA-256", key_encoding="utf-8", output_encoding="hex-lower", ) b = HMACSigner( FAKE_SECRET, algorithm="sha256", key_encoding="utf-8", output_encoding="hex-lower", ) assert a.sign(b"x") == b.sign(b"x")