2

Using the awesome library acme4j, I've created 3 files.

  • domain.csr
  • domain.key
  • domain-chain.crt

The problem I have is when I convert those to a keystore.p12 I can't get Spring boot working with it. I've used the following command to create the keystore.p12 file:

openssl pkcs12 -export -out keystore.p12 -inkey domain.key -in domain-chain.crt

The configuration is setup as such

server:
  port: 9443
  ssl:
    key-store: keystore.p12
    key-password: secret
    key-store-type: PKCS12

However if I try and hit my endpoint, I get javax.net.ssl.SSLHandshakeException: no cipher suites in common thrown.

This seems to be a relatively common issue and one suggestion is to enable debugging as per https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html

So, doing that and hitting the endpoint again I can see

javax.net.ssl|DEBUG|2B|reactor-http-epoll-2|2019-05-03 07:47:10.917 NZST|HandshakeContext.java:294|Ignore unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 for TLS11
javax.net.ssl|DEBUG|2B|reactor-http-epoll-2|2019-05-03 07:47:10.917 NZST|HandshakeContext.java:294|Ignore unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 for TLS11
javax.net.ssl|DEBUG|2B|reactor-http-epoll-2|2019-05-03 07:47:10.917 NZST|HandshakeContext.java:294|Ignore unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 for TLS11
javax.net.ssl|DEBUG|2B|reactor-http-epoll-2|2019-05-03 07:47:10.918 NZST|HandshakeContext.java:294|Ignore unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 for TLS10
javax.net.ssl|DEBUG|2B|reactor-http-epoll-2|2019-05-03 07:47:10.918 NZST|HandshakeContext.java:294|Ignore unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 for TLS10
javax.net.ssl|DEBUG|2B|reactor-http-epoll-2|2019-05-03 07:47:10.918 NZST|HandshakeContext.java:294|Ignore unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 for TLS10

And I'm sure the answer is somewhere in the ClientHello response but It's beyond me on how to understand the issue, or how to fix it

javax.net.ssl|DEBUG|2B|reactor-http-epoll-2|2019-05-03 07:47:10.934 NZST|ClientHello.java:806|Consuming ClientHello handshake message (
"ClientHello": {
  "client version"      : "TLSv1.2",
  "random"              : "C5 25 B0 63 79 3A D5 FB 76 1C 7B DF B5 E9 74 2A 5F FF 2E 1B 7B F0 21 66 5B 33 9C 64 3F 52 40 2A",
  "session id"          : "",
  "cipher suites"       : "[TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xC02F), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(0xC02B), TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030), TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xC02C), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009E), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(0xC027), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(0x0067), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(0xC028), TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(0x006B), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(0xC024), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(0xC014), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(0xC00A), TLS_DH_DSS_WITH_AES_256_GCM_SHA384(0x00A5), TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(0x00A3), TLS_DH_RSA_WITH_AES_256_GCM_SHA384(0x00A1), TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009F), TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(0x006A), TLS_DH_RSA_WITH_AES_256_CBC_SHA256(0x0069), TLS_DH_DSS_WITH_AES_256_CBC_SHA256(0x0068), TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039), TLS_DHE_DSS_WITH_AES_256_CBC_SHA(0x0038), TLS_DH_RSA_WITH_AES_256_CBC_SHA(0x0037), TLS_DH_DSS_WITH_AES_256_CBC_SHA(0x0036), TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(0xC032), TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(0xC02E), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(0xC02A), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(0xC026), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(0xC00F), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(0xC005), TLS_RSA_WITH_AES_256_GCM_SHA384(0x009D), TLS_RSA_WITH_AES_256_CBC_SHA256(0x003D), TLS_RSA_WITH_AES_256_CBC_SHA(0x0035), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(0xC023), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(0xC013), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(0xC009), TLS_DH_DSS_WITH_AES_128_GCM_SHA256(0x00A4), TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(0x00A2), TLS_DH_RSA_WITH_AES_128_GCM_SHA256(0x00A0), TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(0x0040), TLS_DH_RSA_WITH_AES_128_CBC_SHA256(0x003F), TLS_DH_DSS_WITH_AES_128_CBC_SHA256(0x003E), TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033), TLS_DHE_DSS_WITH_AES_128_CBC_SHA(0x0032), TLS_DH_RSA_WITH_AES_128_CBC_SHA(0x0031), TLS_DH_DSS_WITH_AES_128_CBC_SHA(0x0030), TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(0xC031), TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(0xC02D), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(0xC029), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(0xC025), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(0xC00E), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(0xC004), TLS_RSA_WITH_AES_128_GCM_SHA256(0x009C), TLS_RSA_WITH_AES_128_CBC_SHA256(0x003C), TLS_RSA_WITH_AES_128_CBC_SHA(0x002F), TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00FF)]",
  "compression methods" : "00",
  "extensions"          : [
    "server_name (0)": {
      type=host_name (0), value=example.com
    },
    "ec_point_formats (11)": {
      "formats": [uncompressed, ansiX962_compressed_prime, ansiX962_compressed_char2]
    },
    "supported_groups (10)": {
      "versions": [secp256r1, secp521r1, UNDEFINED-NAMED-GROUP(28), UNDEFINED-NAMED-GROUP(27), secp384r1, UNDEFINED-NAMED-GROUP(26), secp256k1, sect571r1, sect571k1, sect409k1, sect409r1, sect283k1, sect283r1]
    },
    "unknown extension (35)": {

    },
    "signature_algorithms (13)": {
      "signature schemes": [rsa_pkcs1_sha512, dsa_sha512, ecdsa_secp512r1_sha512, rsa_pkcs1_sha384, dsa_sha384, ecdsa_secp384r1_sha384, rsa_pkcs1_sha256, dsa_sha256, ecdsa_secp256r1_sha256, rsa_sha224, dsa_sha224, ecdsa_sha224, rsa_pkcs1_sha1, dsa_sha1, ecdsa_sha1]
    },
    "unknown extension (13,172)": {

    }
  ]
}
)

