Elastic search v8.18.2 fails to boot up in FIPS mode because of MD5 invocation in ESQL plugin

I am trying to upgrade our Elasticsearch FIPS enabled cluster from v8.17.4 to 8.18.2. When I tried doing this the initialization failed with this error:

[2025-06-09T20:46:40,119][ERROR][o.e.b.Elasticsearch ][elasticsearch-data-2.gce-lma-01a] fatal exception while booting Elasticsearch
java.lang.ExceptionInInitializerError: null
at org.elasticsearch.xpack.esql.expression.function.scalar.ScalarFunctionWritables.getNamedWriteables(ScalarFunctionWritables.java:87) ~[?:?]
at org.elasticsearch.xpack.esql.expression.ExpressionWritables.scalars(ExpressionWritables.java:143) ~[?:?]
at org.elasticsearch.xpack.esql.expression.ExpressionWritables.getNamedWriteables(ExpressionWritables.java:99) ~[?:?]
at org.elasticsearch.xpack.esql.plugin.EsqlPlugin.getNamedWriteables(EsqlPlugin.java:203) ~[?:?]
at org.elasticsearch.plugins.PluginsService.lambda$flatMap$0(PluginsService.java:186) ~[elasticsearch-8.18.2.jar:?]
at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273) ~[?:?]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[?:?]
at java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720) ~[?:?]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[?:?]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[?:?]
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[?:?]
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[?:?]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?]
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[?:?]
at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276) ~[?:?]
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[?:?]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[?:?]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[?:?]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[?:?]
at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[?:?]
at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[?:?]
at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[?:?]
at java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[?:?]
at org.elasticsearch.node.NodeConstruction.createClientAndRegistries(NodeConstruction.java:592) ~[elasticsearch-8.18.2.jar:?]
at org.elasticsearch.node.NodeConstruction.prepareConstruction(NodeConstruction.java:288) ~[elasticsearch-8.18.2.jar:?]
at org.elasticsearch.node.Node.(Node.java:201) ~[elasticsearch-8.18.2.jar:?]
at org.elasticsearch.bootstrap.Elasticsearch$2.(Elasticsearch.java:385) ~[elasticsearch-8.18.2.jar:?]
at org.elasticsearch.bootstrap.Elasticsearch.initPhase3(Elasticsearch.java:385) ~[elasticsearch-8.18.2.jar:?]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:97) ~[elasticsearch-8.18.2.jar:?]
Caused by: java.lang.IllegalStateException: java.security.NoSuchAlgorithmException: MD5 MessageDigest not available
at org.elasticsearch.xpack.esql.expression.function.scalar.string.Hash$HashFunction.create(Hash.java:196) ~[?:?]
at org.elasticsearch.xpack.esql.expression.function.scalar.string.Md5.(Md5.java:27) ~[?:?]
... 29 more
Caused by: java.security.NoSuchAlgorithmException: MD5 MessageDigest not available
at sun.security.jca.GetInstance.getInstance(GetInstance.java:159) ~[?:?]
at java.security.MessageDigest.getInstance(MessageDigest.java:185) ~[?:?]
at org.elasticsearch.xpack.esql.expression.function.scalar.string.Hash$HashFunction.create(Hash.java:193) ~[?:?]
at org.elasticsearch.xpack.esql.expression.function.scalar.string.Md5.(Md5.java:27) ~[?:?]
... 29 more

I can see that this MD5 hash was added in v8.18.0 as part of the ESQL plugin (https://github.com/elastic/elasticsearch/blob/v8.18.0/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/ScalarFunctionWritables.java#L87(external, opens in a new tab or window)). Since our JVM has disabled MD5 to be FIPS compliant how do we go about with this upgrade and still maintain FIPS compliance?

JVM used: OpenJDK 17, Bouncy castle jar version: 1.0.2.5

@k.rajendran

Did you find a way to resolve this ? (Just curious).

This is a known issue, it's probabkly best to remain on 8.17.4 until it's fixed:

It's a bit more nuanced than that public issue describes.

The existence of an MD5 function in ES|QL should not stop a node from starting on a FIPS JVM - and it doesn't cause a problem in our testing.

The behaviour of MD5 in BC-FIPS is a little peculiar because the FIPS 140-2 standard had to make some compromises to maintain compatibility with commonly used (at the time) TLS ciphers that depend on MD5.

You shouldn't use MD5 for anything security related (whether you're on FIPS or not) because it is less secure and typically less performant than other available hashes, and we want to make it possible to exclude it from your Elasticsearch nodes if you so desire. However, so far we've been unable to reproduce the behaviour described in this thread.

Always test your upgrades (and let us know if you run into problems), but I do not expect this particular issue (whatever the specific details might be to trigger it) to prevent upgrades for typical FIPS deployments.