Java & SSL

Java provides a whole slew of standardized APIs for everything under the Sun (pun intended) ranging from database access to security to protocols for remote access etc. Recently I was at a customer in Stockholm for 2 weeks – getting a testing/staging environment in place with a number of test and load scripts.

To put a long story short, a number of load test scripts I was writing required SSL communication and though I had written applications that communicated over SSL with pluggable authentication & authorization providers, I had never really gotten into SSL at the protocol level and decided to do that after my customer engagement.

SSL was originally developed and published by Netscape. SSL version 3.0 formed the basis of the Transport Layer Security (TLS) protocol version 1.0.

TLS 1.0 has 4 goals:

·        Security (establish a secure connection between end points for communication)

·        Interoperability (interoperate with different providers, implementations etc.)

·        Extensible (new key & encryption methods can be added without creating a new protocol)

·        Efficient (CPU & network utilization should be reduced)

The protocol stack looks something like this:

 

TLS Handshake | TLS Change Cipher spec | TLS Alert | HTTP
TLS Record Protocol
TCP
IP

The TLS Record Protocol encapsulates higher level protocols and has two basic properties:

·        Connection is private – that is, keys for encryption are generated uniquely for each connection

·        Connection is reliable – that is, tampering of data can be detected by integrity checks

It might be useful to understand how TLS operates. The essential sequences of steps for the handshake protocol are:

1.      client sends a hello with security capabilities it (the client) knows about

2.      server chooses the best capability from the client hello and responds with a chosen capability in its hello response (server hello)

3.      server sends authentication information about itself and sends a key

4.      server hello is done

5.      client generates a key and sends it to server encoded with key sent by server in step 4

6.      client finished

7.      server finished

8.      all subsequent communication between client and server switch to key generated in step 5

Asymmetric cryptography – also known as public key cryptography uses an encryption algorithm in which two keys are produced. One key is made public and the other is private. These keys are inverses of one another – that is, what one key encrypts, the other decrypts and vice-versa. And it is not computationally feasible/possible to derive the key inverse from one key. Examples of asymmetric algorithms include RSA, DSS etc.

In symmetric cryptography – also knows as secret key cryptography, the same key is used to encrypt and decrypt data.

Asymmetric cryptography is generally more computationally intensive compared to symmetric cryptography.

TLS 1.0 uses a combination of both asymmetric and symmetric cryptography. First, on the server side, a pair of public and private keys is generated. The private key is known only to the server while the public key can be distributed to clients. However, any party can supply a client with a public key thereby masquerading as a server. To solve this problem of public key distribution, certificates were introduced as a safe mechanism for an entity to pass on its public key to clients. The certificate is a digital equivalent of a passport and is issued by trusted organization usually called a certificate authority (e.g. Verisign, Thawte etc). The certificate authority will provide a certificate only upon proof of identity of the requester of the certificate. The certificate contains a number of fields including issuer (the certificate authority), the time period for which the certificate is valid, information about the entity that the certificate represents, the public key and the digital signature of the certificate authority that issued the certificate.

Thus, the recipient of the public key can examine the certificate and decide if it chooses to accept the public key.

To ensure data integrity TLS uses a cryptographic hash function. A hash is usually a fixed length of bits generated from a message. A cryptographic hash function is very similar to a checksum. While a checksum is used to check damages to data in transit, a cryptographic hash function is designed to check deliberate changes to data. Typically a cryptographic hash function will produce a large change to a resulting hash given a small change to the message. It is important to note that cryptographic hash does not require a key. Popular cryptographic hash functions include MD5, SHA-1 etc.

The TLS process begins by a TLS handshake as was explained previously. The details are:

1.      Client sends a hello with the protocol it supports and the list of cipher suites it supports. The cipher suite contains information about the algorithm used for asymmetric cryptography (key exchange), symmetric cryptography and hash function (for data integrity and message authentication). The cipher suite will typically contain a list with the preferred suite on top. For example, one of the suites in the list might be: SSL_RSA_WITH_RC4_128_MD5. This indicates that the RSA algorithm is used for public-private keys (asymmetric cryptography), a 128 bit RC4 algorithm is used for secret keys (symmetric cryptography) and the MD5 cryptography hash function is used for data integrity and message authentication. The client hello message includes a list of compression algorithms if supported.

2.      The server chooses the top cipher suite and protocol it knows about and responds with that information as a part of its server hello message.

3.      The server sends its public key certificate to the client (server authentication)

4.      The server completes its hello message

