{"record":{"id":"dee939bc51009280","repo":"nautechsystems/nautilus_trader","slug":"pem-does-not-contain-a-private-key","errorCode":null,"errorMessage":"PEM does not contain a private key","messagePattern":"PEM does not contain a private key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cryptography/src/signing.rs","lineNumber":55,"sourceCode":"///\n/// # Errors\n///\n/// Returns an error if:\n/// - `data` is empty.\n/// - `private_key_pem` is not a valid PEM-encoded PKCS#8 RSA private key or cannot be parsed.\n/// - Signature generation fails due to key or cryptographic errors.\npub fn rsa_signature(private_key_pem: &str, data: &str) -> anyhow::Result<String> {\n    if data.is_empty() {\n        anyhow::bail!(\"Query string cannot be empty\");\n    }\n\n    // Remove PEM headings and decode to DER bytes using the `pem` crate\n    let pem = pem::parse(private_key_pem.trim())\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse PEM: {e}\"))?;\n\n    // Ensure this is a private key\n    if !pem.tag().ends_with(\"PRIVATE KEY\") {\n        anyhow::bail!(\"PEM does not contain a private key\");\n    }\n\n    // Construct RSA key pair from PKCS#8 DER bytes\n    let key_pair = KeyPair::from_pkcs8(pem.contents())\n        .map_err(|_| anyhow::anyhow!(\"Failed to decode RSA private key\"))?;\n\n    // Prepare RNG and output buffer (signature length = modulus length)\n    let rng = lc_rand::SystemRandom::new();\n    let mut signature = vec![0u8; key_pair.public_modulus_len()];\n\n    key_pair\n        .sign(\n            &lc_signature::RSA_PKCS1_SHA256,\n            &rng,\n            data.as_bytes(),\n            &mut signature,\n        )\n        .map_err(|_| anyhow::anyhow!(\"Failed to generate RSA signature\"))?;","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/cryptography/src/signing.rs#L37-L73","documentation":"After successfully parsing the PEM structure, `rsa_signature` checks that the PEM tag ends with 'PRIVATE KEY' (i.e. 'PRIVATE KEY' for PKCS#8 or 'RSA PRIVATE KEY'). This error means the PEM block is well-formed but is not a private key — commonly a public key, certificate, or another object type.","triggerScenarios":"Calling `rsa_signature` with a PEM whose tag is e.g. 'PUBLIC KEY', 'CERTIFICATE', or 'ENCRYPTED PRIVATE KEY' (which also ends with 'PRIVATE KEY'... note encrypted keys do end with that tag but will then fail later at decode). The immediate trigger is any tag not ending in 'PRIVATE KEY'.","commonSituations":"Pointing the config at the public key or TLS certificate file instead of the private key; a keychain/cloud secret returning the certificate chain; mixing up the files generated alongside the keypair.","solutions":["Point the key path/env var at the actual private key PEM file (BEGIN PRIVATE KEY or BEGIN RSA PRIVATE KEY)","If you only have a certificate, extract the private key from where it was generated — you cannot sign with a certificate","Generate a proper key: openssl genpkey -algorithm RSA -out key.pem","Check for 'ENCRYPTED PRIVATE KEY' — decrypt it (openssl pkcs8 -topk8 -nocrypt) since this API expects an unencrypted key"],"exampleFix":"// before\nlet pem = std::fs::read_to_string(\"cert.pem\")?; // certificate, not a key\n// after\nlet pem = std::fs::read_to_string(\"private_key.pem\")?; // -----BEGIN PRIVATE KEY-----","handlingStrategy":"validation","validationCode":"let pem = pem::parse(key_text.trim())?;\nif !pem.tag().ends_with(\"PRIVATE KEY\") {\n    return Err(anyhow::anyhow!(\"expected a private key PEM, got tag: {}\", pem.tag()));\n}","typeGuard":"fn pem_is_private_key(s: &str) -> bool {\n    pem::parse(s.trim())\n        .map(|p| p.tag().ends_with(\"PRIVATE KEY\"))\n        .unwrap_or(false)\n}","tryCatchPattern":"match rsa_signature(&key, query) {\n    Ok(sig) => use(sig),\n    Err(e) if e.to_string().contains(\"does not contain a private key\") => {\n        tracing::error!(\"configured key is a public key/certificate\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Double-check which file/env var holds the private key vs the certificate","Name key files unambiguously (private_key.pem vs cert.pem)","Verify with `openssl pkey -in key.pem -noout` before deploying"],"tags":["rust","cryptography","pem","key-format"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}