mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-06-03 21:08:13 +02:00
348 lines
11 KiB
Python
348 lines
11 KiB
Python
import base64
|
|
import json
|
|
import pytest
|
|
|
|
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
from cryptography.hazmat.primitives import serialization
|
|
|
|
from services.mesh import mesh_hashchain, mesh_crypto, mesh_protocol, mesh_schema
|
|
|
|
|
|
def test_infonet_ingest_accepts_valid_event(tmp_path, monkeypatch):
|
|
monkeypatch.setattr(mesh_hashchain, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_hashchain, "CHAIN_FILE", tmp_path / "infonet.json")
|
|
|
|
inf = mesh_hashchain.Infonet()
|
|
|
|
priv = ed25519.Ed25519PrivateKey.generate()
|
|
pub = priv.public_key().public_bytes(
|
|
encoding=serialization.Encoding.Raw,
|
|
format=serialization.PublicFormat.Raw,
|
|
)
|
|
pub_b64 = base64.b64encode(pub).decode("utf-8")
|
|
node_id = mesh_crypto.derive_node_id(pub_b64)
|
|
|
|
payload = mesh_protocol.normalize_payload(
|
|
"message",
|
|
{"message": "hello", "destination": "broadcast", "channel": "LongFast", "priority": "normal", "ephemeral": False},
|
|
)
|
|
sig_payload = mesh_crypto.build_signature_payload(
|
|
event_type="message", node_id=node_id, sequence=1, payload=payload
|
|
)
|
|
signature = priv.sign(sig_payload.encode("utf-8")).hex()
|
|
|
|
evt = mesh_hashchain.ChainEvent(
|
|
prev_hash=mesh_hashchain.GENESIS_HASH,
|
|
event_type="message",
|
|
node_id=node_id,
|
|
payload=payload,
|
|
sequence=1,
|
|
signature=signature,
|
|
public_key=pub_b64,
|
|
public_key_algo="Ed25519",
|
|
protocol_version=mesh_protocol.PROTOCOL_VERSION,
|
|
network_id=mesh_protocol.NETWORK_ID,
|
|
)
|
|
result = inf.ingest_events([evt.to_dict()])
|
|
|
|
assert result["accepted"] == 1
|
|
assert inf.head_hash == evt.event_id
|
|
info = inf.get_info()
|
|
assert info["known_nodes"] == 1
|
|
assert info["author_nodes"] == 1
|
|
assert info["total_events"] == 1
|
|
assert info["event_types"]["message"] == 1
|
|
|
|
|
|
def test_verify_node_binding_accepts_current_and_compat_ids_only(monkeypatch):
|
|
priv = ed25519.Ed25519PrivateKey.generate()
|
|
pub = priv.public_key().public_bytes(
|
|
encoding=serialization.Encoding.Raw,
|
|
format=serialization.PublicFormat.Raw,
|
|
)
|
|
pub_b64 = base64.b64encode(pub).decode("utf-8")
|
|
|
|
current = mesh_crypto.derive_node_id(pub_b64)
|
|
compat = mesh_crypto.derive_node_id(pub_b64, legacy=True)
|
|
legacy = (
|
|
f"{mesh_crypto.NODE_ID_PREFIX}"
|
|
f"{current[len(mesh_crypto.NODE_ID_PREFIX):len(mesh_crypto.NODE_ID_PREFIX) + 8]}"
|
|
)
|
|
|
|
monkeypatch.setenv("MESH_DEV_ALLOW_LEGACY_COMPAT", "true")
|
|
monkeypatch.setenv("MESH_BLOCK_LEGACY_NODE_ID_COMPAT", "false")
|
|
monkeypatch.setenv("MESH_ALLOW_LEGACY_NODE_ID_COMPAT_UNTIL", "2099-01-01")
|
|
from services.config import get_settings
|
|
|
|
get_settings.cache_clear()
|
|
try:
|
|
assert mesh_crypto.verify_node_binding(current, pub_b64)
|
|
assert mesh_crypto.verify_node_binding(compat, pub_b64)
|
|
assert not mesh_crypto.verify_node_binding(legacy, pub_b64)
|
|
finally:
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def test_infonet_append_rejects_missing_signature_fields(tmp_path, monkeypatch):
|
|
monkeypatch.setattr(mesh_hashchain, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_hashchain, "CHAIN_FILE", tmp_path / "infonet.json")
|
|
|
|
inf = mesh_hashchain.Infonet()
|
|
payload = mesh_protocol.normalize_payload(
|
|
"message",
|
|
{"message": "hello", "destination": "broadcast", "channel": "LongFast", "priority": "normal", "ephemeral": False},
|
|
)
|
|
|
|
try:
|
|
inf.append(
|
|
event_type="message",
|
|
node_id="!sb_test",
|
|
payload=payload,
|
|
sequence=1,
|
|
)
|
|
assert False, "Expected missing signature fields to be rejected"
|
|
except ValueError as exc:
|
|
assert "signature" in str(exc).lower()
|
|
|
|
|
|
def test_infonet_load_quarantines_and_resets_on_hash_mismatch(tmp_path, monkeypatch):
|
|
monkeypatch.setattr(mesh_hashchain, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_hashchain, "CHAIN_FILE", tmp_path / "infonet.json")
|
|
|
|
priv = ed25519.Ed25519PrivateKey.generate()
|
|
pub = priv.public_key().public_bytes(
|
|
encoding=serialization.Encoding.Raw,
|
|
format=serialization.PublicFormat.Raw,
|
|
)
|
|
pub_b64 = base64.b64encode(pub).decode("utf-8")
|
|
node_id = mesh_crypto.derive_node_id(pub_b64)
|
|
payload = mesh_protocol.normalize_payload(
|
|
"message",
|
|
{"message": "hello", "destination": "broadcast", "channel": "LongFast", "priority": "normal", "ephemeral": False},
|
|
)
|
|
sig_payload = mesh_crypto.build_signature_payload(
|
|
event_type="message", node_id=node_id, sequence=1, payload=payload
|
|
)
|
|
signature = priv.sign(sig_payload.encode("utf-8")).hex()
|
|
evt = mesh_hashchain.ChainEvent(
|
|
prev_hash=mesh_hashchain.GENESIS_HASH,
|
|
event_type="message",
|
|
node_id=node_id,
|
|
payload=payload,
|
|
sequence=1,
|
|
signature=signature,
|
|
public_key=pub_b64,
|
|
public_key_algo="Ed25519",
|
|
protocol_version=mesh_protocol.PROTOCOL_VERSION,
|
|
network_id=mesh_protocol.NETWORK_ID,
|
|
).to_dict()
|
|
evt["event_id"] = "tampered"
|
|
mesh_hashchain.CHAIN_FILE.write_text(
|
|
json.dumps({"events": [evt], "head_hash": "tampered", "node_sequences": {node_id: 1}}),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
inf = mesh_hashchain.Infonet()
|
|
|
|
assert inf.events == []
|
|
assert inf.head_hash == mesh_hashchain.GENESIS_HASH
|
|
assert not mesh_hashchain.CHAIN_FILE.exists()
|
|
assert list(tmp_path.glob("infonet.json.quarantine.*"))
|
|
|
|
|
|
def test_validate_gate_message_payload_rejects_plaintext_shape():
|
|
payload = mesh_protocol.normalize_payload(
|
|
"gate_message",
|
|
{"gate": "infonet", "message": "plaintext should fail"},
|
|
)
|
|
|
|
valid, reason = mesh_schema.validate_event_payload("gate_message", payload)
|
|
|
|
assert valid is False
|
|
assert reason == "epoch must be a positive integer"
|
|
|
|
|
|
def test_gate_store_accepts_encrypted_gate_payload(tmp_path, monkeypatch):
|
|
priv = ed25519.Ed25519PrivateKey.generate()
|
|
pub = priv.public_key().public_bytes(
|
|
encoding=serialization.Encoding.Raw,
|
|
format=serialization.PublicFormat.Raw,
|
|
)
|
|
pub_b64 = base64.b64encode(pub).decode("utf-8")
|
|
node_id = mesh_crypto.derive_node_id(pub_b64)
|
|
|
|
payload = mesh_protocol.normalize_payload(
|
|
"gate_message",
|
|
{
|
|
"gate": "infonet",
|
|
"epoch": 2,
|
|
"ciphertext": "opaque-ciphertext",
|
|
"nonce": "nonce-2",
|
|
"sender_ref": "persona-ops-1",
|
|
"format": "mls1",
|
|
},
|
|
)
|
|
sig_payload = mesh_crypto.build_signature_payload(
|
|
event_type="gate_message", node_id=node_id, sequence=1, payload=payload
|
|
)
|
|
signature = priv.sign(sig_payload.encode("utf-8")).hex()
|
|
|
|
store = mesh_hashchain.GateMessageStore(data_dir=str(tmp_path / "gate_messages"))
|
|
evt = store.append(
|
|
"infonet",
|
|
{
|
|
"event_id": "evt_gate_cipher",
|
|
"event_type": "gate_message",
|
|
"node_id": node_id,
|
|
"payload": payload,
|
|
"timestamp": 1_700_000_000.0,
|
|
"sequence": 1,
|
|
"signature": signature,
|
|
"public_key": pub_b64,
|
|
"public_key_algo": "Ed25519",
|
|
"protocol_version": mesh_protocol.PROTOCOL_VERSION,
|
|
},
|
|
)
|
|
|
|
assert evt["payload"]["gate"] == "infonet"
|
|
assert evt["payload"]["ciphertext"] == "opaque-ciphertext"
|
|
assert evt["payload"]["epoch"] == 2
|
|
assert evt["payload"]["nonce"] == "nonce-2"
|
|
assert evt["payload"]["sender_ref"] == "persona-ops-1"
|
|
|
|
|
|
def test_gate_store_rejects_replayed_ciphertext_across_append_and_peer_ingest(tmp_path):
|
|
store = mesh_hashchain.GateMessageStore(data_dir=str(tmp_path / "gate_messages"))
|
|
gate_id = "infonet"
|
|
replay_ts = float(int(mesh_hashchain.time.time() / 60) * 60)
|
|
replay_nonce = "stable-nonce"
|
|
first = store.append(
|
|
gate_id,
|
|
{
|
|
"event_id": "a" * 64,
|
|
"event_type": "gate_message",
|
|
"payload": {
|
|
"gate": gate_id,
|
|
"ciphertext": "opaque-ciphertext",
|
|
"nonce": replay_nonce,
|
|
"format": "mls1",
|
|
},
|
|
"timestamp": replay_ts,
|
|
},
|
|
)
|
|
|
|
replayed = store.append(
|
|
gate_id,
|
|
{
|
|
"event_id": "b" * 64,
|
|
"event_type": "gate_message",
|
|
"payload": {
|
|
"gate": gate_id,
|
|
"ciphertext": "opaque-ciphertext",
|
|
"nonce": replay_nonce,
|
|
"format": "mls1",
|
|
},
|
|
"timestamp": replay_ts,
|
|
},
|
|
)
|
|
peer_result = store.ingest_peer_events(
|
|
gate_id,
|
|
[
|
|
{
|
|
"event_type": "gate_message",
|
|
"timestamp": replay_ts,
|
|
"payload": {
|
|
"gate": gate_id,
|
|
"ciphertext": "opaque-ciphertext",
|
|
"nonce": replay_nonce,
|
|
"format": "mls1",
|
|
},
|
|
}
|
|
],
|
|
)
|
|
|
|
assert replayed is first
|
|
assert peer_result == {"accepted": 0, "duplicates": 1, "rejected": 0}
|
|
assert len(store.get_messages(gate_id, limit=10)) == 1
|
|
|
|
|
|
def test_gate_store_prunes_stale_replay_fingerprints(tmp_path):
|
|
store = mesh_hashchain.GateMessageStore(data_dir=str(tmp_path / "gate_messages"))
|
|
old_ts = mesh_hashchain.time.time() - mesh_hashchain.GATE_REPLAY_WINDOW_S - 10
|
|
|
|
store.append(
|
|
"infonet",
|
|
{
|
|
"event_id": "c" * 64,
|
|
"event_type": "gate_message",
|
|
"payload": {
|
|
"gate": "infonet",
|
|
"ciphertext": "old-cipher",
|
|
"format": "mls1",
|
|
},
|
|
"timestamp": old_ts,
|
|
},
|
|
)
|
|
|
|
assert len(store._replay_index) == 1
|
|
removed = store._prune_replay_index(now=mesh_hashchain.time.time())
|
|
|
|
assert removed == 1
|
|
assert store._replay_index == {}
|
|
|
|
|
|
def test_gate_replay_fingerprint_includes_nonce():
|
|
base = {
|
|
"event_type": "gate_message",
|
|
"timestamp": 1_700_000_000,
|
|
"payload": {
|
|
"gate": "infonet",
|
|
"ciphertext": "same-ciphertext",
|
|
"format": "mls1",
|
|
},
|
|
}
|
|
first = mesh_hashchain.build_gate_replay_fingerprint(
|
|
"infonet",
|
|
{
|
|
**base,
|
|
"payload": {**base["payload"], "nonce": "nonce-a"},
|
|
},
|
|
)
|
|
second = mesh_hashchain.build_gate_replay_fingerprint(
|
|
"infonet",
|
|
{
|
|
**base,
|
|
"payload": {**base["payload"], "nonce": "nonce-b"},
|
|
},
|
|
)
|
|
|
|
assert first != second
|
|
|
|
|
|
def test_gate_replay_fingerprint_includes_timestamp():
|
|
base = {
|
|
"event_type": "gate_message",
|
|
"payload": {
|
|
"gate": "infonet",
|
|
"ciphertext": "same-ciphertext",
|
|
"nonce": "nonce-a",
|
|
"format": "mls1",
|
|
},
|
|
}
|
|
first = mesh_hashchain.build_gate_replay_fingerprint(
|
|
"infonet",
|
|
{
|
|
**base,
|
|
"timestamp": 1_700_000_000,
|
|
},
|
|
)
|
|
second = mesh_hashchain.build_gate_replay_fingerprint(
|
|
"infonet",
|
|
{
|
|
**base,
|
|
"timestamp": 1_700_000_001,
|
|
},
|
|
)
|
|
|
|
assert first != second
|