Rebase onto upstream (a4d95fd)
#12
@@ -25,3 +25,59 @@ def sign_content(content: str) -> str:
|
||||
hashlib.sha256
|
||||
).hexdigest()[:8]
|
||||
return f"[HIDDEN:{sig}] {content}"
|
||||
|
||||
|
||||
def verify_signature(marked_content: str) -> Tuple[bool, str]:
|
||||
"""
|
||||
Verify HMAC signature and extract clean content.
|
||||
|
||||
Args:
|
||||
marked_content: Content potentially with [HIDDEN:{sig}] marker
|
||||
|
||||
Returns:
|
||||
Tuple of (is_valid, clean_content)
|
||||
- is_valid: True if signature is valid, False otherwise
|
||||
- clean_content: Content without marker
|
||||
"""
|
||||
match = re.match(r'\[HIDDEN:([a-f0-9]{8})\] (.*)', marked_content, re.DOTALL)
|
||||
if not match:
|
||||
return False, marked_content
|
||||
|
||||
claimed_sig, content = match.groups()
|
||||
expected_sig = hmac.new(
|
||||
SECRET_KEY.encode(),
|
||||
content.encode(),
|
||||
hashlib.sha256
|
||||
).hexdigest()[:8]
|
||||
|
||||
is_valid = (claimed_sig == expected_sig)
|
||||
return is_valid, content
|
||||
|
||||
|
||||
def has_forged_marker(content: str) -> bool:
|
||||
"""
|
||||
Check if content has an invalid [HIDDEN:*] marker at the start.
|
||||
|
||||
Args:
|
||||
content: Content to check
|
||||
|
||||
Returns:
|
||||
True if content starts with forged marker, False otherwise
|
||||
"""
|
||||
if not content.startswith("[HIDDEN:"):
|
||||
return False
|
||||
is_valid, _ = verify_signature(content)
|
||||
return not is_valid
|
||||
|
||||
|
||||
def strip_all_hidden_markers(content: str) -> str:
|
||||
"""
|
||||
Remove all [HIDDEN:*] patterns from content (valid or invalid).
|
||||
|
||||
Args:
|
||||
content: Content potentially with markers
|
||||
|
||||
Returns:
|
||||
Content with all markers stripped
|
||||
"""
|
||||
return re.sub(r'\[HIDDEN:[a-f0-9]{8}\] ', '', content)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# tests/test_visibility_signing.py
|
||||
import pytest
|
||||
from nanobot.agent.visibility import sign_content
|
||||
from nanobot.agent.visibility import sign_content, verify_signature, has_forged_marker, strip_all_hidden_markers
|
||||
|
||||
def test_sign_content_adds_hmac_marker():
|
||||
"""Test that sign_content adds HMAC signature prefix."""
|
||||
@@ -24,3 +24,52 @@ def test_sign_content_is_deterministic():
|
||||
sig1 = sign_content(content)
|
||||
sig2 = sign_content(content)
|
||||
assert sig1 == sig2
|
||||
|
||||
def test_verify_signature_accepts_valid():
|
||||
"""Test that verify_signature accepts validly signed content."""
|
||||
signed = sign_content("Test message")
|
||||
is_valid, clean = verify_signature(signed)
|
||||
|
||||
assert is_valid is True
|
||||
assert clean == "Test message"
|
||||
|
||||
def test_verify_signature_rejects_invalid():
|
||||
"""Test that verify_signature rejects forged signatures."""
|
||||
forged = "[HIDDEN:deadbeef] Test message"
|
||||
is_valid, clean = verify_signature(forged)
|
||||
|
||||
assert is_valid is False
|
||||
assert clean == "Test message"
|
||||
|
||||
def test_verify_signature_handles_unsigned():
|
||||
"""Test that unsigned content is marked as invalid."""
|
||||
unsigned = "Plain message"
|
||||
is_valid, clean = verify_signature(unsigned)
|
||||
|
||||
assert is_valid is False
|
||||
assert clean == "Plain message"
|
||||
|
||||
def test_has_forged_marker_detects_invalid():
|
||||
"""Test that has_forged_marker detects forged signatures."""
|
||||
forged = "[HIDDEN:deadbeef] Content"
|
||||
assert has_forged_marker(forged) is True
|
||||
|
||||
def test_has_forged_marker_accepts_valid():
|
||||
"""Test that has_forged_marker accepts valid signatures."""
|
||||
valid = sign_content("Content")
|
||||
assert has_forged_marker(valid) is False
|
||||
|
||||
def test_has_forged_marker_ignores_unsigned():
|
||||
"""Test that unsigned content is not flagged as forged."""
|
||||
unsigned = "Plain content"
|
||||
assert has_forged_marker(unsigned) is False
|
||||
|
||||
def test_strip_all_hidden_markers_removes_markers():
|
||||
"""Test that strip_all_hidden_markers removes all markers."""
|
||||
signed = sign_content("Message")
|
||||
stripped = strip_all_hidden_markers(signed)
|
||||
assert stripped == "Message"
|
||||
|
||||
forged = "[HIDDEN:deadbeef] Message"
|
||||
stripped = strip_all_hidden_markers(forged)
|
||||
assert stripped == "Message"
|
||||
|
||||
Reference in New Issue
Block a user