mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-05-09 18:47:33 +02:00
144 lines
5.9 KiB
Python
144 lines
5.9 KiB
Python
"""S7B DM Sessionless Alias Restart Recovery.
|
|
|
|
Tests:
|
|
- Alias with no active DM session can export a key package after privacy-core restart
|
|
- Recreated alias handle differs from the stale old handle
|
|
- Persisted alias binding metadata is rewritten with new handle/public_bundle/binding_proof
|
|
- Active-session durable restore behavior is not regressed
|
|
"""
|
|
|
|
def _fresh_dm_mls_state(tmp_path, monkeypatch):
|
|
from services import wormhole_supervisor
|
|
from services.mesh import mesh_dm_mls, mesh_dm_relay, mesh_secure_storage, mesh_wormhole_persona
|
|
|
|
monkeypatch.setattr(mesh_secure_storage, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_secure_storage, "MASTER_KEY_FILE", tmp_path / "wormhole_secure_store.key")
|
|
monkeypatch.setattr(mesh_wormhole_persona, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_wormhole_persona, "PERSONA_FILE", tmp_path / "wormhole_persona.json")
|
|
monkeypatch.setattr(
|
|
mesh_wormhole_persona,
|
|
"LEGACY_DM_IDENTITY_FILE",
|
|
tmp_path / "wormhole_identity.json",
|
|
)
|
|
monkeypatch.setattr(mesh_dm_mls, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_dm_mls, "STATE_FILE", tmp_path / "wormhole_dm_mls.json")
|
|
monkeypatch.setattr(mesh_dm_relay, "DATA_DIR", tmp_path)
|
|
monkeypatch.setattr(mesh_dm_relay, "RELAY_FILE", tmp_path / "dm_relay.json")
|
|
monkeypatch.setattr(
|
|
mesh_dm_mls,
|
|
"get_wormhole_state",
|
|
lambda: {"configured": True, "ready": True, "arti_ready": True, "rns_ready": True},
|
|
)
|
|
monkeypatch.setattr(
|
|
wormhole_supervisor,
|
|
"get_wormhole_state",
|
|
lambda: {"configured": True, "ready": True, "arti_ready": True, "rns_ready": True},
|
|
)
|
|
relay = mesh_dm_relay.DMRelay()
|
|
monkeypatch.setattr(mesh_dm_relay, "dm_relay", relay)
|
|
mesh_dm_mls.reset_dm_mls_state(clear_privacy_core=True, clear_persistence=True)
|
|
return mesh_dm_mls
|
|
|
|
|
|
def _simulate_privacy_core_restart(dm_mls):
|
|
"""Reset privacy-core (destroys all Rust handles) but keep persisted metadata."""
|
|
dm_mls.reset_dm_mls_state(clear_privacy_core=True, clear_persistence=False)
|
|
|
|
|
|
# ── Sessionless alias recovery after restart ─────────────────────────────
|
|
|
|
|
|
def test_alias_export_key_package_after_restart(tmp_path, monkeypatch):
|
|
"""An alias with no active DM session must export a key package after restart."""
|
|
dm_mls = _fresh_dm_mls_state(tmp_path, monkeypatch)
|
|
|
|
# Create alias identity (no session).
|
|
result1 = dm_mls.export_dm_key_package_for_alias("alice")
|
|
assert result1["ok"] is True
|
|
|
|
# Restart privacy-core — all Rust handles become stale.
|
|
_simulate_privacy_core_restart(dm_mls)
|
|
|
|
# Must self-heal and succeed, not fail with stale handle.
|
|
result2 = dm_mls.export_dm_key_package_for_alias("alice")
|
|
assert result2["ok"] is True
|
|
assert result2["alias"] == "alice"
|
|
assert result2["mls_key_package"] # non-empty
|
|
|
|
|
|
def test_recreated_handle_differs_from_stale(tmp_path, monkeypatch):
|
|
"""After restart, the recreated alias handle must differ from the stale one."""
|
|
dm_mls = _fresh_dm_mls_state(tmp_path, monkeypatch)
|
|
|
|
dm_mls.export_dm_key_package_for_alias("bob")
|
|
old_handle = dm_mls._ALIAS_IDENTITIES["bob"]
|
|
assert old_handle > 0
|
|
|
|
_simulate_privacy_core_restart(dm_mls)
|
|
|
|
dm_mls.export_dm_key_package_for_alias("bob")
|
|
new_handle = dm_mls._ALIAS_IDENTITIES["bob"]
|
|
assert new_handle > 0
|
|
assert new_handle != old_handle
|
|
|
|
|
|
def test_persisted_binding_metadata_rewritten(tmp_path, monkeypatch):
|
|
"""After restart self-heal, persisted alias binding must have new handle/bundle/proof."""
|
|
from services.mesh.mesh_secure_storage import read_domain_json
|
|
|
|
dm_mls = _fresh_dm_mls_state(tmp_path, monkeypatch)
|
|
|
|
dm_mls.export_dm_key_package_for_alias("carol")
|
|
old_binding = dict(dm_mls._ALIAS_BINDINGS["carol"])
|
|
old_handle = old_binding["handle"]
|
|
old_bundle = old_binding["public_bundle"]
|
|
old_proof = old_binding["binding_proof"]
|
|
|
|
_simulate_privacy_core_restart(dm_mls)
|
|
|
|
dm_mls.export_dm_key_package_for_alias("carol")
|
|
|
|
# In-memory binding must be updated.
|
|
new_binding = dm_mls._ALIAS_BINDINGS["carol"]
|
|
assert new_binding["handle"] != old_handle
|
|
assert new_binding["handle"] > 0
|
|
assert new_binding["public_bundle"] # non-empty
|
|
assert new_binding["public_bundle"] != old_bundle
|
|
assert new_binding["binding_proof"] # non-empty
|
|
assert new_binding["binding_proof"] != old_proof
|
|
|
|
# Persisted state must also be updated.
|
|
state = read_domain_json(dm_mls.STATE_DOMAIN, dm_mls.STATE_FILENAME, dm_mls._default_state)
|
|
persisted_alias = state.get("aliases", {}).get("carol", {})
|
|
assert persisted_alias["handle"] == new_binding["handle"]
|
|
assert persisted_alias["public_bundle"] == new_binding["public_bundle"]
|
|
assert persisted_alias["binding_proof"] == new_binding["binding_proof"]
|
|
|
|
|
|
# ── Active-session restore not regressed ─────────────────────────────────
|
|
|
|
|
|
def test_active_session_restore_not_regressed(tmp_path, monkeypatch):
|
|
"""S6A durable session restore must still work after this change."""
|
|
dm_mls = _fresh_dm_mls_state(tmp_path, monkeypatch)
|
|
|
|
# Establish a session.
|
|
bob_bundle = dm_mls.export_dm_key_package_for_alias("bob")
|
|
assert bob_bundle["ok"] is True
|
|
initiated = dm_mls.initiate_dm_session("alice", "bob", bob_bundle)
|
|
assert initiated["ok"] is True
|
|
accepted = dm_mls.accept_dm_session("bob", "alice", initiated["welcome"])
|
|
assert accepted["ok"] is True
|
|
|
|
# Encrypt a message before restart.
|
|
encrypted = dm_mls.encrypt_dm("alice", "bob", "pre-restart secret")
|
|
assert encrypted["ok"] is True
|
|
|
|
# Restart: clear in-memory state but keep persistence (including Rust blob).
|
|
dm_mls.reset_dm_mls_state(clear_privacy_core=False, clear_persistence=False)
|
|
|
|
# Session should be restored from persisted Rust state.
|
|
has = dm_mls.has_dm_session("alice", "bob")
|
|
assert has["ok"] is True
|
|
assert has["exists"] is True
|