Java Network Programming (3rd ed) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java Network Programming (3rd ed) [Electronic resources] - نسخه متنی

Harold, Elliotte Rusty

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








11.3 Methods of the SSLSocket Class


Besides the methods we've
already discussed and those it inherits from
java.net.Socket, the SSLSocket
class has a number of methods for configuring exactly how much and
what kind of authentication and encryption is performed. For
instance, you can choose weaker or stronger algorithms, require
clients to prove their identity, force reauthentication of both
sides, and more.


11.3.1 Choosing the Cipher Suites


Different implementations of the
JSSE support different combinations
of authentication and encryption algorithms. For instance, the
implementation Sun bundles with Java 1.4 only supports 128-bit AES
encryption, whereas IAIK's iSaSiLk (http://jce.iaik.tugraz.at/products/02_isasilk/)
supports 256-bit AES encryption. The
getSupportedCipherSuites()
method tells you which combination of algorithms is available on a
given socket:

public abstract String[] getSupportedCipherSuites( )

However, not all cipher suites that are understood are necessarily
allowed on the connection. Some may be too weak and consequently
disabled. The getEnabledCipherSuites()
method tells you which suites this socket is willing to use:

public abstract String[] getEnabledCipherSuites( )

The actual suite used is negotiated between the client and server at
connection time. It's possible that the client and
the server won't agree on any suite.
It's also possible that although a suite is enabled
on both client and server, one or the other or both
won't have the keys and certificates needed to use
the suite. In either case, the createSocket( )
method will throw an SSLException, a subclass of
IOException. You can change the suites the client
attempts to use via the setEnabledCipherSuites(
)

method:

public abstract void setEnabledCipherSuites(String[] suites)

The argument to this method should be a list of the suites you want
to use. Each name must be one of the suites listed by
getSupportedCipherSuites( ). Otherwise, an
IllegalArgumentException will be thrown.
Sun's JDK 1.4 supports these 23 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

TLS_DHE_DSS_WITH_AES_128_CBC_SHA

SSL_RSA_WITH_3DES_EDE_CBC_SHA

SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA

SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA

SSL_RSA_WITH_DES_CBC_SHA

SSL_DHE_RSA_WITH_DES_CBC_SHA

SSL_DHE_DSS_WITH_DES_CBC_SHA

SSL_RSA_EXPORT_WITH_RC4_40_MD5

SSL_RSA_EXPORT_WITH_DES40_CBC_SHA

SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA

SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA

SSL_RSA_WITH_NULL_MD5

SSL_RSA_WITH_NULL_SHA

SSL_DH_anon_WITH_RC4_128_MD5

TLS_DH_anon_WITH_AES_128_CBC_SHA

SSL_DH_anon_WITH_3DES_EDE_CBC_SHA

SSL_DH_anon_WITH_DES_CBC_SHA

SSL_DH_anon_EXPORT_WITH_RC4_40_MD5

SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA


Each name has an algorithm divided into four parts: protocol, key
exchange algorithm, encryption algorithm, and checksum. For example,
the name SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA means
Secure Sockets Layer Version 3; Diffie-Hellman method for
key agreement; no authentication; Data Encryption Standard encryption
with 40-bit keys; Cipher Block Chaining, and the Secure Hash
Algorithm checksum.

By default, the JDK 1.4 implementation enables all the encrypted
authenticated suites (the first 15 members of this list). If you want
nonauthenticated transactions or authenticated but unencrypted
transactions, you must enable those suites explicitly with the
setEnabledCipherSuites( ) method.

Besides key
lengths, there's an important difference between
DES/AES and RC4-based ciphers. DES and AES are block ciphers; that
is, they encrypt a certain number of bits at a time. DES always
encrypts 64 bits. If 64 bits aren't available, the
encoder has to pad the input with extra bits. AES can encrypt blocks
of 128, 192, or 256 bits, but still has to pad the input if it
doesn't come out to an even multiple of the block
size. This isn't a problem for file transfer
applications such as secure HTTP and FTP, where more or less all the
data is available at once. However, it's problematic
for user-centered protocols such as chat and Telnet. RC4 is a stream
cipher that can encrypt one byte at a time and is more appropriate
for protocols that may need to send a single byte at a time.

For example, let's suppose that Edgar has some
fairly powerful parallel computers at his disposal and can quickly
break any encryption that's 64 bits or less and that
Gus and Angela know this. Furthermore, they suspect that Edgar can
blackmail one of their ISPs or the phone company into letting him tap
the line, so they want to avoid anonymous connections that are
vulnerable to man-in-the-middle attacks. To be safe, Gus and Angela
decide to use at least 111-bit, authenticated encryption. It then
behooves them to enable only the strongest available algorithms. This
code fragment accomplishes that:

String[] strongSuites = {"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 
"SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA"};
socket.setEnabledCipherSuites(strongSuites);

If the other side of the connection doesn't support
strong encryption, the socket will throw an exception when they try
to read from or write to it, thus ensuring that no confidential
information is accidentally transmitted over a weak channel.


11.3.2 Event Handlers


Network communications are slow
compared to the speed of most computers. Authenticated network
communications are even slower. The necessary key generation and
setup for a secure connection can easily take several seconds.
Consequently, you may want to deal with the connection
asynchronously. JSSE uses the standard event model introduced in Java
1.1 to notify programs when the handshaking between client and server
is complete. The pattern is a familiar one. In order to get
notifications of handshake-complete events, simply implement the
HandshakeCompletedListener interface:

