1

I'm writing a bit of a net utility, and I want it to have three protocols. PLAIN_TEXT, which, obviously, sends plain text/bytes over the network. ENCRYPTED_UNSECURED, which uses encryption, but doesn't verify any identities, and ENCRYPTED_SECURED, which uses SSL or TSL.

Right now, I've implemented PLAIN_TEXT, and I've partially implemented ENCRYPTED_UNSECURED, but I've hit a block. I'm using SSLSockets for ENCRYPTED_UNSECURED, but with self-signed certs and a fake trust manager, however, the self-signed certs need to come from a key manager, which comes from a keyfile, generated by the java key tool.

What I want to know is: would using the same key file in every instance of the server/client subtract from the security of the encryption? As it is ENCRYPTED_UNSECURED, I don't care about the security of the authentication.

Note: this is being done in java.

EDIT: Why this is not a duplicate? I'm not trying to import the certificate, I know how to do that, I want to know if using the same certificate could decrease the security of SSL/TSL's encryption protocol.

Uzbekjon
  • 11,655
  • 3
  • 37
  • 54
Socratic Phoenix
  • 556
  • 1
  • 7
  • 19
  • @MichałZaborowski No, it's not. I'm asking if ssl's encryption protocol security would be dampened by using the same, self-signed certificate, every time. Not how to import one... – Socratic Phoenix Apr 23 '16 at 19:33

1 Answers1

4

First, don't use actual SSL; SSLv2 was broken long ago (before 2000), and SSLv3 is now broken in most situations by POODLE (see Wikipedia and/or about a dozen questions on security.SE and crypto.SE). (Note the pseudoprotocol SSLv2Hello in Java/JSSE is not actually SSLv2 and is not a security vulnerability; OTOH since maybe 2010 it is very rarely needed or useful and nowadays more likely to cause confusion.)

Caveat: Java uses an "architecture" for cryptography that allows the same function(s) to be performed by different "providers" depending on how (by whom) your JRE is built and whether your installation has been modified. I will assume you use an Oracle (or formerly Sun) version of Java, or another version that uses the same cryptoproviders, which may include OpenJDK (which is mostly the same source as Oracle/Sun). In particular @Michal's answer seems to assume IBM although I see nothing in your question indicating this; IBM Java although otherwise compatible with Oracle/Sun Java has its own set of cryptoproviders and I don't know if any of the IBM differences affect the issues here.

Finally(!) to your question: distributing one privatekey (keystore) to numerous parties increases the risk of compromise at least proportionally to the number -- perhaps more because people are usually less careful about things that they perceive as someone else's responsibility.

TLS (like SSL before it) supports several different keyexchange options.

  • Ephemeral Diffie-Hellman in either classic (Zp) form DHE or elliptic-curve form ECDHE. These are usually preferred, and in particular Java/JSSE client orders them first (except for bugs on some early updates of Java7) because they provide Perfect Forward Secrecy; treating now as the beginning of the future -- as the saying goes 'today is the first day of the rest of your life' -- this also preserves confidentiality even if the server privatekey is already compromised, at least assuming the DHE/ECDHE implementation is correct.

    Be sure not to use (Zp) DHE if the server runs on Java7 or earlier; those versions used 768-bit DH group which is too small. Java8 defaults to 1024, which is enough except perhaps against top adversaries like NSA, see details at http://weakdh.org; and can be configured for 2048 which is definitely enough, see How to expand DH key size to 2048 in java 8 or several others. Note Java7 and up (but not 6 out of the box) support both DHE and ECDHE and prefer ECDHE, and Java ECDHE uses adequate curves, so in practice this should not be a problem.

  • (Plain) RSA. This is not secure if the privatekey is compromised, so in your situation you should if at all possible disable all plain-RSA ciphersuites. Ciphersuites of the form {TLS,SSL}_DHE_RSA_.. and TLS_ECDHE_RSA_... use RSA only for authentication not encryption; it is {SSL,TLS}_RSA_... that you must avoid.

  • Anonymous. TLS also supports keyexchange with DH or ECDH ephemeral keys but NO AUTHENTICATION (i.e. no certificate at all); these suites are called 'anonymous' instead of ephemeral and have the form {SSL/TLS}_{DH,ECDH}_anon_.... This is actually the exact technical match to your goal of providing confidentiality but not authentication, and needs NO keystore on the server or truststore on the client, plus avoids the hostname issue below. The possible downside is that anonymous suites are disabled by default, precisely because most users expect 'Secure Sockets' or 'Transport Security' to be secure, so you must enable them (at both ends); also if your organization (or your user's if different) has actually thought about a security policy, that thinking fairly often prohibits anonymous TLS for the same reason, and unlike some policy items this one can almost always be enforced by scans or monitors.

  • Others. TLS also supports nonephemeral aka static DH and ECDH, but practically no one uses them. TLS also supports non-PKC schemes using Kerberos, SRP, or just an arbitrary key (PSK), but these generally are appropriate only in special situations. Of these Java supports static-ECDH and Kerberos; using static-ECDH in your situation would be as insecure as plain-RSA, and IME even in environments where Kerberos is available using it with Java is about as much fun as hitting yourself in the head with hammers.

Hostname check: finally, for (non-anonymous) suites using a certificate, Java SSL/TLS client normally checks that the name used to connect to the server (either a domainname or an IP address) matches the certificate; the certificate must contain either

  • the name/address of the server, of which there can be more than one using SubjectAltNames aka SAN extension which is supported by keytool beginning in Java7 -- but a full list of names is difficult to arrange if you are going to use one cert on many servers especially ones you didn't identify in advance;

  • or a name with a 'wildcard' in the first component only: i.e. *.fred.example.com can be used for test1.fred.example.com test9999.fred.example.com anything.fred.example.com but NOT test.john.example.com anything.example.net or even fred.example.com (one level higher).

This check can be overridden, although the details vary some depending on whether you are using HTTPS or not and the Java version. Using anonymous suite(s) as above avoids the issue entirely.

Community
  • 1
  • 1
dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
  • So. Much. Detail. Thanks a huge amount, although I found a different solution to the root problem I was having, this definitely answers the question I asked, and more. – Socratic Phoenix Apr 24 '16 at 22:30
  • **Warning**: anonymous security doesn't just mean that you lose authentication, it will also mean that you lose confidentiality if active (man-in-the-middle) attacks are possible. Anonymous only works against passive (eavesdropping) attacks. Problem is: with TLS / internet connections active attacks are usually possible when passive attacks are possible (point in case: public WiFi hotspots). – Maarten Bodewes Jan 03 '17 at 15:39