S25: npe adapter matches real send/keygen CLI; config key rotate script
Probe reports usable without enabling PFC_REQUIRE_NPE. Fail-closed if sender .seed or recipient .npeid is missing.
This commit is contained in:
parent
43cbf51d3e
commit
a72b4c513d
4 changed files with 109 additions and 14 deletions
52
scripts/rotate_config_key.py
Executable file
52
scripts/rotate_config_key.py
Executable file
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Rotate lab Ed25519 config key; re-sign payload; append admin-history."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "python"))
|
||||
|
||||
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||
|
||||
from secure_messaging.admin_history import AdminHistory
|
||||
from secure_messaging.signed_config import (
|
||||
generate_signing_key,
|
||||
load_signed,
|
||||
pem_private,
|
||||
pem_public,
|
||||
save_signed,
|
||||
sign,
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument("--pem", default="/opt/pfc/etc/sm-keys/config.ed25519.pem")
|
||||
p.add_argument("--signed", default="/opt/pfc/etc/secure-messaging.signed.json")
|
||||
p.add_argument("--history", default="/opt/pfc/data/admin/admin-history")
|
||||
p.add_argument("--actor", default="rotate-lab")
|
||||
args = p.parse_args()
|
||||
pem = Path(args.pem)
|
||||
signed_path = Path(args.signed)
|
||||
old = load_pem_private_key(pem.read_bytes(), password=None)
|
||||
payload = load_signed(signed_path, old.public_key())
|
||||
new = generate_signing_key()
|
||||
pem.rename(pem.with_suffix(pem.suffix + ".prev"))
|
||||
pem.write_bytes(pem_private(new))
|
||||
pem.chmod(0o600)
|
||||
pub = pem.with_name("config.ed25519.pub.pem")
|
||||
pub.write_bytes(pem_public(new.public_key()))
|
||||
prev_text = signed_path.read_text()
|
||||
signed = sign(payload, new)
|
||||
save_signed(signed_path, signed)
|
||||
row = AdminHistory(Path(args.history)).append_change(
|
||||
actor=args.actor, prev_text=prev_text, new_text=signed.dumps()
|
||||
)
|
||||
print("rotated key_id", signed.key_id, "history_seq", row.get("seq"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue