ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Java vs. .NET Security, Part 2
Pages: 1, 2

Secure Communication

During transmission, data can be protected on three levels: hardware, platform, and application. These can be used independently, or combined for better results. In all cases, there is some kind of cryptographic protection applied to the data prior to communication, but the amount of required application code and its complexity increases, with application-level solution being the most involved. While wire-level protocols (IPSec, for instance) may be implemented at the hardware level for speed and efficiency, they are not discussed in this article in order to keep the primary focus on the platforms themselves.



At the platform level, SSL is the de facto industry standard of transport protection. Both platforms support (to some extent) the latest SSL 3.0 specification that allows mutual authentication of both client and server. Recently, TLS 1.0 specifications were released by IETF (RFC 2246) as a new standard for Internet communication security, which is supposed to gradually replace SSL.

Additionally, both platforms expose -- albeit at different levels -- implementations of the Generic Security Service API (GSSAPI) (RFC 1508, 1509) common standard, which defines a generic programming interface for different authentication and communication protocols.

Secure Communication: Platform

Windows OS implements GSSAPI in the so-called Security Support Provider Interface (SSPI) to select one of the configured providers for securing data exchange over networked connections, which is used internally by .NET itself. However, as ridiculous as it sounds, .NET applications have only SSL configuration in IIS at their disposal for protection of HTTP-based traffic, while non-IIS based applications, such as standalone Remoting (the successor to DCOM) or HTTP servers, have no means of protecting their data en route. Not surprisingly, during the first year after .NET 1.0's release, protection of Remoting communication was one of the most frequently asked questions on the web forums.

There still exists no officially supported solution for securing Remoting communication, but fortunately, its highly flexible sink architecture allowed for the development of a number of low-level solutions that can be plugged into the infrastructure and server as a substitute for platform-level protection. Microsoft also apparently realized its omission, and released a fix in the form of two assemblies in the samples namespace, Microsoft.Samples: Security.SSPI and Runtime.Remoting.Security. The former exposes a managed SSPI wrapper, and the latter uses it to implement a Remoting sink featuring symmetric encryption. Another article, which appeared at MSDN Magazine, outlined an alternative approach to Remoting security using asymmetric encryption.

The Java platform offers Java Secure Socket Extensions (JSSE) as a platform-level service for securing TCP/IP-based communication in vanilla J2SE applications, and J2EE's servlet specifications declare options for configuring SSL protection and refusing unprotected connection attempts.

Additionally, application servers from various vendors usually include some means to configure the SSL protocol for their HTTP servers. Since these are proprietary solutions, they are not going to be further pursued in this document.

JSSE, originally an extension to J2SE, was incorporated as a standard package as of version 1.4, so any Java application may count on using its services. The standard JSSE API is located in the javax.net.* packages (javax.security.cert is obsolete and should not be used). It is quite rich; readers should consult the Javadocs for the specified packages and the online documentation for the class model and operation overview.

The example below shows a simple scenario of a client/server application, which will be satisfactory in most cases. Normal sockets are replaced with SSL ones by specifying different factory implementations, which are consequently used to obtain input/output streams:

