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 $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 Your keystore contains 1 entry
Enter keystore password: trustno1
Keystore type: jks
Keystore provider: SUN
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:
Share This | Email this page to a friend Server Response from: blog1.codegear.com
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);
22 Responses to “Java & SSL”
Leave a Comment

RSS Feed
July 29th, 2005 at 10:30 am
Thanks Krishnan good work.
August 5th, 2005 at 12:26 am
Thank you very much, Krishnan, for a quality article. Immensely helpful!!
August 10th, 2005 at 1:59 pm
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
August 10th, 2005 at 5:01 pm
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
August 15th, 2005 at 8:00 am
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
August 17th, 2005 at 2:36 pm
Very good article !
September 7th, 2005 at 4:05 pm
Awesome
September 7th, 2005 at 4:05 pm
Awesome
September 22nd, 2005 at 10:42 am
selam
September 25th, 2005 at 10:11 pm
rttrh
September 28th, 2005 at 7:59 pm
hi .
December 6th, 2005 at 7:49 am
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 .
January 17th, 2006 at 4:54 pm
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
January 26th, 2006 at 9:46 pm
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
June 21st, 2006 at 11:58 pm
errors
July 21st, 2006 at 1:25 pm
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
August 9th, 2006 at 5:32 pm
Thanks for your article, you helped me to solve a hard prob
August 30th, 2006 at 9:15 am
foo[a
August 30th, 2006 at 9:15 am
foo[a
November 9th, 2006 at 2:48 pm
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?