|
|
|||||||||||||||
by Krishnan Viswanath | |||||||||||||||
| ||||||||
Java Remote Method
Invocation (RMI) introduced a powerful mechanism for distributing
application logic across different machines. Instead of having to perform tasks in one monolithic central
system, RMI made it possible to build
modular and manageable applications where the computing logic could be
distributed. RMI has been the primary communication mechanism for various
server-side component architectures, including Enterprise JavaBeans
(EJB). Introduced with Java 1.1, RMI has been steadily
evolving with every major release and has seen the introduction of three
new important features with the release of Java 5.0. The new features
include support for dynamic stub generation, RMI over SSL, and the
ability to launch a Java RMI sever as an extended Internet service
(xinetd) daemon in Unix systems. In this article we will
cover these additions.
The default RMI communication mechanism—the Java Remote Method
Protocol (JRMP)—is not secure. It is possible to secure
the communication by writing custom socket factories using Java Secure
Socket Extension (JSSE). But this approach puts the burden of writing additional code
on the developers, who must take care of securing data exchange using
cryptography. Java 5.0 alleviates this issue by introducing two new
classes, javax.rmi.ssl.SslRMIClientSocketFactory and
javax.rmi.ssl.SslRMIServerSocketFactory, that provide the
ability to secure the communication channel between the client and the
server using the Secure Sockets Layer (SSL)/Transport Layer Security
(TLS) protocols. These socket factory classes provide a simple and
elegant way to use JSSE for secure Java RMI communication, which enables
enforcement of data integrity, data confidentiality (through
encryption), server authentication, and (optionally) client
authentication for remote method invocations. This means developers can
focus on the business logic of the distributed application instead of
dealing with security-related plumbing.
In this section we will go over the details of using the new SSL socket factories for RMI communication. But before we delve into details, we will provide a brief introduction on transport level security. Secure Sockets Layer (SSL) is the most widely used protocol for implementing cryptography over a distributed communication protocol such as HTTP. The primary purpose of SSL is to provide privacy, data integrity, authenticity, and non-repudiation. This is achieved by using symmetric key cryptography for data encryption between the client and server, and asymmetric key cryptography (or public/private key cryptography) to authenticate the identities of communicating parties as well as to encrypt the shared encryption key that is used during establishing SSL session.
A client and server that are about to exchange information via the SSL protocol first establish an SSL session after exchanging a series of messages, a process known as an SSL handshake. This is a multi-step process, so we will take a look at a few important messages that are sent between the client and server. The messages in the following sections are from the SSL debug output from the sample application that is provided along with this article (see Resources). The client starts the handshake process by sending a "Hello" message to the server with a list of cipher suites that it supports. This message is as follows:
*** ClientHello, TLSv1
RandomCookie: GMT: 1101964544 bytes = { 99,...,232 }
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5,
SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA, ...]
The server responds with a "Hello" message along with a decision on
the cipher suite and the compression method. In this particular case, the
server chose SSL_RSA_WITH_RC4_128_MD5 for
cipher method and 0 for compression method.
*** ServerHello, TLSv1
RandomCookie: GMT: 1101964544 bytes = { 78,...,209}
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
***
%% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
What this means is that the client-server communication is going to perform the following:
RSA (Rivest Shamir Adleman) public/private key
cryptography for key exchange.RC4 (Rivest Cipher Version 4) with 128-bit
encryption for data exchange.MD5 (Message Digest Version 5) for hashing to
ensure message integrity during the exchange.After sending the "Hello" message, the server sends its certificate and
the client verifies it. The certificate that is sent to the client is served
up from the server's keystore, which is
essentially a flat file that serves as a database for the contents, such
as key pairs and their associated certificates or certificate chains.
The client that receives the certificate from the server will pursue
establishing the SSL connection only when it can authenticate the
server. This trust can be established only when the client can verify
the digital signature on the server's certificate. This is possible when
the client trusts the server or it trusts at least one of the signers in
the certificate chain provided by the server. This trust assertion is
based on the certificates present in the truststore that
the client is configured with. Essentially, truststore is a
database of certificates or certificate chains that the client can trust.
The default truststore is cacerts, which can be found in
$JAVA_HOME\jre\lib\security.
Once the server certificate verification process is complete, the
client uses the public key of the server to send a
ClientKeyExchange message to the server. This message
contains some random information that will be used for the generation of
a symmetric key. This key will be used for encrypting the
content during data exchange. The server checks to see if any other client
already uses the symmetric key; if so, it will ask the client to
regenerate another random key.
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
Random Secret: { 3, 1, 59, 151, 102, 56, 204, 6,
249, 100, 25, 171, 9, 221, 105, 97, 0, 106, 77,
10, 180, 237, 222, 165, 9, 116, 216, 10, 181, 54,
32, 244, 46, 158, 73, 18, 17, 249, 32, 254, 10,
249, 196, 196, 185, 139, 70, 17 }
Once the client and server agree on a symmetric key, the client sends
a ChangeCipherSpec message indicating that it is now ready
to communicate; this message is followed by a Finished
message. The server responds by sending its
ChangeCipherSpec message and a Finished
message:
main, WRITE: TLSv1 Change Cipher Spec, length = 1
[Raw write]: length = 6
0000: 14 03 01 00 01 01
*** Finished
The setup configuration that an application developer needs to provide
for the above client-server exchange is to specify a
keystore for the server application and a
truststore for the client application. We will go
over how to create a keystore and a truststore and once we are done with
infrastructure-related aspects, we will write RMI code and integrate it
in order to establish secure communication. The keystore and truststore
can be created using the keytool utility that is bundled
with the JDK distribution. This utility can be found under
$JAVA_HOME/bin. If the JDK's bin
directory is in the PATH, then the keytool utility can be
executed from a command window or shell.
$keytool -genkey -alias SecureServer
-keyalg RSA -keystore Server_Keystore
Enter keystore password: password
What is your first and last name?
[Unknown]: kv
What is the name of your organizational unit?
[Unknown]: IT
What is the name of your organization?
[Unknown]: ABC
What is the name of your City or Locality?
[Unknown]: KC
What is the name of your State or Province?
[Unknown]: MO
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=kv, OU=IT, O=ABC, L=KC, ST=MO, C=US correct?
[no]: y
Enter key password for <SecureServer>
(RETURN if same as keystore password):
$keytool -list -v -keystore Server_Keystore
Enter keystore password: password
Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: secureserver
Creation date: Aug 12, 2005
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=kv, OU=IT, O=ABC, L=KC, ST=MO, C=US
Issuer: CN=kv, OU=IT, O=ABC, L=KC, ST=MO, C=US
Serial number: 42fc999e
Valid from: Fri Aug 12 07:44:14 CDT 2005
until: Thu Nov 10 06:44:14 CST 2005
Certificate fingerprints:
MD5: 08:09:5D:2C:4B:28:D9:94:48:69:6D:AE:8E:
B2:43:CB
SHA1: 14:BE:5F:88:1F:8D:2D:04:93:F6:22:02:84:
C0:DD:51:4F:B0:E8:97
*******************************************
*******************************************
As it can be seen from the output of the above command that there is a
"keyEntry" which is the private key for corresponding self signed
certificate.$keytool -export -alias SecureServer -keystore
Server_Keystore -rfc -file Server.cer
Enter keystore password: password
Certificate stored in file <Server.cer>
Just to see what the certificate looks like, we'll print to the console with the following:
$cat Server.cer
This will print a byte string that starts with -----BEGIN CERTIFICATE----- and ends with -----END CERTIFICATE-----
$keytool -import -alias SecureServer -file Server.cer \
-keystore Client_Truststore
Enter keystore password: passsword
Owner: CN=kv, OU=IT, O=ABC, L=KC, ST=MO, C=US
Issuer: CN=kv, OU=IT, O=ABC, L=KC, ST=MO, C=US
Serial number: 42fc999e
Valid from: Fri Aug 12 07:44:14 CDT 2005
until: Thu Nov 10 06:44:14 CST 2005
Certificate fingerprints:
MD5: 08:09:5D:2C:4B:28:D9:94:48:69:6D:AE:8E:
B2:43:CB
SHA1: 14:BE:5F:88:1F:8D:2D:04:93:F6:22:02:84:
C0:DD:51:4F:B0:E8:97
Trust this certificate? [no]: y
Certificate was added to keystoretrustedCertEntry, which means
that a private key is not available and should not be.
keytool -list -v -keystore Client_Truststore
Enter keystore password: password
Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: secureserver
Creation date: Aug 12, 2005
Entry type: trustedCertEntry
Owner: CN=kv, OU=IT, O=ABC, L=Kansas City, ST=MO, C=US
Issuer: CN=kv, OU=IT, O=ABC, L=Kansas City, ST=MO, C=US
Serial number: 42fc999e
Valid from: Fri Aug 12 07:44:14 CDT 2005
until: Thu Nov 10 06:44:14 CST 2005
Certificate fingerprints:
MD5: 08:09:5D:2C:4B:28:D9:94:48:69:6D:AE:8E:B2:43:CB
SHA1: 14:BE:5F:88:1F:8D:2D:04:93:F6:22:02:84:C0:DD:51:4F:B0:E8:97
*******************************************
*******************************************In this particular case, we are working with a self-signed certificate instead of certificates signed by Certification Authority (CA). If there is a need to get the certificate signed by a CA then a Certificate Signing Request(CSR) needs to be generated. The generated CSR, then, should to be submitted along with other pertinent information to a Certification Authority such as VeriSign or USPS, who will then digitally sign the certificate. The aspects of creating a CSR and getting it signed by a CA is beyond the scope of this article.
View all java.net Articles.
|
|