Do I need to be doing something more than I already am? I'm running on OpenJDK Runtime Environment Zulu11.31+11-CA and using Spring boot 2.1.3.RELEASE with WebFlux, so running on Netty if that makes a difference

Cheers

Update:

Thanks to the helpful comments, I've tried using openssl s_client as suggested and the result looks like no certificate is being loaded at all?

CONNECTED(00000003)
140175956235392:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:../ssl/record/rec_layer_s3.c:1536:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 338 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
Chris
  • 3,437
  • 6
  • 40
  • 73
  • 2
    The `ClientHello` isn't the response, it's the initial message sent by the client. If you want to check how your server is configured, it's the `ServerHello` message you need to look for. – Bruno May 02 '19 at 21:27
  • Thanks for clarifying that, searching the debug statement the only mention of `ServerHello` I can find is part of the stacktrace with one line `...at java.base/sun.security.ssl.ServerHello$T12ServerHelloProducer.produce(ServerHello.java:294)` which doesn't really tell me much :( – Chris May 02 '19 at 22:44
  • 1
    @Bruno: except that if no cipher match the server sends Alert(40=handshake_failure) and _not_ ServerHello. Chris: further up in the javax.net.debug=ssl output (perhaps _much_ further up) it should log the/each alias and cert it loaded from the keystore, and possibly the filename; check those match the one you want. The Java alias is the PKCS12 friendlyname, and since you didn't specify it, openssl defaults to the somewhat unobvious name `1`. – dave_thompson_085 May 02 '19 at 22:46
  • 1
    PS: don't worry about the unsupported suites. Those are unsupported _in 1.1 and 1.0_ because the TLS specs allow them only in 1.2 and not in 1.1 and 1.0. Your client is offering 1.2. – dave_thompson_085 May 02 '19 at 22:47
  • 1
    @dave_thompson_085 is correct, and checking the debug output would help indeed. It would be worth trying with another client (e.g. `openssl s_client`, or a browser) to see whether you get a certificate. – Bruno May 02 '19 at 22:51
  • 3
    I'm not familiar with the configuration you're using, but I'd try to use `key-store-password: secret` in addition to `key-password: secret` (which you already have). The Java keystore format (in general) allows for two passwords: one for the store, and one for the key itself. For the p12 file you've generated, they should be the same. Whether both need to be specified depends on the tool that loads this configuration. If the store and key aren't unlocked, the certificate won't be in use, so it will try to use an anonymous cipher suite which is not advertised/enabled. – Bruno May 02 '19 at 22:54
  • 1
    Oh wow, that was it @Bruno as soon as I plugged `key-store-password` in everything started working as expected. If you write that up as the answer I'll happily accept. – Chris May 02 '19 at 22:57

1 Answers1

5

I'm not familiar with the configuration you're using, but I'd try to use key-store-password: secret in addition to key-password: secret (which you already have).

The Java keystore format (in general) allows for two passwords: one for the store, and one for the key itself.

For the p12 file you've generated, they should be the same. Whether both need to be specified depends on the tool that loads this configuration (some libraries would fall back on the keystore password if the key wasn't specified, for example).

If the store and key aren't unlocked, the certificate won't be in use, so it will try to use an anonymous cipher suite which is not advertised by the client and also likely to be disabled by default on the server.

Bruno
  • 119,590
  • 31
  • 270
  • 376