S27: HPKE-Base content wrap + public-key directory; reject xor on send
Some checks are pending
ci / python (push) Waiting to run
ci / go (push) Waiting to run

Routing/error fields stay clear. Content is X25519-HKDF-SHA256-ChaCha20.
This commit is contained in:
George Lambert 2026-09-15 23:43:01 -04:00
parent 9cdc64b185
commit 94919185a9
8 changed files with 364 additions and 13 deletions

View file

@ -93,23 +93,65 @@ class HistoryTests(unittest.TestCase):
h.append_change(actor="", prev_text="", new_text="x")
class HpkeDirTests(unittest.TestCase):
def test_roundtrip_and_router_cannot_see_body(self):
from secure_messaging.content import routing_view, unwrap_content, wrap_content
from secure_messaging.pubkey_dir import PubKeyDir
with tempfile.TemporaryDirectory() as td:
d = PubKeyDir(Path(td))
d.create_endpoint("alice")
d.create_endpoint("pfc-repl")
avail = d.available()
self.assertIn("pfc-repl", avail["handles"])
self.assertTrue(all("sk" not in json.dumps(k) for k in avail["keys"]))
env = wrap_content(
to_handle="pfc-repl",
sender="alice",
body={"bytes_hex": "ab", "note": "secret-phi"},
directory=d,
)
self.assertEqual(env["alg"], "npe")
rv = routing_view(env)
self.assertNotIn("ct", rv)
blob = json.dumps(env)
self.assertNotIn("secret-phi", blob)
self.assertNotIn("bytes_hex", routing_view(env))
pt = unwrap_content(env, handle="pfc-repl", directory=d)
self.assertEqual(pt["note"], "secret-phi")
with self.assertRaises(Exception):
unwrap_content(env, handle="alice", directory=d)
class RouterTests(unittest.TestCase):
def test_good_passthrough(self):
from secure_messaging.envelope import seal
from secure_messaging.router import handle_send
env = seal(to="npe.inbox.abc", sender="alice", body={"note": "hello"}, mode="lab-xor", lab_key=b"lab")
r = handle_send(json.dumps(env.wire()).encode())
env = {
"to": "npe.inbox.abc",
"to_handle": "pfc-repl",
"alg": "npe",
"ct": "abcd",
"enc": "00",
"from_lookup_id": "lid-npe",
}
r = handle_send(json.dumps(env).encode())
self.assertTrue(r.accepted)
self.assertEqual(r.ack()["lookup_id"], env.from_lookup_id)
self.assertEqual(r.ack()["lookup_id"], "lid-npe")
self.assertNotIn("ct", r.ack())
self.assertEqual(r.events, [])
def test_xor_rejected_for_content(self):
from secure_messaging.router import handle_send
r = handle_send(b'{"to":"npe.inbox.x","alg":"lab-xor","ct":"ab"}')
self.assertEqual(r.error_code, "SM-BAD-ALG")
def test_missing_to_failure_path(self):
from secure_messaging.router import handle_send
from secure_messaging.error_bundle import open_sender, open_system
r = handle_send(b'{"alg":"lab-xor","ct":"ab","from_lookup_id":"lid-x"}')
r = handle_send(b'{"alg":"npe","ct":"ab","from_lookup_id":"lid-x"}')
self.assertFalse(r.accepted)
self.assertEqual(r.error_code, "SM-MISSING-TO")
subjects = [e["subject"] for e in r.events]
@ -125,9 +167,9 @@ class RouterTests(unittest.TestCase):
def test_empty_ct_and_plaintext_body(self):
from secure_messaging.router import handle_send
r = handle_send(b'{"to":"npe.inbox.x","alg":"lab-xor","ct":""}')
r = handle_send(b'{"to":"npe.inbox.x","alg":"npe","ct":""}')
self.assertEqual(r.error_code, "SM-EMPTY-CT")
r2 = handle_send(b'{"to":"npe.inbox.x","alg":"lab-xor","ct":"ab","body":{"secret":1}}')
r2 = handle_send(b'{"to":"npe.inbox.x","alg":"npe","ct":"ab","body":{"secret":1}}')
self.assertEqual(r2.error_code, "SM-PLAINTEXT-BODY")