Web Push (VAPID) key input accepted in Admin UI JMAP Push page , but actions rejected with with cryptic errors.
This could result in impression to admins everything is OK.
Invalid Web Push VAPID key: public key error: ASN.1 error: unexpected ASN.1 DER tag: expected OBJECT IDENTIFIER, got SEQUENCE
Invalid Web Push VAPID key: PKCS#8 ASN.1 error: PEM error: PEM error in pre-encapsulation boundary
I just gave to Claude Code stalwart code and to figure out and to make script for the key.
With the key generated by the script the server started advertising “urn:ietf:params:jmap:webpush-vapid”.
I’m attach the script as reference and his explanation
Setting the Web Push (VAPID) signing key in the admin console (jmap.web_push_key → VapidKey::from_pkcs8_pem) is easy to get wrong — two valid-looking inputs fail with opaque errors that don’t point at the cause.
A valid P-256 key with explicit EC parameters is rejected
Invalid Web Push VAPID key: public key error: ASN.1 error: unexpected ASN.1 DER tag: expected OBJECT IDENTIFIER, got SEQUENCE
p256/RustCrypto only accepts the namedCurve OID encoding, but LibreSSL (the default openssl on macOS) — and OpenSSL with explicit-param encoding — emit explicit ECParameters. The key is cryptographically fine; only the parameter encoding differs. Fails:
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 # LibreSSL → explicit params
Works:
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve
Suggestion: accept explicit-parameter P-256 keys (re-encode to namedCurve on load), or make the error say “P-256 key must use named-curve encoding”.
Lightly-mangled paste → “pre-encapsulation boundary”
Invalid Web Push VAPID key: PKCS#8 ASN.1 error: PEM error: PEM error in pre-encapsulation boundary
Pasting the PEM into the Secret textarea easily carries a UTF-8 BOM or leading whitespace around -----BEGIN PRIVATE KEY-----, which pem-rfc7468 rejects with this message — hard to spot since the visible text looks correct. Suggestion: strip a leading BOM / trim surrounding whitespace before parsing, or point the error at the offending boundary line.
Stalwart Version
v0.16.x
Installation Method
Binary (macOS)
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Internal
Directory Backend
Internal
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
Confirmed by looking at the source: Stalwart’s Web Push VAPID key parsing (VapidKey::from_pkcs8_pem in crates/common/src/network/webpush.rs) uses the p256/RustCrypto PKCS#8 decoder, which only accepts P-256 keys encoded with namedCurve OID parameters, not the explicit ECParameters form some OpenSSL/LibreSSL builds emit by default. That matches your first error (unexpected ASN.1 DER tag: expected OBJECT IDENTIFIER, got SEQUENCE). The generator function used internally is:
which always produces a compatible, named-curve PKCS#8 PEM — that’s why Stalwart’s own auto-generated key (created at first startup, see crates/common/src/manager/defaults.rs) works out of the box, while a manually generated key from openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 on macOS’s LibreSSL may not. To generate a compatible key manually, force named-curve encoding:
Your second error is indeed just the PEM parser choking on stray bytes (BOM/whitespace) before the -----BEGIN PRIVATE KEY----- boundary when pasted through the Admin UI textarea — that’s a straightforward PEM-formatting issue on the client side, not a Stalwart-specific setting.
There’s no documented note about the named-curve requirement or PEM-boundary sensitivity in the current docs, so this is a good candidate for a docs/UX improvement (clearer validation error, or trimming/BOM-stripping on input) — a maintainer will likely want to look at that.
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.
I also generated valid key with OpenSSL.
The problem is that Admin UI says the key is successfully saved, even if the server cannot use them.
If you do not inspect via JMAP won’t know.
Both failures are the encoding of the pasted key rather than a broken key. The parser wants a PKCS#8 PEM key with named-curve (namedCurve OID) encoding and a clean -----BEGIN PRIVATE KEY----- boundary. The first error is a P-256 key emitted with explicit EC parameters (LibreSSL, the default openssl on macOS, does this); the key is cryptographically fine, only the parameter encoding differs, so re-encoding to named-curve fixes it. The second is a UTF-8 BOM or leading whitespace picked up when pasting into the textarea, which the PEM parser rejects even though the visible text looks correct.
KaKeBr’s two-step works because openssl pkey re-emits the key as PKCS#8 with named-curve encoding:
One thing worth knowing: the server generates a valid VAPID key automatically on first startup (on new deployments only), so in most cases you can just use the pre-populated key under the JMAP push settings rather than crafting one.