NationalSecurityAgency/ghidra · error · GeneralSecurityException

File {} does not appear to be a certificate

Error message

File {} does not appear to be a certificate

What it means

Thrown by checkCertAuthorityFile() (as GeneralSecurityException) when the CA file exists and is a regular file but fails verifyPEMFormat(), i.e. its contents are not a valid PEM-encoded certificate. BSim requires a real X.509 CA in PEM form to act as PostgreSQL's ssl_ca_file (root.crt).

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimControlLaunchable.java:853

		}
	}

	/**
	 * Make sure certificate authority needed for pki was provided by user, otherwise throw exception
	 * @throws IOException if the cert file is invalid
	 * @throws GeneralSecurityException if the cert file is not a valid certificate
	 */
	private void checkCertAuthorityFile() throws IOException, GeneralSecurityException {
		if (certAuthorityFile == null) {
			throw new IOException(
				"PKI authentication requested, but certificate authority file not provided");
		}
		if (!certAuthorityFile.isFile()) {
			throw new IOException(
				certAuthorityFile.getAbsolutePath() + " is not a valid certification authority");
		}
		if (!verifyPEMFormat(certAuthorityFile)) {
			throw new GeneralSecurityException(
				"File " + certAuthorityFile.getName() + " does not appear to be a certificate");
		}
	}

	/**
	 * Locate the PostgreSQL configuration and authentication files (postgresql.conf and pg_hba.conf)
	 * and recover the settings pertinent to BSimControl.  If the data directory has not been initialized yet,
	 * run PostgreSQL's init command to perform the initialization and then tailor the configuration
	 * based on BSimControl's command-line options and the Ghidra specific configuration options
	 * @throws IOException if the module data file cannot be retrieved
	 * @throws InterruptedException if the postgres command is interrupted
	 * @throws SAXException if tuneConfig fails
	 * @throws GeneralSecurityException if the cert file cannot be processed
	 */
	private void initializeDataDirectory()
			throws IOException, InterruptedException, SAXException, GeneralSecurityException {
		File configFile = new File(dataDirectory, POSTGRES_CONFIGFILE);
		File hbaFile = new File(dataDirectory, POSTGRES_CONNECTFILE);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Confirm the file contains a PEM block: it should have `-----BEGIN CERTIFICATE-----` / `-----END CERTIFICATE-----`.
  2. Convert DER to PEM: `openssl x509 -in ca.der -inform DER -out root.crt -outform PEM`.
  3. Export the CA from a keystore to PEM using keytool/openssl.
  4. Validate the cert independently: `openssl x509 -in root.crt -noout -text`.

Example fix

// before (cafile is a DER binary)
bsim_ctl start --auth cert --cafile ca.der
// after
openssl x509 -in ca.der -inform DER -out root.crt -outform PEM
bsim_ctl start --auth cert --cafile root.crt
Defensive patterns

Strategy: validation

Validate before calling

// Mirror BSim's PEM check before invoking.
private static final Pattern PEM =
    Pattern.compile("(?s).*-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----.*");
String body = Files.readString(Path.of(caFilePath));
if (!PEM.matcher(body).matches()) {
    throw new IllegalArgumentException(caFilePath + " is not a PEM certificate");
}

Type guard

public boolean looksLikePemCert(File f) throws IOException {
    if (!f.isFile()) return false;
    String s = Files.readString(f.toPath());
    return s.contains("-----BEGIN CERTIFICATE-----")
        && s.contains("-----END CERTIFICATE-----");
}

Try / catch

try {
    bsimControl.start(args);
} catch (GeneralSecurityException e) {
    if (e.getMessage() != null && e.getMessage().contains("does not appear to be a certificate")) {
        throw new UserFacingException("Convert the CA to PEM (openssl x509 -inform DER -outform PEM)", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Pointing --cafile at a DER-encoded cert, a private key, a concatenated bundle without BEGIN CERTIFICATE, a text file, or a truncated/corrupt PEM.

Common situations: Using a .der (binary) cert where PEM is required; passing a .key by mistake; PEM headers stripped or base64 mangled by copy/paste or transfer; pointing at a Java keystore (.jks) instead of an exported PEM.

Understand the failure class

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/48368b7faeeba770. Report an issue: GitHub.