siyuan-note/siyuan · error

failed to decode CA private key PEM

Error message

failed to decode CA private key PEM

What it means

Returned by ImportCABundle when pem.Decode on caKeyPEM returns nil — the private key input is not valid PEM. Mirrors the cert-side decode check; the key must be wrapped in proper PEM markers before it can be parsed.

Source

Thrown at kernel/util/cert.go:332

// ImportCABundle imports a CA certificate and private key from PEM-encoded strings.
func ImportCABundle(caCertPEM, caKeyPEM string) error {
	certBlock, _ := pem.Decode([]byte(caCertPEM))
	if certBlock == nil {
		return fmt.Errorf("failed to decode CA certificate PEM")
	}

	caCert, err := x509.ParseCertificate(certBlock.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse CA certificate: %w", err)
	}

	if !caCert.IsCA {
		return fmt.Errorf("the provided certificate is not a CA certificate")
	}

	keyBlock, _ := pem.Decode([]byte(caKeyPEM))
	if keyBlock == nil {
		return fmt.Errorf("failed to decode CA private key PEM")
	}

	_, err = x509.ParseECPrivateKey(keyBlock.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse CA private key: %w", err)
	}

	caCertPath := filepath.Join(ConfDir, TLSCACertFilename)
	caKeyPath := filepath.Join(ConfDir, TLSCAKeyFilename)

	if err := os.WriteFile(caCertPath, []byte(caCertPEM), 0644); err != nil {
		return fmt.Errorf("failed to write CA certificate: %w", err)
	}

	if err := os.WriteFile(caKeyPath, []byte(caKeyPEM), 0600); err != nil {
		return fmt.Errorf("failed to write CA private key: %w", err)
	}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Provide the key as PEM, e.g. `-----BEGIN EC PRIVATE KEY----- ... -----END EC PRIVATE KEY-----`.
  2. Convert a DER key: `openssl ec -in ca.key.der -inform DER -out ca.key.pem -outform PEM`.
  3. Confirm the PEM block type matches an EC private key encoding.

Example fix

// before
ImportCABundle(certPEM, derKey) // -> failed to decode CA private key PEM

// after
ImportCABundle(certPEM, "-----BEGIN EC PRIVATE KEY-----\n"+pemBody+"\n-----END EC PRIVATE KEY-----\n")
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the key decodes as PEM before importing.
if block, _ := pem.Decode([]byte(caKeyPEM)); block == nil {
    return fmt.Errorf("ca key is not valid PEM; include BEGIN/END EC PRIVATE KEY markers")
}
return util.ImportCABundle(caCertPEM, caKeyPEM)

Prevention

When it happens

Trigger: Calling ImportCABundle with a caKeyPEM argument that pem.Decode cannot parse (missing markers, DER form, empty, wrong label).

Common situations: Supplying a raw base64 key, a DER-encoded key, or a PKCS#8 key whose PEM type is not what the decoder expects; truncated key.

Understand the failure class

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/224638877fc94350. Report an issue: GitHub.