{"id":3793,"date":"2019-04-25T13:59:46","date_gmt":"2019-04-25T13:59:46","guid":{"rendered":"http:\/\/www.gubatron.com\/blog\/?p=3793"},"modified":"2019-04-25T13:59:46","modified_gmt":"2019-04-25T13:59:46","slug":"solving-received-fatal-alert-handshake_failure-error-when-performing-https-connections-on-a-custom-made-jre-with-jlink","status":"publish","type":"post","link":"https:\/\/www.gubatron.com\/blog\/solving-received-fatal-alert-handshake_failure-error-when-performing-https-connections-on-a-custom-made-jre-with-jlink\/","title":{"rendered":"Solving &#8220;Received fatal alert: handshake_failure&#8221; error when performing HTTPS connections on a custom made JRE with jlink"},"content":{"rendered":"<p><strong>TL; Tell me already what to do:<\/strong><br \/>\nAdd the <code>jdk.crypto.cryptoki<\/code> module to the list of <code>--add-modules<\/code> parameter to your <code>jlink<\/code> command invocation<\/p>\n<hr \/>\n<p>If you&#8217;re reading this you&#8217;re one of the few developers out there that wanted to distribute a java 9+ app (using either jdk 9, jdk 10, jdk 11 or jdk 12, as of this writing) with a smaller version of the jdk, to build your custom jre, you used the <strong>jlink<\/strong> tool.<\/p>\n<p>When you run your app using the full JRE that comes with the OpenJDK, your app is working fine when it comes to making <strong>https<\/strong> requests, but when you run your app using your custom jre you get the following error when opening https connections<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;Received%20fatal%20alert%3A%20handshake_failure&#8221; message=&#8221;&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>This issue occurs because your JRE is missing lots of Cipher Suites that come with the full JDK.<\/p>\n<p>With your JDK, you can try to check the list of supported ciphers with this one liner using the <strong>jrunscript<\/strong> tool:<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;jrunscript%20-e%20%22print(java.util.Arrays.toString(javax.net.ssl.SSLServerSocketFactory.getDefault().getSupportedCipherSuites()))%22%0A&#8221; message=&#8221;&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>however that might not work for your custom JRE if you haven&#8217;t included the scripting module, so here&#8217;s a Java program I made that prints all the available Ciphers of your JRE<\/p>\n<p>[pastacode lang=&#8221;java&#8221; manual=&#8221;public%20class%20PrintCiphers%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09var%20sslSocketFactory%20%3D%20javax.net.ssl.SSLServerSocketFactory.getDefault()%3B%0A%09System.out.println(%22SSLServerSocketFactory%20-%3E%20%22%20%2B%20sslSocketFactory.getClass().getName())%3B%0A%09try%20%7B%0A%20%20%09%20%20%20%20var%20getSupportedCipherSuitesMethod%20%3D%20sslSocketFactory.getClass().getMethod(%22getSupportedCipherSuites%22)%3B%0A%09%20%20%20%20String%5B%5D%20ciphers%20%3D%20(String%5B%5D)%20getSupportedCipherSuitesMethod.invoke(sslSocketFactory)%3B%0A%09%20%20%20%20int%20i%3D1%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(String%20c%20%3A%20ciphers)%20%7B%0A%09%09System.out.println(i%2B%2B%20%2B%20%22%20%22%20%2B%20c)%3B%0A%09%20%20%20%20%7D%0A%09%7D%20catch(Throwable%20t)%20%7B%0A%09%20%20%20%20t.printStackTrace()%3B%0A%09%7D%0A%20%20%20%20%7D%0A%7D%0A&#8221; message=&#8221;&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>If you run <code>PrintCiphers<\/code> on your OpenJDK&#8217;s full JRE, you will see almost 50 Cipher Suites available:<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;%24%20java%20PrintCiphers%3B%0A1%20TLS_AES_128_GCM_SHA256%0A2%20TLS_AES_256_GCM_SHA384%0A3%20TLS_CHACHA20_POLY1305_SHA256%0A4%20TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384%0A5%20TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256%0A6%20TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256%0A7%20TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384%0A8%20TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256%0A9%20TLS_RSA_WITH_AES_256_GCM_SHA384%0A10%20TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384%0A11%20TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384%0A12%20TLS_DHE_RSA_WITH_AES_256_GCM_SHA384%0A13%20TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256%0A14%20TLS_DHE_DSS_WITH_AES_256_GCM_SHA384%0A15%20TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256%0A16%20TLS_RSA_WITH_AES_128_GCM_SHA256%0A17%20TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256%0A18%20TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256%0A19%20TLS_DHE_RSA_WITH_AES_128_GCM_SHA256%0A20%20TLS_DHE_DSS_WITH_AES_128_GCM_SHA256%0A21%20TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384%0A22%20TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384%0A23%20TLS_RSA_WITH_AES_256_CBC_SHA256%0A24%20TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384%0A25%20TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384%0A26%20TLS_DHE_RSA_WITH_AES_256_CBC_SHA256%0A27%20TLS_DHE_DSS_WITH_AES_256_CBC_SHA256%0A28%20TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA%0A29%20TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA%0A30%20TLS_RSA_WITH_AES_256_CBC_SHA%0A31%20TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA%0A32%20TLS_ECDH_RSA_WITH_AES_256_CBC_SHA%0A33%20TLS_DHE_RSA_WITH_AES_256_CBC_SHA%0A34%20TLS_DHE_DSS_WITH_AES_256_CBC_SHA%0A35%20TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256%0A36%20TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256%0A37%20TLS_RSA_WITH_AES_128_CBC_SHA256%0A38%20TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256%0A39%20TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256%0A40%20TLS_DHE_RSA_WITH_AES_128_CBC_SHA256%0A41%20TLS_DHE_DSS_WITH_AES_128_CBC_SHA256%0A42%20TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA%0A43%20TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA%0A44%20TLS_RSA_WITH_AES_128_CBC_SHA%0A45%20TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA%0A46%20TLS_ECDH_RSA_WITH_AES_128_CBC_SHA%0A47%20TLS_DHE_RSA_WITH_AES_128_CBC_SHA%0A48%20TLS_DHE_DSS_WITH_AES_128_CBC_SHA%0A49%20TLS_EMPTY_RENEGOTIATION_INFO_SCSV%0A&#8221; message=&#8221;&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>but if you use your custom JRE to run <code>PrintCiphers<\/code> you will see only 23 Cipher Suites available:<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;%24%20jre%2Fbin%2Fjava%20PrintCiphers%0A1%20TLS_AES_128_GCM_SHA256%0A2%20TLS_AES_256_GCM_SHA384%0A3%20TLS_CHACHA20_POLY1305_SHA256%0A4%20TLS_RSA_WITH_AES_256_GCM_SHA384%0A5%20TLS_DHE_RSA_WITH_AES_256_GCM_SHA384%0A6%20TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256%0A7%20TLS_DHE_DSS_WITH_AES_256_GCM_SHA384%0A8%20TLS_RSA_WITH_AES_128_GCM_SHA256%0A9%20TLS_DHE_RSA_WITH_AES_128_GCM_SHA256%0A10%20TLS_DHE_DSS_WITH_AES_128_GCM_SHA256%0A11%20TLS_RSA_WITH_AES_256_CBC_SHA256%0A12%20TLS_DHE_RSA_WITH_AES_256_CBC_SHA256%0A13%20TLS_DHE_DSS_WITH_AES_256_CBC_SHA256%0A14%20TLS_RSA_WITH_AES_256_CBC_SHA%0A15%20TLS_DHE_RSA_WITH_AES_256_CBC_SHA%0A16%20TLS_DHE_DSS_WITH_AES_256_CBC_SHA%0A17%20TLS_RSA_WITH_AES_128_CBC_SHA256%0A18%20TLS_DHE_RSA_WITH_AES_128_CBC_SHA256%0A19%20TLS_DHE_DSS_WITH_AES_128_CBC_SHA256%0A20%20TLS_RSA_WITH_AES_128_CBC_SHA%0A21%20TLS_DHE_RSA_WITH_AES_128_CBC_SHA%0A22%20TLS_DHE_DSS_WITH_AES_128_CBC_SHA%0A23%20TLS_EMPTY_RENEGOTIATION_INFO_SCSV%0A&#8221; message=&#8221;&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>To solve the problem you must add the <code>jdk.crypto.cryptoki<\/code> module to the list of <code>--add-modules<\/code> parameter to your <code>jlink<\/code> command invocation, next time your run <code>PrintCiphers<\/code> you should see the full list of Cipher Suites and your SSL handshake issues should be gone.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL; Tell me already what to do: Add the jdk.crypto.cryptoki module to the list of &#8211;add-modules parameter to your jlink command invocation If you&#8217;re reading this you&#8217;re one of the few developers out there that wanted to distribute a java 9+ app (using either jdk 9, jdk 10, jdk 11 or jdk 12, as of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3798,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[15],"tags":[1596,583,1600,1598,1599,1597,1601,1603,1604,1602],"class_list":["post-3793","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-code","tag-handshake_failure","tag-java","tag-java10","tag-java12","tag-java9","tag-openjdk","tag-openjdk10","tag-openjdk11","tag-openjdk12","tag-openjdk9"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.gubatron.com\/blog\/wp-content\/uploads\/2019\/04\/dragon.jpg?fit=1953%2C1297&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5Unzf-Zb","jetpack-related-posts":[{"id":2767,"url":"https:\/\/www.gubatron.com\/blog\/ubuntu-packages-for-a-kick-ass-web-server\/","url_meta":{"origin":3793,"position":0},"title":"ubuntu packages for a kick ass web server","author":"gubatron","date":"September 7, 2012","format":false,"excerpt":"Copy and paste the following list on a file, say \"packages.txt\". To install all just do: sudo apt-get install $(cat packages.txt) accountsservice acpid adduser ant ant-optional apache2-utils apparmor apport apport-symptoms apt apt-transport-https apt-utils apt-xapian-index aptitude at base-files base-passwd bash bash-completion bc bind9-host bsdmainutils bsdutils busybox-initramfs busybox-static byobu bzip2 ca-certificates ca-certificates-java\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2186,"url":"https:\/\/www.gubatron.com\/blog\/new-location-of-src-jar-for-jdk-1-6-0_24-on-mac-os-x\/","url_meta":{"origin":3793,"position":1},"title":"New Location of src.jar for JDK 1.6.0_24 on Mac OS X","author":"gubatron","date":"March 5, 2011","format":false,"excerpt":"These Apple devs... why do you keep moving src.jar? Here's the new location: [bash]\/Library\/Java\/JavaVirtualMachines\/1.6.0_24-b07-330.jdk\/Contents\/Home\/src.jar[\/bash] Not there! If you don't see src.jar there, and you're running Mac OSX 10.6, and you did download the Java system update, you will have to go to developer.apple.com and download the \"Java for Mac OS\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3699,"url":"https:\/\/www.gubatron.com\/blog\/how-to-run-your-kotlin-gradle-built-app-from-the-command-line\/","url_meta":{"origin":3793,"position":2},"title":"How to run your Kotlin gradle built app from the command line","author":"gubatron","date":"July 20, 2017","format":false,"excerpt":"So you build your Kotlin app, you went through the trouble of creating a build.gradle script that you build with gradle assemble this outputs a a \"build\/libs\/kotlin.jar\" .jar file, but you have no clue how to run your Kotlin code from the command line. Doing it by hand with \"java\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3661,"url":"https:\/\/www.gubatron.com\/blog\/codejava-scanner-read-a-full-line\/","url_meta":{"origin":3793,"position":3},"title":"[CODE\/JAVA] Scanner &#8211; read a full line","author":"gubatron","date":"January 21, 2017","format":false,"excerpt":"I was solving problems at HackerRank to teach a friend how to code in Java and to process the input data it's convenient to use Java's built in Scanner class. However, in one of the problems we wanted to read a whole line at once and we noticed that the\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3001,"url":"https:\/\/www.gubatron.com\/blog\/how-to-gpu-mine-bitcoins-on-a-macbook-pro\/","url_meta":{"origin":3793,"position":4},"title":"How to GPU-mine BitCoins on a MacBook Pro","author":"gubatron","date":"April 27, 2013","format":false,"excerpt":"I've just gotten started into BitCoin a little late in the game (April 2013) and if you're reading this you're probably on the same boat. This post details the steps I took to start mining BitCoins with GPU on a MacBook Pro. 1.\u00a0Get DiabloMiner. You will need to have installed\u2026","rel":"","context":"In &quot;Geeklife&quot;","block_context":{"text":"Geeklife","link":"https:\/\/www.gubatron.com\/blog\/category\/geeklife\/"},"img":{"alt_text":"4195093260_78f080cab0_z","src":"https:\/\/i0.wp.com\/www.gubatron.com\/blog\/wp-content\/uploads\/2013\/04\/4195093260_78f080cab0_z.jpg?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.gubatron.com\/blog\/wp-content\/uploads\/2013\/04\/4195093260_78f080cab0_z.jpg?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.gubatron.com\/blog\/wp-content\/uploads\/2013\/04\/4195093260_78f080cab0_z.jpg?resize=525%2C300 1.5x"},"classes":[]},{"id":2660,"url":"https:\/\/www.gubatron.com\/blog\/5-object-oriented-programming-principles-learned-during-the-last-15-years\/","url_meta":{"origin":3793,"position":5},"title":"5 Object Oriented Programming Principles learned during the last 15 years","author":"gubatron","date":"February 1, 2012","format":false,"excerpt":"It was about 15 years ago when I first created my first class. I went from thinking of Object Oriented programming as this awesome paradigm I should know about, I remember having all these mental models of what objects where and learning all this new vocabulary that I really didn't\u2026","rel":"","context":"In &quot;Code&quot;","block_context":{"text":"Code","link":"https:\/\/www.gubatron.com\/blog\/category\/code\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts\/3793","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/comments?post=3793"}],"version-history":[{"count":5,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts\/3793\/revisions"}],"predecessor-version":[{"id":3799,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/posts\/3793\/revisions\/3799"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/media\/3798"}],"wp:attachment":[{"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/media?parent=3793"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/categories?post=3793"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gubatron.com\/blog\/wp-json\/wp\/v2\/tags?post=3793"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}