//client establishing a connection
SSLSocketFactory clientFactory = 
 (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket sslSocket = (SSLSocket)
clientFactory.createSocket(host,port);

//use as a normal socket
OutputStream out = sslSocket.getOutputStream();
InputStream in = sslSocket.getInputStream();

...

//server accepting a connection, 
//requesting mutual authentication
SSLServerSocketFactory serverFactory = 
  (SSLServerSocketFactory)
   SSLServerSocketFactory.getDefault();
SSLServerSocket ss = (SSLServerSocket)
serverFactory.createServerSocket(port);
ss.setNeedClientAuth(true);

//use as a normal socket
SSLSocket socket = ss.accept();
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();

...

A connection between two peers in JSSE is represented by a javax.net.ssl.SSLSession object. Among other things, this session contains negotiated shared secrets and information about ciphers used in the session. The master shared secret keys are not exposed through the JSSE API, and remain known only to the underlying implementation classes. Cipher information, however, is available for analysis, and the server may refuse a connection if the client does not use strong enough ciphers:

SSLSocket socket = ss.accept();
SSLSession session = socket.getSession();
String cipher = session.getCipherSuite();
if (cipher.equals("SSL_RSA_WITH_RC4_128_SHA") ||
cipher.equals("SSL_RSA_WITH_RC4_128_MD5")) {
	//sufficient strength, may continue
	...
} else {
	throw new SSLException(
            "Insufficient cipher strength!");
}

JSSE providers follow general JCE guidelines, and are pluggable into the provider-based JCA architecture. As a result, they may be configured in the java.security file, or added in code just like other security providers. Consequently, if a JCE provider, implementing the same algorithms as a JSSE one, is configured higher (i.e. it has a lower ordinal number -- see JCE Providers Configuration) in the crypto providers list than the JSSE provider, JSSE operations will use the JCE provider's implementations instead of the built-in ones. Note, however, that the JSSE cryptography algorithm implementations are private and not available for public usage. Also, as a departure from the usual provider model due to export restrictions, the default SSLSocketFactory and SSLServerSocketFactory cannot be replaced.

In JDK 1.4.2, Sun provides a reasonably good reference JSSE implementation named "SunJSSE," whose features are highlighted below. For the complete list, check the JSSE guide.

  • API and implementations of SSL 3.0 and TLS 1.0 algorithms.
  • Stream-based I/O classes: SSLSocket and SSLServerSocket.
  • One-way and mutual authentication. Certificate management is required and key and trust stores on both client and server should be set up appropriately.
  • Implementation of HTTPS. Actually, JSSE services can be applied to many application-level protocols, such as RMI, FTP, LDAP, etc.
  • Internal implementations for some cryptography algorithms.
  • Read-only implementation of PKCS#12 keystore, in addition to the default Java KeyStore (JKS).
  • Key and trust store management. For easier control, JSSE defines several system properties to control behaviors of appropriate classes from the command line.

The following properties (all starting with javax.net.ssl) may be specified on the command line or set in code: keyStore, keyStorePassword, keyStoreType, trustStore, trustStorePassword, and trustStoreType. For example:

java -Djavax.net.ssl.trustStore=AppTrustStore SecureApp

Java applications using RMI communication are pretty much limited to using JSSE for protection. Sun is working on separate specifications for secure RMI, which will include authentication, confidentiality, or integrity mechanisms, but they are not going to be available any time soon -- the JSR 76 "RMI Security for J2SE" was rejected in February 2001. Custom solutions are possible (such as subclassing SSLServerSocket), but they are non-trivial.

The J2EE specification promotes usage of SSL/TLS across all of its components by mandating support for the following ciphers:

  • TLS_RSA_WITH_RC4_128_MD5
  • SSL_RSA_WITH_RC4_128_MD5
  • TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
  • SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
  • TLS_RSA_EXPORT_WITH_RC4_40_MD5
  • SSL_RSA_EXPORT_WITH_RC4_40_MD5
  • TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
  • SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA

In most cases, cipher suites will be either SSL_RSA_WITH_RC4_128_SHA or SSL_RSA_WITH_RC4_128_MD5 (or their TLS equivalents), as they are currently the strongest commonly used SSL ciphers.

The servlet specification defines the transport-guarantee element in the deployment descriptor, which is used to require a certain level of call protection from the servlet container. Possible values are: NONE, INTEGRAL, and CONFIDENTIAL, and can be specified in the /WEB-INF/web.xml file. The names for the constraints are pretty self-descriptive, and implementation interpretation is left at the vendor's discretion. However, the servlets have an option to programmatically reject a HTTP connection if the HttpRequest.isSecure method shows that the connection is not secure. Below is an example of specifying the transport guarantee element:

<security-constraint>
  <user-data-constraint>
    <transport-guarantee>
      CONFIDENTIAL
    </transport-guarantee>
  </user-data-constraint>
</security-constraint>

EJBs do not have an option to determine connection's security settings. EJB specifications, however, require passive support for remote calls' security; i.e., if a call is made using a secure connection, EJB server also uses a secure connection for further calls. Remote EJB calls use the IIOP protocol, with support for SSL 3.0 and TLS 1.0 support mandated by EJB 2.0 and J2EE specifications.

Note: Besides IIS, .NET does not offer any standard means for communication protection at the platform level, while Java has a complete solution in this space.

Secure Communication: Application

For finer control over applied security mechanisms, an application can use an application-level, token-based protection mechanism, abstract from the underlying transmission protocol. This approach has an advantage over channel blanket encryption by being smarter and protecting only sensitive data. For instance, web services (see later in this section) use this paradigm for message protection, where only particular details of messages are signed and encrypted.

As already explained, J2SE includes GSSAPI, which may be utilized on the application level to provide token-based protection using the Kerberos V 5. GSSAPI framework, is quite a thin wrapper, delegating all requests to the underlying mechanism providers. The Java GSS mechanisms do not perform user logins themselves -- they should be done using JAAS prior to invoking GSSAPI services, and the credentials should be stored in some cache accessible to the GSS mechanism provider. Using JAAS and Kerberos tickets in GSS provides not only transport-level security protection, but also a principal delegation mechanism over the network. See "Authentication" in Part 4 for more information about JAAS and delegation.

GSS classes reside in the org.ietf.jgss package; check the online documentation for details and code examples.

Overall, Java offers a choice of platform-level (JSSE) and application-level (GSS) protection services with similar security goals: client-server authentication and protection of transmitted data. Listed below are a few criteria that can help to decide which service is more appropriate for a particular application:

  • JSSE is very easy to use from client's code -- no action besides establishing the proper socket factory is needed. GSS setup and coding are significantly more involved.
  • Java's "Single Sign-On" mechanism is based on Kerberos V5, which is supported only by GSS.
  • JSSE implementations are socket-based and typically use TCP as the underlying protocol. GSS is token-based and can use any communication channel for token transmission -- the code is responsible for establishing the channel, though.
  • GSS is capable of client credential delegation.
  • JSSE encrypts all data sent through the socket. GSS, being token-based, can encrypt tokens selectively, thus significantly lowering computational load.
  • JSSE implements TLS 1.0 and SSL 3.0 communication protocols. GSS supports only the Kerberos V5 protocol (known as "SSPI with Kerberos" on Win32), and provides implementation of IETF's generic GSS-API framework.

Web services security specifications and toolkits also look at protecting individual messages, or tokens. This area has been rapidly evolving, and has not yet been fully standardized. Because of this lack of standards, both platforms provide only partial support for it via extensions or external products. However, since the topic of web services security alone warrants a whole separate book, it is not addressed here in any significant detail. Of all competing standards in this area, only SAML and WS-Security have been so far accepted for standardization by OASIS, with the latter still undergoing committee reviews.

For web services security, Microsoft is actively promoting its Web Service Architecture (WSA, formerly GXA), and adds support for all released up-to-date specifications via its Web Services Extension (WSE) pack for .NET. WSE is currently at 1.0 release, with 2.0 coming soon -- check the MSDN documentation for updates and new releases. Notably, WSE (and .NET in general) lacks support for SAML, even though the WS-Security specification does define binding for SAML assertions as one of the supported token types. In other areas, WSE provides relatively complete support of WS-Security and a number of other specifications. Additionally, WSE's certificate classes (located in the Microsoft.Web.Services.Security.X509 package) are much more convenient to deal with than .NET's original ones. The code sample below shows how to sign a request using WSE:

// Get SOAP context from the Web service proxy
SoapContext reqCxt = 
               serviceProxy.RequestSoapContext;

// Retrieve the certificate to be used for signing
Microsoft.Web.Services.Security.X509.X509Certificate crt = ...;
// Create a X509 security token
X509SecurityToken token = 
                     new X509SecurityToken(crt);

// Sign the request by adding 
//a signature to the request
reqCxt.Security.Tokens.Add(token);
reqCxt.Security.Elements.Add(
                       new Signature(token));

// Use the signed request to call the service...
serviceProxy.Hello();

The extensible architecture of .NET's Remoting has allowed for the development of quite interesting approaches to transport security, whereas Remoting's RPC-style invocations are transmitted and protected by the means of SOAP-based web service messages. In principle, this is not very different from the Microsoft solution described earlier, but it allows applying WSA-family protection (in particular, WS-Security) to individual messages, which ensures standard-based authentication, integrity, and authorization at the message level, as opposed to the non-standard approach of blank encryption of the former solution. For explanations and code samples, read the excellent publications at the CodeProject web site, in particular ""Remoting over Internet"" and related articles.

The Java platform does not provide direct support for web services security yet. Currently, there are two web services security-related JSRs at work: JSR 155 "Web Services Security Assertions", and JSR 183 "Web Services Message Security APIs". When accepted (although they have been in review stage for over a year now), these specifications should provide assertions support and transport-level security to web services written in Java. Although not a standard part of Java platform, IBM's Emerging Technologies Toolkit v1.2 (ETTK), formerly known as Web Services Development Kit, or WSTK, adds support for the current draft of WS-Security and some other specifications from the WSA family, of which IBM is a co-author.

Note: The .NET platform stays very current with the latest developments in web services security, while their support in Java is not standardized and is limited to offerings from individual vendors.

Conclusions

In this article, cryptography and communication protection on Java and .NET platforms were reviewed. Both platforms come out pretty even in terms of cryptographic features, although Java has a more complicated solution due to the obsolete US export restrictions. The picture becomes muddier when it comes to communication protection -- while Java fares much better by providing a choice of both platform and application-level solutions, it clearly lags behind .NET when it comes to support for web services security. Here, Java developers would have to turn to independent vendors for the desired features.

The next article of this series will cover code protection and Code Access Security (CAS) on both platforms.

Denis Piliptchouk is a senior technical member of BEA's AquaLogic Enterprise Security group, participates in OASIS WSS and WS-I BSP standards committees, and regularly contributes to industry publications.


Return to ONJava.com.