public interface HandshakeCompletedListener 
extends java.util.EventListener

This interface declares the handshakeCompleted( )
method:

public void handshakeCompleted(HandshakeCompletedEvent event)

This method receives as an argument a
HandshakeCompletedEvent:

public class HandshakeCompletedEvent extends java.util.EventObject

The
HandshakeCompletedEvent class provides four methods for getting
information about the event:

public SSLSession getSession( )
public String getCipherSuite( )
public X509Certificate[] getPeerCertificateChain( )
throws SSLPeerUnverifiedException
public SSLSocket getSocket( )

Particular HandshakeCompletedListener objects
register their interest in handshake-completed events from a
particular SSLSocket via its
addHandshakeCompletedListener( ) and
removeHandshakeCompletedListener( ) methods:

public abstract void addHandshakeCompletedListener(
HandshakeCompletedListener listener)
public abstract void removeHandshakeCompletedListener(
HandshakeCompletedListener listener) throws IllegalArgumentException


11.3.3 Session Management


SSL is commonly used on web
servers, and for good reason. Web connections tend to be transitory;
every page requires a separate socket. For instance, checking out of
Amazon.com on its secure server requires seven separate page loads,
more if you have to edit an address or choose gift-wrapping. Imagine
if every one of those pages took an extra 10 seconds or more to
negotiate a secure connection. Because of the high overhead involved
in handshaking between two hosts for secure communications, SSL
allows sessions to be established that extend
over multiple sockets. Different sockets within the same session use
the same set of public and private keys. If the secure connection to
Amazon.com takes seven sockets, all seven will be established within
the same session and use the same keys. Only the first socket within
that session will have to endure the overhead of key generation and
exchange.

As a programmer using JSSE, you don't need to do
anything extra to take advantage of sessions. If you open multiple
secure sockets to one host on one port within a reasonably short
period of time, JSSE will reuse the session's keys
automatically. However, in high-security applications, you may want
to disallow session-sharing between sockets or force reauthentication
of a session. In the JSSE, sessions are represented by instances of
the SSLSession interface; you can use the methods
of this interface to check the times the session was created and last
accessed, invalidate the session, and get various information about
the session:

public byte[] getId( )
public SSLSessionContext getSessionContext( )
public long getCreationTime( )
public long getLastAccessedTime( )
public void invalidate( )
public void putValue(String name, Object value)
public Object getValue(String name)
public void removeValue(String name)
public String[] getValueNames( )
public X509Certificate[] getPeerCertificateChain( )
throws SSLPeerUnverifiedException
public String getCipherSuite( )
public String getPeerHost( )

The getSession( ) method of
SSLSocket returns the Session
this socket belongs to:

public abstract SSLSession getSession( )

However, sessions are a trade-off between performance and security.
It is more secure to renegotiate the key for each and every
transaction. If you've got really spectacular
hardware and are trying to protect your systems from an equally
determined, rich, motivated, and competent adversary, you may want to
avoid sessions. To prevent a socket from creating a session that
passes false to setEnableSessionCreation( ), use:

public abstract void setEnableSessionCreation(boolean allowSessions)

The getEnableSessionCreation()
method returns true if multisocket sessions are
allowed, false if they're not:

public abstract boolean getEnableSessionCreation( )

On rare occasions, you may even want to reauthenticate a connection;
that is, throw away all the certificates and keys that have
previously been agreed to and start over with a new session. The
startHandshake( ) method does this:

public abstract void startHandshake( ) throws IOException


11.3.4 Client Mode


It's a rule of thumb
that in most secure communications, the server is required to
authenticate itself using the appropriate certificate. However, the
client is not. That is, when I buy a book from Amazon using its
secure server, it has to prove to my browser's
satisfaction that it is indeed Amazon and not Joe Random Hacker.
However, I do not have to prove to Amazon that I am Elliotte Rusty
Harold. For the most part, this is as it should be, since purchasing
and installing the trusted certificates necessary for authentication
is a fairly user-hostile experience that readers
shouldn't have to go through just to buy the latest
Nutshell handbook. However, this asymmetry can lead to credit card
fraud. To avoid problems like this, sockets can be required to
authenticate themselves. This strategy wouldn't work
for a service open to the general public. However, it might be
reasonable in certain internal, high-security applications.

The setUseClientMode() method determines
whether the socket needs to use authentication in its first
handshake. The name of the method is a little misleading. It can be
used for both client- and server-side sockets. However, when
true is passed in, it means the socket is in
client mode (whether it's on the client side or not)
and will not offer to authenticate itself. When
false is passed, it will try to authenticate
itself:

public abstract void setUseClientMode(boolean mode) 
throws IllegalArgumentException

This property can be set only once for any given socket. Attempting
to set it a second time throws an
IllegalArgumentException.

The getUseClientMode() method simply tells
you whether this socket will use authentication in its first
handshake:

public abstract boolean getUseClientMode( )

A secure socket on the server side (that is, one returned by the
accept( ) method of an
SSLServerSocket) uses the
setNeedClientAuth( )
method to require that all clients connecting to it authenticate
themselves (or not):

public abstract void setNeedClientAuth(boolean needsAuthentication) 
throws IllegalArgumentException

This method throws an IllegalArgumentException if
the socket is not on the server side.

The getNeedClientAuth()
method returns true if the socket requires
authentication from the client side, false
otherwise:

public abstract boolean getNeedClientAuth( )


/ 164