The Source for Java Technology Collaboration
User: Password:



   

The New RMI The New RMI

by Krishnan Viswanath
10/06/2005

Contents
RMI Security
   Security Overview
   Securing RMI
RMI as Service
Stubless RMI
Conclusion
Resources

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.

RMI Security

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.

Security Overview

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:

  • Use RSA (Rivest Shamir Adleman) public/private key cryptography for key exchange.
  • Use RC4 (Rivest Cipher Version 4) with 128-bit encryption for data exchange.
  • Use 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.

  • First, we will generate a keystore that has a key pair (public and private key) along with a self-signed certificate. This is accomplished by executing the following command, which will create a file called Server_Keystore. The key algorithm is RSA, and the keysize is 1024 bits.
    $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):
            
  • Next, we will examine the contents of the generated Server Keystore, which is accomplished by the following command.
    $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.

  • We are done creating a key entry for the server, so we will shift our focus to the client side. The next step is to create a self-signed certificate and this is accomplished by executing the following commands.
    $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-----


  • Now that we have created a self-signed certificate, the next logical step is to import this certificate into a truststore, which then can be used by the client. This is accomplished by the following command.
    $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 keystore
  • To verify the contents of the truststore that we created, we issue the following command. As can be seen from the output, the contents of the truststore contain a trustedCertEntry, 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.

Pages: 1, 2, 3

Next Page » 

View all java.net Articles.

 Feed java.net RSS Feeds