aaif-goose/goose · error
Unsupported key format '{}'. Expected PKCS#8, PKCS#1, or SEC
Error message
Unsupported key format '{}'. Expected PKCS#8, PKCS#1, or SEC1. Convert with: openssl pkey -in key.pem -out key-pkcs8.pem What it means
convert_key_to_pkcs8_pem recognizes exactly three PEM tags: 'PRIVATE KEY' (PKCS#8), 'RSA PRIVATE KEY' (PKCS#1), and 'EC PRIVATE KEY' (SEC1). Any other leading tag hits this catch-all arm. Typical offenders: 'ENCRYPTED PRIVATE KEY' (passphrase-protected PKCS#8), 'OPENSSH PRIVATE KEY' (ed25519 keys from ssh-keygen), 'DSA PRIVATE KEY', or a certificate body passed as the key.
Source
Thrown at crates/goose-providers/src/api_client.rs:198
.parameters
.and_then(|p| p.named_curve())
.ok_or_else(|| {
anyhow::anyhow!(
"EC key missing curve parameters. Convert to PKCS#8: \
openssl pkey -in key.pem -out key-pkcs8.pem"
)
})?;
let algorithm = pkcs8::AlgorithmIdentifierRef {
oid: sec1::ALGORITHM_OID,
parameters: Some((&curve_oid).into()),
};
let info = pkcs8::PrivateKeyInfo::new(algorithm, parsed.contents());
let der_bytes = info
.to_der()
.map_err(|e| anyhow::anyhow!("Failed to encode PKCS#8: {}", e))?;
Ok(pem::encode(&pem::Pem::new("PRIVATE KEY", der_bytes)))
}
tag => Err(anyhow::anyhow!(
"Unsupported key format '{}'. Expected PKCS#8, PKCS#1, or SEC1. \
Convert with: openssl pkey -in key.pem -out key-pkcs8.pem",
tag
)),
}
}
#[async_trait]
pub trait AuthProvider: Send + Sync {
async fn get_auth_header(&self) -> Result<(String, String)>;
async fn refresh_credentials(&self) -> Result<()> {
anyhow::bail!("credential refresh not supported")
}
}
pub struct ApiResponse {
pub status: StatusCode,View on GitHub (pinned to 3810898a74)
Solutions
- Convert whatever you have to unencrypted PKCS#8: openssl pkey -in key.pem -out key-pkcs8.pem (use -passin for encrypted input)
- For encrypted PKCS#8 specifically: openssl pkcs8 -topk8 -nocrypt -in key.pem -out key-pkcs8.pem
- For OpenSSH ed25519 keys: openssl pkey -in id_ed25519 -out key-pkcs8.pem (recent OpenSSL reads OpenSSH format)
- Double-check key_path really points at the private key ('openssl pkey -in <file> -noout' must succeed)
Example fix
# before -----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAA... # key_path = id_ed25519 -> Unsupported key format 'OPENSSH PRIVATE KEY' # after openssl pkey -in id_ed25519 -out key-pkcs8.pem -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEG... -----END PRIVATE KEY-----
Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED: [&str; 3] = ["PRIVATE KEY", "RSA PRIVATE KEY", "EC PRIVATE KEY"];
fn pem_tag_ok(path: &str) -> anyhow::Result<()> {
let first = std::fs::read_to_string(path)?
.lines().find(|l| l.starts_with("-----BEGIN"))
.unwrap_or_default().to_string();
let tag = first.trim_start_matches("-----BEGIN").trim_end_matches("-----").trim();
anyhow::ensure!(SUPPORTED.contains(&tag),
"unsupported PEM tag '{tag}'; convert: openssl pkey -in {path} -out {path}.pkcs8");
Ok(())
} Try / catch
match build_identity(cert, key) {
Err(e) if e.to_string().contains("Unsupported key format") =>
eprintln!("convert the key first: openssl pkey -in {key} -out {key}.pkcs8 (or -passin for encrypted keys)"),
r => r?,
} Prevention
- Ban ssh-keygen output and encrypted PKCS#8 from mTLS config; enforce unencrypted PKCS#8 via policy
- Script key distribution to always end with openssl pkey -in k -out k.pkcs8 so the canonical form is what ships
- Name files explicitly (server.key vs server.crt) and lint config for the key path pointing at a cert
When it happens
Trigger: Configuring TlsConfig::with_client_cert_and_key (native-tls build) with a key file that is passphrase-encrypted, in OpenSSH format, DSA, or actually the certificate/public half instead of the private key.
Common situations: Teams generate ed25519 keys with ssh-keygen by habit and hand them to mTLS config; security teams deliver passphrase-protected PKCS#8; someone pastes cert.pem into the key_path field. Note the rustls path (Identity::from_pem) is equally strict about encryption, so the fix is the same regardless of backend.
Related errors
- Failed to parse EC key: {}
- EC key missing curve parameters. Convert to PKCS#8: openssl
- Failed to parse PEM key: {}
- Failed to encode PKCS#8: {}
- Failed to create identity from cert and key: {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/239fec21a0c81293.
Report an issue: GitHub.