apache/pulsar · error · PulsarClientException.CryptoException

${logCtx}Failed to load public key ${keyName}. ${e.getMessag

Error message

${logCtx}Failed to load public key ${keyName}. ${e.getMessage()}

What it means

This is a wrapping error: addPublicKeyCipher loaded the key bytes from the CryptoKeyReader and passed them to loadPublicKey, which failed (bad PEM format, unsupported curve, non-EC/RSA content, parse error). The code logs and rethrows the failure as a CryptoException prefixed with 'Failed to load public key <keyName>', embedding the underlying exception message.

Source

Thrown at pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java:386

        }
    }

    private void addPublicKeyCipher(String keyName, CryptoKeyReader keyReader) throws CryptoException {
        if (keyName == null || keyReader == null) {
            throw new PulsarClientException.CryptoException("Keyname or KeyReader is null");
        }

        // Read the public key and its info using callback
        EncryptionKeyInfo keyInfo = keyReader.getPublicKey(keyName, null);

        PublicKey pubKey;

        try {
            pubKey = loadPublicKey(keyInfo.getKey());
        } catch (Exception e) {
            String msg = logCtx + "Failed to load public key " + keyName + ". " + e.getMessage();
            log.error(msg);
            throw new PulsarClientException.CryptoException(msg);
        }

        Cipher dataKeyCipher;
        byte[] encryptedKey;
        try {
            AlgorithmParameterSpec params = null;
            // Encrypt data key using public key
            if (RSA.equals(pubKey.getAlgorithm())) {
                dataKeyCipher = Cipher.getInstance(RSA_TRANS, bcProvider());
            } else if (ECDSA.equals(pubKey.getAlgorithm())) {
                dataKeyCipher = Cipher.getInstance(ECIES, bcProvider());
                params = createIESParameterSpec();
            } else {
                String msg = logCtx + "Unsupported key type " + pubKey.getAlgorithm() + " for key " + keyName;
                log.error(msg);
                throw new PulsarClientException.CryptoException(msg);
            }
            if (params != null) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Read the embedded cause message in the exception and fix the underlying parse failure it reports
  2. Verify the key file contains a valid PEM block starting with '-----BEGIN PUBLIC KEY-----' (or EC PARAMETERS followed by EC PUBLIC KEY)
  3. Confirm the keyName passed to addEncryptionKey exactly matches the key file name the CryptoKeyReader resolves
  4. Test parsing locally: openssl pkey -pubin -in key.pem -text -noout to confirm the key is loadable and of a supported type (RSA or EC on a named curve)

Example fix

// before: certificate passed where a public key is expected
CryptoKeyReader reader = new DefaultCryptoKeyReader("/certs/server.crt");
// after: extract the public key PEM
// openssl x509 -in server.crt -pubkey -noout > public.key
CryptoKeyReader reader = new DefaultCryptoKeyReader("/certs/public.key");
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate the key material served by the reader
byte[] keyBytes = keyReader.getPublicKey(keyName, null).getKey();
String pem = new String(keyBytes, StandardCharsets.UTF_8);
if (!pem.contains("BEGIN PUBLIC KEY") && !pem.contains("BEGIN EC PUBLIC KEY")) {
    throw new IllegalStateException(keyName + " does not contain a public key PEM block");
}

Try / catch

try {
    crypto.addPublicKeyCipher(keyName, keyReader);
} catch (PulsarClientException.CryptoException e) {
    // message embeds the underlying load failure; surface it with key context
    throw new IllegalStateException("Public key '" + keyName + "' failed to load: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: addPublicKeyCipher is invoked with a keyName whose keyReader.getPublicKey(keyName, null) returns bytes that loadPublicKey cannot parse: invalid PEM, DER structure errors, unsupported EC curve OID (see the PEMException cases), or a key format not matching RSA/EC expectations.

Common situations: Key name passed to addEncryptionKey does not match a key file in the CryptoKeyReader directory; the public key file contains a private key or certificate instead of a PUBLIC KEY PEM block; key file corrupted in transit; unsupported curve; whitespace/encoding mangling from secret-management tooling.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/7bcca82bb070d5ba. Report an issue: GitHub.