apache/pulsar · error · RuntimeException

MD5 algorithm not found

Error message

MD5 algorithm not found

What it means

The MD5 role anonymizer hashes the role string with MessageDigest.getInstance("MD5") and returns a Base64-encoded 'MD5:'-prefixed digest. Like the SHA-256 variant, every standard JDK ships MD5, so this RuntimeException signals a broken JCE environment rather than an input problem. It exists purely as a checked-exception bridge since anonymize() has no throws clause.

Source

Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/common/configuration/anonymizer/DefaultRoleAnonymizerType.java:73

      }
   },
   MD5 {
      private static final String PREFIX = "MD5:";
      private static final FastThreadLocal<MessageDigest> DIGEST = new FastThreadLocal<MessageDigest>() {
         @Override
         protected MessageDigest initialValue() throws Exception {
            // codeql[java/weak-cryptographic-algorithm] - md5 is sufficient for this use case
            return MessageDigest.getInstance("MD5");
         }
      };

      @Override
      public String anonymize(String role) {
         try {
            byte[] hash = DIGEST.get().digest(role.getBytes());
            return PREFIX + Base64.getEncoder().encodeToString(hash);
         } catch (Exception e) {
            throw new RuntimeException("MD5 algorithm not found", e);
         }
      }
   };

   private static final String REDACTED_VALUE = "[REDACTED]";
   public abstract String anonymize(String role);
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Restore default providers in $JAVA_HOME/conf/security/java.security (ensure sun.security.provider.Sun is registered).
  2. Use a full standard JDK distribution instead of a trimmed one.
  3. For native-image builds, register MD5 in the security services configuration.
  4. Consider migrating anonymization config to the SHA256 variant anyway, since MD5 is cryptographically weak.

Example fix

// before
roleAnonymizer = MD5
// after (client and server config)
roleAnonymizer = SHA256
Defensive patterns

Strategy: try-catch

Validate before calling

boolean md5Available;
try {
    java.security.MessageDigest.getInstance("MD5");
    md5Available = true;
} catch (java.security.NoSuchAlgorithmException e) {
    md5Available = false;
}

Try / catch

try {
    String anon = anonymizer.anonymize(role);
} catch (RuntimeException e) {
    throw new IllegalStateException("JRE is missing MD5 provider; prefer SHA256 anonymizer anyway", e);
}

Prevention

When it happens

Trigger: Calling anonymize(role) on the MD5 anonymizer variant when MessageDigest.getInstance("MD5") (via the FastThreadLocal DIGEST) throws NoSuchAlgorithmException — effectively only on a JRE without the standard providers.

Common situations: Same as SHA-256 variant: stripped/custom JRE, edited java.security removing the SUN provider, GraalVM native-image without registered MessageDigest services.

Related errors


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