Withdraw the key manager, and keep what probing it established
A Settings section for public keys is furniture, not a feature. Nothing in ihasmail signs, encrypts, decrypts or verifies with a key, so the page could only ever tell the reader in its own footnote that adding one does nothing. It is withdrawn on that reasoning -- the same reasoning that closed PR #67, reached again with the code in front of us. So this reverts every user-visible part of it: the section, the lib, the mock handlers, the component and the 261 catalogue strings. Nothing in web/ or server/ differs from main now. What stays is the part that was expensive and is true regardless. The x:PublicKey registry was probed against a live 0.16.20 on 2026-09-05, and the findings are now in KNOWN-ISSUES rather than in a closed pull request -- which is where they sat for the nine days between #67 and this branch, and why the work was done twice. Consolidated into one entry, framed as what Stalwart does rather than what ihasmail offers: - an ordinary user may read and write their own keys, whatever the permissions table says - the registry takes S/MIME certificates as well as OpenPGP keys, and parses both -- confirmed with a real self-signed X.509 certificate, and a malformed one gets its own BER decoding error - a key can parse and still be refused, with different words. A sign-and-certify key -- what `gpg --quick-generate-key` makes -- gets "Could not find any suitable keys", which is not a paste error and must not be shown as one - emailAddresses comes back as {} when empty, an object where a list property should be an array. It type-checks, then throws in join() - a create answers with the id alone; patching `key` is allowed - expiresAt is the registry's field and is not derived from the key ROADMAP now says plainly that key management has been built and withdrawn twice, that the registry is not the obstacle, and that verifying a signature -- which needs only public keys -- is the shortest route to a key being worth having. Encryption at rest moves from "not offered yet" to refused: it is a one-way door, since turning it off does not decrypt what is already there, and that is not a switch to hand an ordinary user however easy it would be to add.
This commit is contained in:
-69
@@ -1212,75 +1212,6 @@ Over Stalwart's own registry objects, so there is no administrator in the loop:
|
||||
credentials". Doing it properly means implementing OAuth; that is in
|
||||
[ROADMAP.md](ROADMAP.md).
|
||||
|
||||
## Encryption keys
|
||||
|
||||
Settings › Encryption keys publishes OpenPGP public keys and S/MIME certificates
|
||||
on the account, over Stalwart's `x:PublicKey` registry: list, add, rename,
|
||||
remove. Only public material — no private key is stored, requested or sent by
|
||||
any of it.
|
||||
|
||||
Everything below was established against a live Stalwart **0.16.20** on
|
||||
2026-09-05, rather than taken from the documentation, which is wrong on the
|
||||
first two:
|
||||
|
||||
- **An ordinary user may read *and* write their own keys.** Stalwart's
|
||||
permissions table lists every `sysPublicKey*` permission as administrative.
|
||||
The server granted them to a normal account: `x:PublicKey/get` and
|
||||
`x:PublicKey/query` both answered, and a create carrying a deliberately
|
||||
malformed key came back `invalidProperties` naming `key` — a rejection of the
|
||||
key, not of the person. Had the documentation been right this section would
|
||||
have been useless to everyone but an administrator.
|
||||
- **Stalwart parses the key itself** and says precisely what is wrong with it:
|
||||
*"Failed to decode OpenPGP public key: Malformed packet: Malformed CTB: MSB of
|
||||
ptag not set."* So ihasmail does not validate key material. Anything it
|
||||
checked would be a second opinion, and the one that counts would still be the
|
||||
server's — its message is shown verbatim, the way password-policy rejections
|
||||
already are.
|
||||
- **Certificates are parsed too, by their own decoder.** The registry is not
|
||||
OpenPGP-only, though every other message it returns reads as though it were: a
|
||||
self-signed X.509 certificate registers, reads back and removes cleanly, and a
|
||||
malformed one is refused with *"Failed to decode X509 certificate: BER
|
||||
decoding error…"*. So the S/MIME half of this section is real, and the server
|
||||
is the thing checking it in both formats.
|
||||
- **A key that parses can still be refused, and says something else.** A
|
||||
sign-and-certify key with no encryption subkey — which is what
|
||||
`gpg --quick-generate-key` produces by default — comes back *"Could not find
|
||||
any suitable keys in OpenPGP public key"*. That is the rejection somebody
|
||||
exporting from GnuPG is most likely to meet, and it is not a paste error:
|
||||
the fix is to add an encryption subkey, not to paste more carefully. Showing
|
||||
the server's own two sentences distinguishes the two; showing "invalid key"
|
||||
would not.
|
||||
- **`emailAddresses` arrives as `{}` when it is empty** — an object, where a
|
||||
JMAP list property should be an array. ihasmail checks the shape rather than
|
||||
trusting the type, so nothing puts an object through `join()` halfway through
|
||||
rendering the list.
|
||||
- **Creating a key answers with its id and nothing else**, so adding one
|
||||
reloads the list instead of believing what came back. Renaming and removing
|
||||
both work; removal leaves the registry genuinely empty.
|
||||
|
||||
**`expiresAt` is the registry's field, not the key's.** A certificate valid for
|
||||
a year registers with no expiry set, and the card says so. Reading the real one
|
||||
means parsing the certificate, which is the second opinion this section exists
|
||||
not to offer.
|
||||
|
||||
The kind badge — OpenPGP or S/MIME — is read from the armour header alone, which
|
||||
is a label rather than a parse, and the excerpt beside each key is deliberately
|
||||
not called a fingerprint: computing a real one means parsing the key, and naming
|
||||
it a fingerprint would invite somebody to verify against it.
|
||||
|
||||
**What this does not do.** Nothing signs, encrypts, decrypts or verifies with
|
||||
these keys. The page says so. Adding one does not by itself start encrypting
|
||||
your mail — the one thing known to consume a registered key is
|
||||
`encryptionAtRest`, a field on `x:AccountSettings` beside `description`,
|
||||
`locale` and `timeZone`. There is no `x:EncryptionAtRest` object whatever the
|
||||
documentation suggests — asking for one on 0.16.20 is an `unknownMethod` — and
|
||||
the field's value is a typed object, `{"@type": "Disabled"}`, not a bare string.
|
||||
ihasmail does not yet offer it, and it carries a caveat of its own: turning it
|
||||
off does not decrypt what is already there. Signing and decrypting need a private key in a page
|
||||
served by the same host that would handle it, which is a security model to agree
|
||||
before it is a feature to build. Verifying a signature needs only public keys
|
||||
and is tractable on its own. See [ROADMAP.md](ROADMAP.md).
|
||||
|
||||
## Privacy by default
|
||||
|
||||
Remote images blocked, the proxy on, read receipts never automatic, no
|
||||
|
||||
Reference in New Issue
Block a user