Fix R4: checkpoint binds private key to enrolled fingerprint #8
@ -675,8 +675,15 @@ class Store:
|
|||||||
|
|
||||||
public = _keys.public_from_private(private)
|
public = _keys.public_from_private(private)
|
||||||
fingerprint = _keys.fingerprint(public)
|
fingerprint = _keys.fingerprint(public)
|
||||||
if self.get_agent(signer) is None:
|
agent_row = self.get_agent(signer)
|
||||||
|
if agent_row is None:
|
||||||
raise ValueError(f"{signer} is not enrolled, so cannot sign a checkpoint")
|
raise ValueError(f"{signer} is not enrolled, so cannot sign a checkpoint")
|
||||||
|
enrolled_fp = agent_row["fingerprint"] or ""
|
||||||
|
if not enrolled_fp or fingerprint != enrolled_fp:
|
||||||
|
raise ValueError(
|
||||||
|
f"private key fingerprint does not match enrolled key for {signer}; "
|
||||||
|
"refusing to sign a checkpoint with a stranger key"
|
||||||
|
)
|
||||||
with self._write_lock:
|
with self._write_lock:
|
||||||
last = self.conn.execute(
|
last = self.conn.execute(
|
||||||
"SELECT id, hash FROM events ORDER BY id DESC LIMIT 1"
|
"SELECT id, hash FROM events ORDER BY id DESC LIMIT 1"
|
||||||
|
|||||||
@ -133,6 +133,15 @@ class TestSignedCheckpoints(unittest.TestCase):
|
|||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
stranger.checkpoint(self.private, "not-enrolled")
|
stranger.checkpoint(self.private, "not-enrolled")
|
||||||
|
|
||||||
|
def test_checkpoint_refuses_enrolled_name_with_wrong_key(self):
|
||||||
|
# R4: signer name is enrolled, but private key is not the enrolled one.
|
||||||
|
before = len(self.store.checkpoints())
|
||||||
|
other_private, _ = keys.generate()
|
||||||
|
with self.assertRaises(ValueError) as ctx:
|
||||||
|
self.store.checkpoint(other_private, "bigpickle")
|
||||||
|
self.assertIn("does not match enrolled key", str(ctx.exception))
|
||||||
|
self.assertEqual(len(self.store.checkpoints()), before)
|
||||||
|
|
||||||
def test_checkpoint_after_rekey_is_flagged(self):
|
def test_checkpoint_after_rekey_is_flagged(self):
|
||||||
secret = identity.seed_bootstrap(self.store, "bigpickle")
|
secret = identity.seed_bootstrap(self.store, "bigpickle")
|
||||||
identity.enrol_rekey(
|
identity.enrol_rekey(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user