95 lines
2.8 KiB
Python
95 lines
2.8 KiB
Python
"""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")
|