# HSM / key custody This is **not** a HIPAA/SOC 2/ISO certificate. ## What lives where | Key | Lab (ns1) | Production | |---|---|---| | Config Ed25519 | `/opt/pfc/etc/sm-keys/config.ed25519.pem` mode 0600 root | Customer HSM / PKCS#11; public half in signed wrapper `sig.key_id` | | NPE HPKE | `/opt/pfc/etc/npe/lab.seed` + `lab.npeid` (host only) | `npe keygen --rotate --id` on HSM-backed seed; inbox id unchanged | | System bounce | `crypto.system_key_id` in signed payload | Same id; private material in HSM | | Session / Google | `/opt/pfc/etc/admin.env` | Secrets manager; never git | Private files are **never** committed. Public PEMs and `.npeid` may be copied. ## Rotate config signing key (lab) ```bash sudo python3 /opt/pfc/python/secure_messaging/../scripts/rotate_config_key.py # or from the repo: sudo python3 scripts/rotate_config_key.py \ --pem /opt/pfc/etc/sm-keys/config.ed25519.pem \ --signed /opt/pfc/etc/secure-messaging.signed.json \ --history /opt/pfc/data/admin/admin-history \ --actor rotate-lab ``` Writes a **new** PKCS8 PEM, re-signs the current payload, appends prev+new+diff to the admin-history cube. Old PEM is kept as `config.ed25519.pem.prev`. ## Rotate NPE encryption key (lab) ```bash sudo /opt/pfc/bin/npe keygen --rotate --id /opt/pfc/etc/npe/lab.seed ``` Inbox (`npe.inbox.`) stays stable. Previous enc keys are retained for `--keep-old` then `npe keygen --wipe-old --id ...`. ## Production HSM (not on ns1) Guess until hardware is attached: PKCS#11 slot for Ed25519 config signatures; NPE seed never leaves the module. `PFC_CONFIG_KEY_PEM` is replaced by `PFC_CONFIG_KEY_PKCS11=pkcs11:token=...`. Unsigned wrappers still rejected.