{"id":1331,"date":"2009-11-10T00:00:59","date_gmt":"2009-11-09T23:00:59","guid":{"rendered":"http:\/\/blog.jteam.nl\/?p=1331"},"modified":"2009-11-10T00:00:59","modified_gmt":"2009-11-09T23:00:59","slug":"securing-connections-with-tls","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/","title":{"rendered":"Securing connections with TLS"},"content":{"rendered":"<p>In this article I&#8217;ll explore some ways to secure socket communication with <a href=\"http:\/\/tools.ietf.org\/html\/rfc4346\">TLS<\/a> from a java application. To make it more concrete I&#8217;ll show you <a href=\"http:\/\/code.google.com\/p\/subethasmtp\/\">SubEtha SMTP<\/a> (an excellent Java based bare bones SMTP server) and the recent TLS extensions I added to it.<\/p>\n<p>What you&#8217;ll get from this article:<\/p>\n<ul>\n<li>How to mix secure with insecure communication<\/li>\n<li>How to start TLS, server side<\/li>\n<li>How to make the connection really safe<\/li>\n<li>How to add client authentication<\/li>\n<li>How to apply this with SubEtha SMTP<\/li>\n<\/ul>\n<p>I&#8217;ll assume you know Java, understand the concept of a socket and the purpose of TLS\/SSL.<br \/>\n<!--more--><\/p>\n<h3>How to mix TLS with insecure communication<\/h3>\n<p>Often protocols need to operate both securely and insecurely. Be it for simplicity or for backward compatibility. The latter reason is important for SMTP as it is traditionally insecure.<\/p>\n<p>There are two options to secure SMTP with TLS. Let discuss them shortly:<\/p>\n<ul>\n<li>Option 1: use a separate server port for TLS. The client will connect to a separate port for secure mode and the TLS handshake will begin immediately after the socket is open. This mode is suitable for new protocols that need to be completely secure. This option is <i>not<\/i> suitable for protocols that also need to operate insecurely like SMTP. (See <a href=\"http:\/\/www.ietf.org\/rfc\/rfc2595.txt\">RFC2595 chapter 7<\/a> for more information.)<\/li>\n<li>Option 2: use a single server port for both insecure as secure communication. The trick is to start the TLS handshake simultaneously on the client and the server. For telnet based protocols like SMTP, POP3 and IMAP, this is done with the STARTTLS command (<a href=\"http:\/\/www.ietf.org\/rfc\/rfc2595.txt\">RFC2595<\/a> and <a href=\"http:\/\/www.ietf.org\/rfc\/rfc3207.txt\">RFC3207<\/a>).<\/li>\n<\/ul>\n<p>This article will focus on the server side of option 2, but most of the code is identical to the client side and for option 1.<\/p>\n<h3>How to open a TLS connection &#8211; Server<\/h3>\n<p>TLS is implemented by <abbr title=\"Java Secure Socket Extension\">JSSE<\/abbr> which is part of the JDK since J2SDK 1.4. The <a href=\"http:\/\/java.sun.com\/javase\/6\/docs\/technotes\/guides\/security\/jsse\/JSSERefGuide.html\">JSSE Reference Guide<\/a> is a good source of information, both general as very specific.<\/p>\n<p>To listen on a port (without TLS), the server first needs to create a <a href=\"http:\/\/java.sun.com\/javase\/6\/docs\/api\/javax\/net\/ssl\/SSLServerSocket.html\">ServerSocket<\/a> and then wait for new connections. This can be as simple as:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  int bindPort = 25;&lt;br&gt;\n  InetSocketAddress bindAddress = new InetSocketAddress(bindPort);&lt;br&gt;\n  ServerSocket serverSocket = new ServerSocket();&lt;br&gt;\n  serverSocket.setReuseAddress(true);&lt;br&gt;\n  serverSocket.bind(bindAddress);&lt;br&gt;\n  while (true) {&lt;br&gt;\n    Socket socket = serverSocket.accept();&lt;br&gt;\n    \/\/ ...start a new thread that will communicate on the socket...&lt;br&gt;\n  }&lt;br&gt;\n<\/pre><\/p>\n<p>Later, when both parties agree that TLS should be started, a <a href=\"http:\/\/java.sun.com\/javase\/6\/docs\/api\/javax\/net\/ssl\/SSLSocket.html\">SSLSocket<\/a> is needed. The SSLSocket will wrap the normal socket that was created by the ServerSocket.<\/p>\n<p>Here is the code. It is very similar to what SubEtha SMTP does (find it in <a href=\"http:\/\/code.google.com\/p\/subethasmtp\/source\/browse\/tags\/3.1.2\/src\/org\/subethamail\/smtp\/server\/SMTPServer.java#316\">SMTPServer#createSSLSocket<\/a>).<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Get the default SSLSocketFactory&lt;br&gt;\n  SSLSocketFactory sf = ((SSLSocketFactory) SSLSocketFactory.getDefault());&lt;\/p&gt;\n&lt;p&gt;  \/\/ Wrap 'socket' from above in a SSL socket&lt;br&gt;\n  InetSocketAddress remoteAddress =&lt;br&gt;\n          (InetSocketAddress) socket.getRemoteSocketAddress();&lt;br&gt;\n  SSLSocket s = (SSLSocket) (sf.createSocket(&lt;br&gt;\n          socket, remoteAddress.getHostName(), socket.getPort(), true));&lt;\/p&gt;\n&lt;p&gt;  \/\/ we are a server&lt;br&gt;\n  s.setUseClientMode(false);&lt;\/p&gt;\n&lt;p&gt;  \/\/ allow all supported protocols and cipher suites&lt;br&gt;\n  s.setEnabledProtocols(s.getSupportedProtocols());&lt;br&gt;\n  s.setEnabledCipherSuites(s.getSupportedCipherSuites());&lt;\/p&gt;\n&lt;p&gt;  \/\/ and go!&lt;br&gt;\n  s.startHandshake();&lt;\/p&gt;\n&lt;p&gt;  \/\/ continue communication on 'socket'&lt;br&gt;\n  socket = s;&lt;br&gt;\n<\/pre><\/p>\n<p>When this code has executed, the application can continue communicating on <code>socket<\/code> as before, only now all data is encrypted prior to being sent over the big bad internet.<\/p>\n<h3>You are not done!<\/h3>\n<p>The code above mostly works but has some problems:<\/p>\n<ul>\n<li>The default SSLSocketFactory is used. Configuring which private key is used is done through the JVM (<a href=\"http:\/\/java.sun.com\/javase\/6\/docs\/technotes\/guides\/security\/jsse\/JSSERefGuide.html#CustomizingStores\">info<\/a>). If there is none, an anonymous cipher suite will be selected leading to vulnerability of man-in-the-middle-attacks. <em>You have been warned!<\/em><br \/>In addition, you now depend on the list of trusted certificate authorities known to the JVM.<\/li>\n<li><em>Allowing all supported protocols and cipher suites is insecure.<\/em> SSLv1 and SSLv2 have problems, but worse, some older cipher suites are so badly broken that they hardly offer any protection.<\/li>\n<li>It has no exception handling. You will need to catch IOException, but your are better of catching SSLHandshakeException separately as it is common to get the &#8220;no cipher suites in common&#8221; error (there is no need to log a whole stacktrace for that).<\/li>\n<\/ul>\n<p>Lets fix the first 2 problems.<\/p>\n<h3>Adding key management<\/h3>\n<p>To get back some control over the used certificates, you&#8217;ll need to create your own SSLSocketFactory in the form of a <a href=\"http:\/\/java.sun.com\/javase\/6\/docs\/technotes\/guides\/security\/jsse\/JSSERefGuide.html#SSLContext\">SSLContext<\/a>. Here are the steps needed to create a SSLContext:<\/p>\n<p>First you&#8217;ll create the <em>key store<\/em>. The key store contains your own private key and all the certificates that signed that key. The key store is backed by a file and protected by a passphrase.<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Key store for your own private key and signing certificates&lt;br&gt;\n  InputStream keyStoreResource = new FileInputStream(&quot;\/path\/to\/keystore.jks&quot;);&lt;br&gt;\n  char&#x5B;] keyStorePassphrase = &quot;secret&quot;.toCharArray();&lt;br&gt;\n  KeyStore ksKeys = KeyStore.getInstance(&quot;JKS&quot;);&lt;br&gt;\n  ksKeys.load(keyStoreResource, keyStorePassphrase);&lt;br&gt;\n<\/pre><\/p>\n<p>The file <code>\/path\/to\/keystore.jks<\/code> is in the default format as created by <a href=\"http:\/\/java.sun.com\/javase\/6\/docs\/technotes\/tools\/solaris\/keytool.html\">keytool<\/a> which is part of the JDK.<\/p>\n<p>A more interesting option is to use a key store in the standardized PKCS#12 format (which is also supported by openssl):<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Key store for your own private key and signing certificates&lt;br&gt;\n  InputStream keyStoreResource = new FileInputStream(&quot;\/path\/to\/keystore.p12&quot;);&lt;br&gt;\n  char&#x5B;] keyStorePassphrase = &quot;secret&quot;.toCharArray();&lt;br&gt;\n  KeyStore ksKeys = KeyStore.getInstance(&quot;PKCS12&quot;);&lt;br&gt;\n  ksKeys.load(keyStoreResource, keyStorePassphrase);&lt;br&gt;\n<\/pre><\/p>\n<p>As a key store potentially contains many keys, you need a KeyManager to determine which key to use. Under the assumption that there is only 1 key in the key store, the default KeyManager is fine. Of course, there is an extra indirection through a KeyManagerFactory:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ KeyManager decides which key material to use.&lt;br&gt;\n  KeyManagerFactory kmf = KeyManagerFactory.getInstance(&quot;SunX509&quot;);&lt;br&gt;\n  kmf.init(ksKeys, keyStorePassphrase);&lt;br&gt;\n<\/pre><\/p>\n<p>The second component you need is the <em>trust store<\/em>. A trust store contains certificates of trusted certificate authorities. These are needed to validate client certificates. You can use the JDK trust store (located at either <code>$JAVA_HOME\/lib\/security\/jssecacerts<\/code> or <code>$JAVA_HOME\/lib\/security\/cacerts<\/code>), or you can create one from scratch with keytool.<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Trust store contains certificates of trusted certificate authorities.&lt;br&gt;\n  \/\/ Needed for client certificate validation.&lt;br&gt;\n  InputStream trustStoreIS = new FileInputStream(&quot;\/path\/to\/truststore.certs&quot;);&lt;br&gt;\n  char&#x5B;] trustStorePassphrase = &quot;secret&quot;.toCharArray();&lt;br&gt;\n  KeyStore ksTrust = KeyStore.getInstance(&quot;JKS&quot;);&lt;br&gt;\n  ksTrust.load(trustStoreIS, trustStorePassphrase);&lt;br&gt;\n<\/pre><\/p>\n<p>And again a TrustManager (the default one accepts all certificate authorities in the trust store):<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ TrustManager decides which certificate authorities to use.&lt;br&gt;\n  TrustManagerFactory tmf = TrustManagerFactory.getInstance(&quot;SunX509&quot;);&lt;br&gt;\n  tmf.init(ksTrust);&lt;br&gt;\n<\/pre><\/p>\n<p>Finally you can create the SSLContext:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  SSLContext sslContext = SSLContext.getInstance(&quot;TLS&quot;);&lt;br&gt;\n  sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);&lt;br&gt;\n<\/pre><\/p>\n<p>Luckily the code above only needs to run once. Thereafter you can get the SSLSocketFactory as follows.<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Get your own custum SSLSocketFactory&lt;br&gt;\n  SSLSocketFactory sf = sslContext.getSocketFactory();&lt;\/p&gt;\n&lt;p&gt;  \/\/ continu as above&lt;br&gt;\n<\/pre><\/p>\n<h3>Removing dangerous protocols and cipher suites<\/h3>\n<p>The second problem the code has is that it allows for broken protocols and cipher suites. To fix this you&#8217;ll need to indicate exactly which protocols and cipher suites you want to enable.<\/p>\n<p>Look at the code above and replace the arguments to <code>setEnabledProtocols<\/code> and <code>setEnabledCipherSuites<\/code>:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ select supported protocols and cipher suites&lt;br&gt;\n  s.setEnabledProtocols(SslConstants.intersection(&lt;br&gt;\n        s.getSupportedProtocols(), StrongSsl.ENABLED_PROTOCOLS));&lt;br&gt;\n  s.setEnabledCipherSuites(SslConstants.intersection(&lt;br&gt;\n        s.getSupportedCipherSuites(), StrongSsl.ENABLED_CIPHER_SUITES));&lt;br&gt;\n<\/pre><\/p>\n<p><code><a href=\"http:\/\/blog.jteam.nl\/wp-content\/uploads\/2009\/10\/StrongTls.java\">StrongTls.java<\/a><\/code> is a class that lists strong protocols and ciphersuites. You can use it under the Apache 2 license. The list was compiled by a security expert at the Dutch government.<\/p>\n<h3>Adding client authentication<\/h3>\n<p>Most internet applications do not require strict identification of the client. Therefore by default TLS only lets the client check the identify of the server (hence the need for a signed private key on the server). However, for some applications client authentication is just as important.<\/p>\n<p>To indicate this, add the following code just before the start of the handshake:<br \/>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Client must authenticate&lt;br&gt;\n  s.setNeedClientAuth(true);&lt;br&gt;\n<\/pre><\/p>\n<p>When the client certificate is not signed by a trusted certificate authority, the handshake will fail. After a successful handshake the client certificates can be accessed with:<\/p>\n<p><pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Get client certificates&lt;br&gt;\n  Certificate&#x5B;] peerCertificates = s.getSession().getPeerCertificates();&lt;br&gt;\n<\/pre><\/p>\n<h3>Securing SubEtha SMTP<\/h3>\n<p>Now lets apply all this to SubEtha SMTP. First of all you&#8217;ll need to make sure that you have SubEtha SMTP version 3.1.2 or higher. This is the version I extended to optionally require TLS and to allow custom SSLSocket creation.<\/p>\n<p>First create the SSLContext as described above:<br \/>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Key store for your own private key and signing certificates.&lt;br&gt;\n  InputStream keyStoreIS = new FileInputStream(&quot;\/path\/to\/keystore.p12&quot;);&lt;br&gt;\n  char&#x5B;] keyStorePassphrase = &quot;secret&quot;.toCharArray();&lt;br&gt;\n  KeyStore ksKeys = KeyStore.getInstance(&quot;PKCS12&quot;);&lt;br&gt;\n  ksKeys.load(keyStoreIS, keyStorePassphrase);&lt;\/p&gt;\n&lt;p&gt;  \/\/ KeyManager decides which key material to use.&lt;br&gt;\n  KeyManagerFactory kmf = KeyManagerFactory.getInstance(&quot;SunX509&quot;);&lt;br&gt;\n  kmf.init(ksKeys, keyStorePassphrase);&lt;\/p&gt;\n&lt;p&gt;  \/\/ Trust store contains certificates of trusted certificate authorities.&lt;br&gt;\n  \/\/ We'll need this to do client authentication.&lt;br&gt;\n  InputStream trustStoreIS = new FileInputStream(&quot;\/path\/to\/truststore.certs&quot;);&lt;br&gt;\n  char&#x5B;] trustStorePassphrase = &quot;secret&quot;.toCharArray();&lt;br&gt;\n  KeyStore ksTrust = KeyStore.getInstance(&quot;JKS&quot;);&lt;br&gt;\n  ksTrust.load(trustStoreIS, trustStorePassphrase);&lt;\/p&gt;\n&lt;p&gt;  \/\/ TrustManager decides which certificate authorities to use.&lt;br&gt;\n  TrustManagerFactory tmf = TrustManagerFactory.getInstance(&quot;SunX509&quot;);&lt;br&gt;\n  tmf.init(ksTrust);&lt;\/p&gt;\n&lt;p&gt;  SSLContext sslContext = SSLContext.getInstance(&quot;TLS&quot;);&lt;br&gt;\n  sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);&lt;br&gt;\n<\/pre><\/p>\n<p>Then create a subclass of SMTPServer and start it:<br \/>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">&lt;br&gt;\n  \/\/ Your message handler factory.&lt;br&gt;\n  MessageHandlerFactory mhf = new YourMessageHandlerFactory();&lt;\/p&gt;\n&lt;p&gt;  SMTPServer smtpServer = new SMTPServer(mhf) {&lt;br&gt;\n    @Override&lt;br&gt;\n    public SSLSocket createSSLSocket(Socket socket) throws IOException {&lt;br&gt;\n      InetSocketAddress remoteAddress =&lt;br&gt;\n              (InetSocketAddress) socket.getRemoteSocketAddress();&lt;\/p&gt;\n&lt;p&gt;      SSLSocketFactory sf = sslContext.getSocketFactory();&lt;br&gt;\n      SSLSocket s = (SSLSocket) (sf.createSocket(&lt;br&gt;\n              socket, remoteAddress.getHostName(), socket.getPort(), true));&lt;\/p&gt;\n&lt;p&gt;      \/\/ we are a server&lt;br&gt;\n      s.setUseClientMode(false);&lt;\/p&gt;\n&lt;p&gt;      \/\/ select strong protocols and cipher suites&lt;br&gt;\n      s.setEnabledProtocols(StrongSsl.intersection(&lt;br&gt;\n            s.getSupportedProtocols(), StrongSsl.ENABLED_PROTOCOLS));&lt;br&gt;\n      s.setEnabledCipherSuites(StrongSsl.intersection(&lt;br&gt;\n            s.getSupportedCipherSuites(), StrongSsl.ENABLED_CIPHER_SUITES));&lt;\/p&gt;\n&lt;p&gt;      \/\/\/\/ Client must authenticate&lt;br&gt;\n      \/\/ s.setNeedClientAuth(true);&lt;\/p&gt;\n&lt;p&gt;      return s;&lt;br&gt;\n    }&lt;br&gt;\n  };&lt;\/p&gt;\n&lt;p&gt;  smtpServer.setHostName(host);&lt;br&gt;\n  smtpServer.setPort(port);&lt;br&gt;\n  smtpServer.setBindAddress(bindAddress);&lt;br&gt;\n  smtpServer.setRequireTLS(true);&lt;br&gt;\n  smtpServer.start();&lt;br&gt;\n<\/pre><\/p>\n<p>That&#8217;s it, SubEtha SMTP is now accessible only with TLS. If you also required client authentication, you can get the client certificates from the context parameter in the message handler.<\/p>\n<h3>Some further considerations<\/h3>\n<p>To prevent &#8220;no cipher suites in common&#8221; errors, it is wise to install the unlimited security library. Download &#8220;Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6&#8221; from the <a href=\"http:\/\/java.sun.com\/javase\/downloads\/index.jsp\">Sun Java download site<\/a> (last item in the list) and install it as described in the readme. This allows for longer keys which can improve security and increases TLS compatibility.<\/p>\n<h3>Conclusions<\/h3>\n<p>With some minor adjustments to the excellent SubEtha SMTP library, it is possible to have very secure e-mail transmission.<\/p>\n<h3>Further reading<\/h3>\n<ul>\n<li><a href=\"http:\/\/java.sun.com\/javase\/6\/docs\/technotes\/guides\/security\/jsse\/JSSERefGuide.html\">JSSE reference guide<\/a><\/li>\n<li><a href=\"http:\/\/java.sun.com\/products\/javamail\/SSLNOTES.txt\">Using SSL with javamail<\/a>, however the code shown here has more general (client) uses as well.<\/li>\n<\/ul>\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/bit.ly\/3BAo305\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" alt=\"\" class=\"wp-image-20303\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-300x75.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-768x192.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1536x384.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-2048x512.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1920x480.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>In this article I&#8217;ll explore some ways to secure socket communication with TLS from a java application. To make it more concrete I&#8217;ll show you SubEtha SMTP (an excellent Java based bare bones SMTP server) and the recent TLS extensions I added to it. What you&#8217;ll get from this article: How to mix secure with [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[10],"tags":[11,71],"class_list":["post-1331","post","type-post","status-publish","format-standard","hentry","category-development","tag-java","tag-security"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Securing connections with TLS - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Securing connections with TLS - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"In this article I&#8217;ll explore some ways to secure socket communication with TLS from a java application. To make it more concrete I&#8217;ll show you SubEtha SMTP (an excellent Java based bare bones SMTP server) and the recent TLS extensions I added to it. What you&#8217;ll get from this article: How to mix secure with [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2009-11-09T23:00:59+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" \/>\n<meta name=\"author\" content=\"Erik van Oosten\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Erik van Oosten\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/\",\"url\":\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/\",\"name\":\"Securing connections with TLS - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\",\"datePublished\":\"2009-11-09T23:00:59+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/992bb0fa3ad86e2552b688ac7ac98734\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#primaryimage\",\"url\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\",\"contentUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Securing connections with TLS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/992bb0fa3ad86e2552b688ac7ac98734\",\"name\":\"Erik van Oosten\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/196760a91365490d76a137547feaf006?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/196760a91365490d76a137547feaf006?s=96&d=mm&r=g\",\"caption\":\"Erik van Oosten\"},\"url\":\"https:\/\/trifork.nl\/blog\/author\/eriko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Securing connections with TLS - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/","og_locale":"en_US","og_type":"article","og_title":"Securing connections with TLS - Trifork Blog","og_description":"In this article I&#8217;ll explore some ways to secure socket communication with TLS from a java application. To make it more concrete I&#8217;ll show you SubEtha SMTP (an excellent Java based bare bones SMTP server) and the recent TLS extensions I added to it. What you&#8217;ll get from this article: How to mix secure with [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/","og_site_name":"Trifork Blog","article_published_time":"2009-11-09T23:00:59+00:00","og_image":[{"url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","type":"","width":"","height":""}],"author":"Erik van Oosten","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Erik van Oosten","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/","url":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/","name":"Securing connections with TLS - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#primaryimage"},"thumbnailUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","datePublished":"2009-11-09T23:00:59+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/992bb0fa3ad86e2552b688ac7ac98734"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#primaryimage","url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","contentUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/securing-connections-with-tls\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"Securing connections with TLS"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/992bb0fa3ad86e2552b688ac7ac98734","name":"Erik van Oosten","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/196760a91365490d76a137547feaf006?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/196760a91365490d76a137547feaf006?s=96&d=mm&r=g","caption":"Erik van Oosten"},"url":"https:\/\/trifork.nl\/blog\/author\/eriko\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/1331","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=1331"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/1331\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=1331"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=1331"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=1331"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}