5.      The client generates a pre-master secret, encrypts it using the public key from step 3 and sends it to the server. Since the private key is only known to the server, only the server will be able to decrypt the message.

6.      Client sends a finish message – encrypted with the just negotiated algorithms and keys. The finish message includes the content of all previous handshake messages negotiated up until this message and its hash (Change Cipher Spec is done, but is not exactly a part of the handshake protocol and the finish is sent after the ChangeCipherSpec. Implies that communication will shift to using symmetric cryptography negotiated).

7.      Server sends an equivalent finish message. The previous handshake messages included in the finish message with [its] hash prevent an eavesdropper from modifying any of the handshake messages (Change Cipher Spec is done, but is not exactly a part of the handshake protocol and the finish is sent after the ChangeCipherSpec. Implies that communication will shift to using symmetric cryptography negotiated).

8.      From the pre-master key, the client and server arrive independently to the same master key value (symmetric cryptography) that is used for subsequent encryption of messages between the client and the server for that session.

On the Java side, Java provides an implementation of the TLS (version 1.0) and the SSL protocol (version 3.0) including encryption, server authentication and message integrity. The API is called the Java Secure Socket Extension (JSSE) and bundles an implementation of that API as well.

In Java, certificates have to be placed in a keystore - a Java Key Store to be precise. The keytool command line utility (bundled with the JDK) can generate test certificates or import existing certificates (issued certificates from a certificate authority). A keystore is standard mechanism to transport keys and certificates in a password protected file.

For example, to generate a RSA keypair, you would run:

$prompt> keytool -genkey -alias serverCert -keyalg RSA -keysize 1024 -validity 9999 -keystore server.ks

Enter keystore password:  trustno1
What is your first and last name?
  [Unknown]:  Krishnan Subramanian
What is the name of your organizational unit?
  [Unknown]:  Professional Services
What is the name of your organization?
  [Unknown]:  Borland Software Corporation
What is the name of your City or Locality?
  [Unknown]:  Amstelveen
What is the name of your State or Province?
  [Unknown]:  North Holland
What is the two-letter country code for this unit?
  [Unknown]:  NL
Is CN=Krishnan Subramanian, OU=Professional Services, O=Borland Software Corporation, L=Amstelveen, ST=North Holland, C=NL correct?
  [no]:  y
Enter key password for
        (RETURN if same as keystore password): 

$prompt>

Initially when the keytool’s –genkey option is used, an RSA keypair is generated and the public key is wrapped in a self-signed certificate. Self-signed in the sense that the issuer of the certificate is the same as that of the entity for whom the keypair is being generated.

If you were to apply to a commercial certificate authority (e.g. Thawte, Verisign etc) you would generate a certificate signing request (CSR) using the keytool’s –certreq option on the above generate keystore and submit the output of the certificate signing request along with necessary documentation proving your organization’s identity among others. After verification of documents, the certificate authority will issue you a certificate that you can then import into the keystore.

However for testing purposes, it is overkill to apply to a certificate authority (fees for a certificate are usually a few hundred dollars). Remember that during the TLS handshake process, the server will send its certificate to the client. And it is up to the client to decide whether it will trust the certificate sent by the server. The trust is usually established by checking the issuing authority. There may be a certificate chain in which case, the client will navigate the certificate chain until it finds an issuing authority it will trust.

You can check the content of the keystore using the keytool’s –list option. For example,

$prompt>keytool -list -keystore server.ks
Enter keystore password:  trustno1

Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

servercert, Jul 28, 2005, keyEntry,
Certificate fingerprint (MD5): 3E:4C:D2:5F:D7:1C:F1:BF:5C:C2:CE:20:17:52:94:69
 

The above entry displays one keyEntry (that is, a public/private key pair). It is important to note that the private key in the keystore is not accessible using the keytool utility.

For an SSL Server application, for example – a Socket based application; you would specify the location and password of the keystore as JVM parameters.

