Issue Description
I am trying to generate a new RSA key pair. I have used the WebUI to do so, but I cannot see the public key listed in the output when I click on show DNS records. I’ve also tried to use the stalwart-cli to get the public key, but that fails with this error; Request failed: Failed to read RSA DER)
Expected Behavior
I ought to be able to view the key so I can put it in DNS.
Actual Behavior
Public key is unavailable.
Reproduction Steps
- Generate RSA key via the UI
- Go to domains to see the listed key
Relevant Log Output
DEBUG Management error (manage.error) listenerId = "https", localPort = 443, remoteIp = fe80::f816:3eff:fe4d:e655, remotePort = 46022, details = "Failed to read RSA DER", reason = "Cryptography layer error:
VersionNotSupported"
2026-05-14T20:06:59Z TRACE HTTP response body (http.response-body) listenerId = "https", localPort = 443, remoteIp = fe80::f816:3eff:fe4d:e655, remotePort = 46022, contents = "{"error":"other","details":"Failed to read RSA DER","reason":"Cryptography layer
error:
VersionNotSupported"}", code = 200, size = 109
Stalwart Version
v0.15.x
Installation Method
Binary (Linux)
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Internal
Directory Backend
Internal
Additional Context
ed25519 key works fine, other keys are able to be returned.
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.
on
The key issue is clear from looking at the source code. The "Failed to read RSA DER" / "VersionNotSupported" error occurs in generate_dkim_public_key when it tries to call Document::from_pkcs1_der() on the public key produced by rsa_key_parse. The error VersionNotSupported is a well-known error from the pkcs8 crate when the DER data is in PKCS#8 format rather than PKCS#1 format (or vice versa), which can happen when the private key stored in the database was generated with a format mismatch.
The most likely cause is a format mismatch in the stored RSA private key. The WebUI-generated RSA key is stored as a PEM wrapped PKCS#1 key (-----BEGIN RSA PRIVATE KEY-----), but the public key extraction path (Document::from_pkcs1_der) will fail with VersionNotSupported if the underlying DER is actually PKCS#8 (-----BEGIN PRIVATE KEY-----), or the stored PEM was corrupted/truncated during saving.
Here’s what to check and try:
-
Verify the stored key format. Retrieve the raw private key value from the DKIM signature object (via the WebUI or CLI). It should start with -----BEGIN RSA PRIVATE KEY----- (PKCS#1). If it starts with -----BEGIN PRIVATE KEY----- (PKCS#8), the public-key extraction path in the current code expects PKCS#1 DER specifically for the from_pkcs1_der step and that mismatch causes VersionNotSupported.
-
Delete and regenerate the RSA key pair via the WebUI. The generate_dkim_private_key function in source explicitly generates with the "RSA PRIVATE KEY" PEM header (PKCS#1), so a freshly generated key should work. If the key you’re hitting was created by an older version, the format may differ.
-
As a workaround to get the public key now, you can extract it locally. Export/copy the raw PEM private key from the stored object, save it as private.key, and run:
openssl rsa -in private.key -pubout -outform der 2>/dev/null | openssl base64 -A
Then publish the DNS TXT record manually:
v=DKIM1; k=rsa; p=<base64-output>
This is consistent with your observation that Ed25519 works fine – the Ed25519 code path uses a different PEM parser (simple_pem_parse) and is not affected by PKCS version.
Reference: DKIM Signing documentation
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong. If you found it useful, mention @helpbot in any reply to ask follow-up questions and the bot will respond again.
The key is available in the UI, will that suffice?
v0.15 reads the stored RSA private key DER as PKCS#1 only; if the key was stored in PKCS#8 form (header -----BEGIN PRIVATE KEY-----) the parse fails with VersionNotSupported. We unified that in 0.16 (a rsa_key_parse that tries PKCS#1 then PKCS#8), so the upgrade fixes it.
If you need the public key on 0.15 today, you can try using openssl.
Yes, I solved this by using openssl to create a PKCS#1 key.