How to enable ECDHE ciphers with openjdk 14 on an Alpine docker container?
Asked Answered
V

1

6

One API I have to use for my app only supports ECDHE ciphers for TLS connections.

PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers:
|   TLSv1.2:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: server
|_  least strength: A

Nmap done: 1 IP address (1 host up) scanned in 15.16 seconds

It looks like my app doesn't support those, I get:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Here's the list of ciphers I can see in the logs:

"ClientHello": {
  "client version"      : "TLSv1.2",
  "random"              : "FE 6E D4 06 07 51 D0 66 1A 6A B8 60 84 B0 C7 9F 07 82 8F 92 13 48 2A 72 DC BD 80 39 B9 33 7A 1D",
  "session id"          : "8C 37 D0 37 88 6C D6 5C 59 94 5B AD E6 6E 0F 50 1D F2 9E 06 F6 17 3F 85 44 AB 12 82 E1 1F F5 53",
  "cipher suites"       : "[TLS_AES_256_GCM_SHA384(0x1302), TLS_AES_128_GCM_SHA256(0x1301), TLS_CHACHA20_POLY1305_SHA256(0x1303), TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009F), TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256(0xCCAA), TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(0x00A3), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009E), TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(0x00A2), TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(0x006B), TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(0x006A), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(0x0067), TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(0x0040), TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039), TLS_DHE_DSS_WITH_AES_256_CBC_SHA(0x0038), TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033), TLS_DHE_DSS_WITH_AES_128_CBC_SHA(0x0032), TLS_RSA_WITH_AES_256_GCM_SHA384(0x009D), TLS_RSA_WITH_AES_128_GCM_SHA256(0x009C), TLS_RSA_WITH_AES_256_CBC_SHA256(0x003D), TLS_RSA_WITH_AES_128_CBC_SHA256(0x003C), TLS_RSA_WITH_AES_256_CBC_SHA(0x0035), TLS_RSA_WITH_AES_128_CBC_SHA(0x002F), TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00FF)]",

And my Dockerfile

FROM alpine:3.10 as jdk-14-alpine

# Add the musl-based JDK 14 distribution
RUN apk update \
    && apk add wget \
    && apk --no-cache add ca-certificates

RUN wget -q https://download.java.net/java/early_access/alpine/12/binaries/openjdk-14-ea+12_linux-x64-musl_bin.tar.gz && \
    echo "f6247b208eae214562ec69ec928a238ec26a15b7d18a435523c3ceb3f3f18a7c *openjdk-14-ea+12_linux-x64-musl_bin.tar.gz" | sha256sum -c -
RUN tar -x -f openjdk-14-ea+12_linux-x64-musl_bin.tar.gz -C /opt
RUN rm openjdk-14-ea+12_linux-x64-musl_bin.tar.gz

# Set up env variables
ENV JAVA_HOME=/opt/jdk-14
ENV PATH=$PATH:$JAVA_HOME/bin

# Strip away unnecessary parts of the JDK
# The java.desktop module is needed because Jersey's RenderedImageProvider references java.awt.image.RenderedImage
# The java.sql module is needed because Snakeyaml's Tag references java.sql.Date

RUN jlink --module-path /opt/jdk-14/jmods \
    --add-modules java.base,java.logging,java.xml,jdk.unsupported,java.desktop,java.management,java.naming,java.sql,jdk.jdi,jdk.jdwp.agent \
    --compress 2 \
    --no-header-files \
    --output /opt/jdk-14-alpine-linked

CMD ["/opt/jdk-14-alpine-linked/bin/java", "-version"]

FROM alpine:3.10

# Copy the stripped JDK 14 from the previous stage
COPY --from=jdk-14-alpine /opt/jdk-14-alpine-linked /opt/jdk-14
COPY --from=jdk-14-alpine /opt/jdk-14-alpine-linked /opt/jre-14
ENV JAVA_HOME=/opt/jre-14
ENV PATH=$PATH:$JAVA_HOME/bin

# Add the application jar file
ADD target/app-backend.jar /opt/app/app-backend.jar

ADD run.sh /opt/app/run.sh
RUN chmod +x /opt/app/run.sh


CMD ["sh", "/opt/app/run.sh"]

I tried to enable unlimited security by adding

Security.setProperty("crypto.policy", "unlimited");

But it didn't make a difference. I also tried to add bouncycastle in my pom file and I instead got:

Caused by: java.lang.RuntimeException: Could not generate XDH keypair

This could be fixed by applying the solution described here but then I get back to the initial error.

Any idea of what I could do? I works on my local machine, it's only when I deploy that the issue appears.

This app is using Apache http so an alternative would be to inject support for these ciphers directly at that level. Can it be done?

Vocable answered 20/9, 2019 at 11:12 Comment(4)
Thanks for the tip but it's not Java 1.4 but Java 14 (early access)Vocable
If you are using Java 14 then why do you try to set crypto.policy? AFAIK since Java 9 there is no crypto limitation anymore. Anyway if you are using pre-alpha software IMHO Stackoverflow is the wrong place to ask. Use the Java mailing lists.Kittiekittiwake
I set the crypto.policy according to mail.openjdk.java.net/pipermail/security-dev/2016-October/… In my understanding, the crypto limitation was removed for Java from Oracle but is still there be default in OpenJDK.Vocable
Note that I don't insist on using Java 14, I only need java 11 but I open openJDK for alpine is now only available for version 14Vocable
V
10

This actually has nothing to do with Alpine or OpenJDK 14. I found the solution at http://www.gubatron.com/blog/2019/04/25/solving-received-fatal-alert-handshake_failure-error-when-performing-https-connections-on-a-custom-made-jre-with-jlink/ , just add jdk.crypto.cryptoki to the list of modules to add with jlink

Vocable answered 23/9, 2019 at 9:52 Comment(1)
There are not enough upvotes in the world for this, it just saved me what could easily have been days of troubleshooting.Mcqueen

© 2022 - 2024 — McMap. All rights reserved.