Here is a sample Socket Server application:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
public class SocketServer {

public static final boolean USE_SECURE = true;
  public static final int PORT = 6666;
  public static final String PASS_PHRASE = "knock knock";
  public static void main(String[] args) throws IOException {
    ServerSocket mServerSocket = null;
    if (USE_SECURE) {
      mServerSocket = getSecureSocket();
    }
    else {
      mServerSocket = getPlainSocket();
    }
    System.out.println("SocketServer listening . . . ");
    startListening(mServerSocket);

Posted by Krishnan Subramanian on July 28th, 2005 under General, J2EE, Java |



22 Responses to “Java & SSL”

  1. Yusuf Celik Says:

    Thanks Krishnan good work.

  2. Dan Mazur Says:

    Thank you very much, Krishnan, for a quality article. Immensely helpful!!

  3. Maxit Says:

    how can i use ssl without using Certificate iussed by a trusted organization but only a

    keypair. For example I, with tomcat AP, succeed using ssl connection using only a keypair, but in a standalone application I don’t.

    thanks

  4. Krishnan Says:

    Maxit,

    You do not mention too many details. For example, if you use a CA that is not trusted, then the browser will display a warning to that effect and you may have chosen to accept that certificate permanently. In which case, you will not be prompted with the warning any more.

    In any case, it is possible for a client to blindly trust all server certificates. You need to create an implementation of the javax.net.ssl.X509TrustManager interface and then override all the methods to return a null. In your client, you can then initialize the SSLContext with your implementation of the X509TrustManager. And then the SSLContext instance can be used to get a SocketFactory from which you can create SSL connections.

    In the above case, the handshake will succeed with the client blindly trusting the server certificate. Caveat emptor.

    -krish

  5. Henner Says:

    Hi Krishnan,

    thanks for the blog: really good site exact for the time I need it. Thanks:

    Had some problems with the error "No trusted certificate found" under Linux (works fine for windows on another server) For some reason the cacert under Linux does not include the certificates I needed. So I added an

    System.setProperty("javax.net.ssl.trustStore","/file/to/windows/cacerts");

    in the code and could go through with java

    -Djavax.net.ssl.keyStore=/home/of/personal/server.ks -Djavax.net.ssl.keyStorePassword=changeit JavaCodeToExecuteClass

    Thanks for the advice for the server.ks

    Henner

  6. Alessandro Says:

    Very good article !

  7. Sankar Ramu Says:

    Awesome :)

  8. Sankar Ramu Says:

    Awesome :)

  9. Mustafa+ %c3%87etiner Says:

    selam

  10. m Says:

    rttrh

  11. hassan Says:

    hi .

  12. karthik Says:

    Hey , iam getting an error

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found

    but the trust certificates are loaded properly. can u guide me in this .

  13. Jan Choike Says:

    Hello:

    Step #3 in your enumeration of the "essential sequences of steps for the handshake protocol are" states that "server sends authentication information about itself and sends a key". However, according to RFC 2246, a TLS-enabled server is not required to send this certificate. As show in the communication flow on page 30, the certificate (following the ServerHello) is option (denoted by the *).

    How must I interpret your explanation so that it confirms my understanding of the TLS RFC? This reason I ask is this: every Java implemenation example of SSL/TLS involves a certificate (e.g. JSSE, PureTLS), and I need to know how it is possible to carry out this handshakes without the server certificate.

    Thank you for your consideration and article! Other than this one discrepancy in my understanding, your explanation is excellent.

    Sincerely,

    Jan L. Choike

    jlchoike@gmail.com

  14. krish Says:

    Jan,

    You raise an excellent point. Based on my understanding of TLS, the server may not send its certificate if the agreed upon key exchange between the client and server is anonymous. Which implies that the client is not required to trust the server.

    In such a scenario, the server will usually send a key exchange message that will allow the client to exchange a pre-master secret.

    Note that the key exchange message will be sent iff:

    - the server does not send its certificate to the client

    - or, the certificate does not contain enough data (e.g. a weak algorithm) for the client to exchange a pre-master secret.

    Hopefully that clears things up?

    -krish

  15. stephanie sauter Says:

    errors

  16. iketutg Says:

    Hi i’m not yet try your source code ssl , but i have question, can i used for simultaneous clients connect to Sever.

    Thank’s

    IKetutG

  17. alban maillere Says:

    Thanks for your article, you helped me to solve a hard prob :)

  18. c Says:

    foo[a

  19. c Says:

    foo[a

  20. Ming Says:

    I tried to use JMeter to load test our https server. JMeter doesn’t decrypt the http response body (it could decrypt the http header). So I enabled debug. From the debug log, I don’t see any error, only thing I could see is that the debug log missing the statement "Found trusted certificate:", although the certificate is in the chain. How significant is that missing statement?

Leave a Comment


Server Response from: blog1.codegear.com

 
Copyright© 1994 - 2008 Embarcadero Technologies, Inc. All rights reserved. Contact Us   Legal Notices   Privacy Policy   Report Software Piracy