{"record":{"id":"e55712bf8fdd2ce7","repo":"stalwartlabs/stalwart","slug":"err-re-encode-the-key-as-named-curve-pkcs-8-e","errorCode":null,"errorMessage":"{err}. Re-encode the key as named-curve PKCS#8, e.g. `openssl pkey -in key.pem -out key_pkcs8.pem`.","messagePattern":"(.+?)\\. Re-encode the key as named-curve PKCS#8, e\\.g\\. `openssl pkey -in key\\.pem -out key_pkcs8\\.pem`\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/common/src/network/webpush.rs","lineNumber":58,"sourceCode":"    public_key: String,\n}\n\nimpl VapidKey {\n    pub fn from_pkcs8_pem(pem: &str) -> Result<Self, String> {\n        let pem = pem.trim_start_matches('\\u{feff}').trim();\n\n        if let Ok(key) = SigningKey::from_pkcs8_pem(pem) {\n            return Ok(Self::from_signing_key(key));\n        }\n        if let Ok(secret) = SecretKey::from_sec1_pem(pem) {\n            return Ok(Self::from_signing_key(secret.into()));\n        }\n        if let Some(secret) = secret_key_from_explicit_params(pem) {\n            return Ok(Self::from_signing_key(secret.into()));\n        }\n\n        Err(SigningKey::from_pkcs8_pem(pem)\n            .err()\n            .map(|err| {\n                format!(\n                    \"{err}. Re-encode the key as named-curve PKCS#8, \\\n                     e.g. `openssl pkey -in key.pem -out key_pkcs8.pem`.\"\n                )\n            })\n            .unwrap_or_else(|| \"unsupported VAPID key encoding\".to_string()))\n    }\n\n    fn from_signing_key(signing_key: SigningKey) -> Self {\n        let public_key = URL_SAFE_NO_PAD.encode(\n            signing_key\n                .verifying_key()\n                .to_encoded_point(false)\n                .as_bytes(),\n        );\n        Self {\n            signing_key,","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/stalwartlabs/stalwart/blob/e96200385781a6a9995a8b839ac27d6c75a983ee/crates/common/src/network/webpush.rs#L40-L76","documentation":"from_pkcs8_pem in crates/common/src/network/webpush.rs parses a WebPush VAPID signing key from PKCS#8 PEM. If explicit-parameters extraction fails, it falls back to p256::SigningKey::from_pkcs8_pem; when that also fails it returns this error wrapping the underlying message plus a hint to re-encode the key as named-curve PKCS#8. The usual cause is a PEM whose algorithm parameters encode the curve explicitly (or a wrong key type/format) rather than the named-curve form p256 expects.","triggerScenarios":"Calling from_pkcs8_pem with: a PKCS#8 PEM containing explicit curve parameters instead of the namedCurve OID; a key that is not P-256/prime256v1 (e.g. RSA or P-384); a DER or raw key passed where PEM is expected; a SEC.1 'EC PRIVATE KEY' PEM instead of a PKCS#8 'PRIVATE KEY' PEM.","commonSituations":"Keys generated/exported by openssl with explicit parameters (missing -param_enc named_curve); pasting a public key instead of the private key; legacy SEC.1 key files; VAPID keys generated on a different curve.","solutions":["Re-encode the key as named-curve PKCS#8: openssl pkey -in key.pem -out key_pkcs8.pem","Check the PEM header is '-----BEGIN PRIVATE KEY-----'; convert SEC.1 files with: openssl pkcs8 -topk8 -in ec_key.pem -out key_pkcs8.pem","Verify the key is actually P-256 (prime256v1), not RSA or another curve: openssl pkey -in key.pem -text -noout","Generate a fresh key if needed: openssl ecparam -name prime256v1 -genkey -noout -param_enc named_curve | openssl pkcs8 -topk8 -nocrypt -out key.pem"],"exampleFix":"// before (SEC.1 / explicit params, rejected)\n// -----BEGIN EC PRIVATE KEY-----\n// ...\n// after (named-curve PKCS#8)\n// $ openssl pkey -in key.pem -out key_pkcs8.pem\n// -----BEGIN PRIVATE KEY-----\n// ...","handlingStrategy":"validation","validationCode":"// validate the PEM before calling from_pkcs8_pem:\nfn validate_p256_pkcs8_pem(pem: &str) -> Result<(), String> {\n    if !pem.contains(\"-----BEGIN PRIVATE KEY-----\") {\n        return Err(\"expected PKCS#8 PEM ('PRIVATE KEY'), got SEC.1 or other format\".into());\n    }\n    use p256::pkcs8::DecodePrivateKey;\n    p256::SecretKey::from_pkcs8_pem(pem)\n        .map(|_| ())\n        .map_err(|e| format!(\"not a named-curve P-256 PKCS#8 key: {e}\"))\n}","typeGuard":"fn is_p256_pkcs8_pem(pem: &str) -> bool {\n    pem.contains(\"-----BEGIN PRIVATE KEY-----\")\n        && p256::SecretKey::from_pkcs8_pem(pem).is_ok()\n}","tryCatchPattern":"match VapidKey::from_pkcs8_pem(&pem) {\n    Ok(key) => use_key(key),\n    Err(e) => {\n        eprintln!(\"VAPID key rejected: {e}\");\n        eprintln!(\"fix: openssl pkey -in key.pem -out key_pkcs8.pem\");\n        std::process::exit(1);\n    }\n}","preventionTips":["Generate VAPID keys with named-curve parameters: openssl ecparam -name prime256v1 -genkey -noout -param_enc named_curve","Always store keys as PKCS#8 ('BEGIN PRIVATE KEY'); convert legacy 'EC PRIVATE KEY' files with openssl pkcs8 -topk8","Validate the key at startup/config-load time, not on first WebPush send","Confirm the curve is P-256 with: openssl pkey -in key.pem -text -noout"],"tags":["rust","cryptography","pem","pkcs8","p256","vapid","webpush","key-parsing"],"backgroundTag":"invalid-key-format","analyzedSha":"e96200385781a6a9995a8b839ac27d6c75a983ee","analyzedAt":"2026-09-06T22:07:17.982Z","contentChangedAt":"2026-09-06T22:07:17.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}