apache/cassandra · error · GeneralSecurityException

Invalid certificate format

Error message

Invalid certificate format

What it means

extractBase64EncodedCerts matches the CERT_PATTERN regex for '-----BEGIN ... CERTIFICATE-----' ... '-----END ... CERTIFICATE-----' blocks per RFC 7468. If the input string contains no certificate block at all, this GeneralSecurityException is thrown. It indicates the supplied 'certificates' PEM content has no recognizable X.509 certificate.

Source

Thrown at src/java/org/apache/cassandra/security/PEMReader.java:256

            throw new GeneralSecurityException("Invalid private key format");
        }
    }

    /**
     * Parses the PEM formatted certificate/public-key based on the standard pattern specified by the
     * <a href="https://datatracker.ietf.org/doc/html/rfc7468#section-13">RFC 7468</a>.
     *
     * @param pemCerts certificate/public-key stored as PEM content
     * @return list of base64 encoded certificates within the defined encapsulation boundaries by the above RFC
     * @throws GeneralSecurityException in case any issue encountered parsing the certificate
     */
    private static List<String> extractBase64EncodedCerts(String pemCerts) throws GeneralSecurityException
    {
        List<String> certificateList = new ArrayList<>();
        Matcher matcher = CERT_PATTERN.matcher(pemCerts);
        if (!matcher.find())
        {
            throw new GeneralSecurityException("Invalid certificate format");
        }

        for (int start = 0; matcher.find(start); start = matcher.end())
        {
            String certificate = matcher.group(1).replaceAll("\\s", "");
            certificateList.add(certificate);
        }
        return certificateList;
    }

    /**
     * Decodes given input in Base64 format.
     *
     * @param base64Input input to be decoded
     * @return byte[] containing decoded bytes
     * @throws GeneralSecurityException in case it fails to decode the given base64 input
     */
    private static byte[] decodeBase64(String base64Input) throws GeneralSecurityException

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Confirm the certificate file starts with '-----BEGIN CERTIFICATE-----' and ends with '-----END CERTIFICATE-----'
  2. Check the key and certificate_chain settings are not swapped in the encryption options
  3. Convert DER certificates to PEM: openssl x509 -inform der -in cert.der -out cert.pem
  4. Include the full chain (intermediates) concatenated in PEM form if required
  5. Verify the file is non-empty and readable by the Cassandra process; re-export from your CA if it is blank

Example fix

// before: DER certificate used directly
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key.pem -out cert.der   # DER output
// after: ensure PEM output / convert existing DER
openssl x509 -inform der -in cert.der -out cert.pem   # '-----BEGIN CERTIFICATE-----'
Defensive patterns

Strategy: validation

Validate before calling

// Check PEM certificate markers before calling the API
static boolean looksLikePemCertificateChain(String pem) {
    return pem != null && pem.contains("BEGIN CERTIFICATE");
}

Try / catch

try {
    Certificate[] certs = PEMReader.extractCertificates(pemCerts);
} catch (GeneralSecurityException e) {
    if (e.getMessage().contains("Invalid certificate format")) {
        logger.error("No BEGIN/END CERTIFICATE block found - check certificate_chain value in cassandra.yaml");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling PEMReader.extractCertificates(pemCerts) or base64EncodedCerts — typically from PEMBasedSslContextFactory when loading certificate_chain from cassandra.yaml — where the string is empty, holds a private key instead of a certificate, or uses a nonstandard/missing BEGIN CERTIFICATE header.

Common situations: Swapped key and certificate_chain values in cassandra.yaml; a certificate file exported in DER binary format rather than PEM; a config value containing only a public key ('BEGIN PUBLIC KEY') rather than a certificate; empty file after a failed cert-issuance/renewal; templating leaving an empty placeholder.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/b3fd6c4f513b71d6. Report an issue: GitHub.