public abstract class PSKManager
extends java.lang.Object
When client and server agree on a psk cipher suite, the client has to tell
the server which pre-shared key
(psk) shall be used by
sending the psk identity within the ClientKeyExchange message. If the
server has a pre-shared key for the received identity the handshake can continue,
otherwise the handshake will fail. Before receiving the psk identity in the
ClientKeyExchange message, the server may use the ServerKeyExchange message
to send a psk identity hint to help the client to select a proper
pre-shared key. However, the TLS-PSK specification recommends that an identity
hint should not be sent
by the server and that it must be ignored
by the client (except for a special profile makes some other recommendation).
iSaSiLk wraps pre-shared keys into PSKCredentials
.
Each PSKCredential binds a pre-shared key to a psk identity. Optionally
a PSKCredential may also contain a psk identity hint
for the pre-shared key and identification information
of the peer to which to authenticate with the
pre-shared key of the credential.
The PSKManager
is responsible for maintaining PSKCredentials
to provide the right pre-shared key when going into a TLS connection with some
particular peer. On the server side, the PSKManager searches
for the psk by means of the psk identity received from the client. On the client
side, the PSKManager needs to know the remote peer id to search
for the right pre-shared key. You may
write and plug-in
your own PSKManager (or set it as default
PSKManager); however, in general you may not take care about PSKManager details at all
and only use the SSLContext
addPSKCredential
, setPSKCredential
methods to add/set PSKCredentials for being used for
psk cipher suite based TLS authentication. To, for instance, tell iSaSiLk to use
a pre-shared key with identity "pskclient.iaik.tugraz.at" for communicating with a server
named "pskserver.iaik.tugraz.at" you may create and add a PSKCredential in the
following way:
// psk identity String identity = "pskclient.iaik.tugraz.at"; // server name (remote peer id) String serverName = "pskserver.iaik.tugraz.at"; // the pre-shared key PreSharedKey psk = ...; // create PSKCredential PSKCredential pskCredential = new PSKCredential(identity, psk); // set remote peer id pskCredential.setRemotePeerId(serverName); // create client context SSLClientContext context = new SSLClientContext(); // add PSKCredential context.addPSKCredential(pskCredential); // enable PSK cipher suites CipherSuiteList suites = new CipherSuiteList(); suites.add(CipherSuite.CS_ALL_PSK); context.setEnabledCipherSuiteList(suites); context.updateCipherSuites(); ...When calling method
addPSKCredential
iSaSiLk forwards the given PSKCredential to the
internal PSKManager. When then connecting to the server with the remote
peer id specified in the credential just added, the PSKManager returns
this credential and the client can use it for authenticating the TLS session
with this server. Note, that you can disable the PSKManager at all by using
method setPSKCredential
for specifying an exclusive PSKCredential to be used only with some specific
SSLContext
. This may be suitable on the
client side: since you already know the server when creating the SSLClientContext
you also will know the pre-shared key to be used for establishing a TLS-PSK session
with this server. Thus you may not neet a PSKManager and may explicitly set the
corresponding PSKCredential to be used with this specific SSLClientContext.
However, be careful to use setPSKCredential
on the server side.
In this case your server will only have one single pre-shared key to be used with any
client that requests a PSK based TLS communication.
On the server side a remote peer id for a PSKCredential is only required
when the server wants to send
a psk identity hint to the client. However, usage of psk identity hints
is not recommended by the TLS-PSK specification.
In the sample above we have enabled all psk based cipher suites by calling
suites.add(CipherSuite.CS_ALL_PSK);
. However, you also can
enable one specific cipher suite only (e.g. CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA
)
or any of the three defined sets of psk based cipher suites:
Cipher suites
that use symmetric key operations for
authentication only:
TLS_PSK_WITH_RC4_128_SHA, TLS_PSK_WITH_3DES_EDE_CBC_SHA, TLS_PSK_WITH_AES_128_CBC_SHA, TLS_PSK_WITH_AES_256_CBC_SHA
Cipher suites
that use a Diffie-Hellman key exchange
authenticated with a pre-shared key:
TLS_DHE_PSK_WITH_RC4_128_SHA, TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, TLS_DHE_PSK_WITH_AES_128_CBC_SHA, TLS_DHE_PSK_WITH_AES_256_CBC_SHA
Cipher suites
Cipher suites that use a RSA public key authentication
of the server and pre-shared key authentication of the client:
TLS_RSA_PSK_WITH_RC4_128_SHA, TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, TLS_RSA_PSK_WITH_AES_128_CBC_SHA, TLS_RSA_PSK_WITH_AES_256_CBC_SHA
SSLContext
method addPSKCredential
,
the credential is forwarded to the internal PSKManager. By default iSaSiLk uses the
system-wide DefaultPSKManager
, i.e. one PSKManager is used
for maintaining the PSKCredentials for all SSLContext objects that may be created
during the application lifetime. If you want to use a separate PSKManager
for each SSLContext you may configure it with the PSKCredentials to be used and set
it for a SSLContext by calling method sslContextsetPSKManager
, e.g. (when using the DefaultPSKManager
):
// create PSKManager PSKManager manager = new DefaultPSKManager(); // add PSKCredential(s) as required PSKCredential credential = ...; manager.addPSKCredential(credential); ... // set the PSKManager for some SSLContext SSLContext context = ...; context.setPSKManager(manager);
Modifier | Constructor and Description |
---|---|
protected |
PSKManager()
Constructor to be used by subclasses.
|
Modifier and Type | Method and Description |
---|---|
abstract void |
addPSKCredential(PSKCredential pskCredential)
Adds the given PSKCredential.
|
abstract java.util.Enumeration |
getAll()
Gets all PSKCredentials maintained by this PSKManager.
|
static PSKManager |
getDefault()
Gets the current PSKManager.
|
PSKCredential |
getPSKCredential(byte[] identity,
SSLTransport transport)
Searches the PSKManager for a PSKCredential.
|
abstract PSKCredential |
getPSKCredential(java.lang.String identity,
SSLTransport transport)
Searches the PSKManager for a PSKCredential.
|
abstract void |
removeAll()
Removes all PSKCredentials from this PSKManager.
|
PSKCredential |
removePSKCredential(byte[] identity)
Removes the PSKCredential with the given identity.
|
abstract PSKCredential |
removePSKCredential(PSKCredential pskCredential)
Removes the given PSKCredential from this PSKManager.
|
abstract PSKCredential |
removePSKCredential(java.lang.String identity)
Removes the PSKCredential with the given identity.
|
abstract PSKCredential |
removePSKCredentialWithRemotePeerId(java.lang.Object remotePeerId)
Removes the PSKCredential associated with the given remote peer id.
|
static void |
setDefault(PSKManager manager)
Sets the PSKManager.
|
abstract int |
size()
Gets the number of PSKCredentials maintained by this
PSKManager.
|
public static PSKManager getDefault()
DefaultPSKManager
. An application may plug-in
its own PSKManager implementation.null
if PSK management is disabledpublic static void setDefault(PSKManager manager)
public abstract void addPSKCredential(PSKCredential pskCredential)
pskCredential
- the PSKCredential to be addedpublic abstract PSKCredential removePSKCredential(java.lang.String identity)
identity
- the identity of the PSKCredential to be removednull
if
no PSKCredential with the given identity is includedpublic PSKCredential removePSKCredential(byte[] identity) throws java.io.UnsupportedEncodingException
identity
- the identity of the PSKCredential to be removednull
if
no PSKCredential with the given identity is includedjava.io.UnsupportedEncodingException
- if the given identity cannot
be UTF-8 decoded to give the identity String keypublic abstract PSKCredential removePSKCredentialWithRemotePeerId(java.lang.Object remotePeerId)
remotePeerId
- the remote peer id associated with the PSKCredential to be removednull
if
no PSKCredential for the given remote peer id is includedpublic abstract PSKCredential removePSKCredential(PSKCredential pskCredential)
pskCredential
- the PSKCredential to be removednull
if
no such PSKCredential is includedpublic abstract void removeAll()
public abstract java.util.Enumeration getAll()
public abstract int size()
public abstract PSKCredential getPSKCredential(java.lang.String identity, SSLTransport transport) throws SSLException
This method does the same as method getPSKCredential(byte[], SSLTransport)
except for that the psk identity
is given as String instead of a byte array
identity
- the identity String, if not null
identifying
the PSK for which to searchtransport
- the SSLTransport to maybe used for getting information
about the remote peer (if identity
is
null
or if required by the psk management
implementation)null
if no such PSKCredential is includedSSLException
- if an error occurs when trying to get the requested
PSKCredentialpublic PSKCredential getPSKCredential(byte[] identity, SSLTransport transport) throws SSLException
This method maybe called by iSaSiLk in two different situations, depending
on if the identity
argument is null
or
not. If not null
the PSKManager is searched for a PSKCredential
with the specific psk identity (see 1. below). If null
the PSKManager is searched based on identification information provided by
the second (SSLTransport
) argument (see 2. below).
identity
argument is not null
this method is called by iSaSiLk to search for a pre-shared key for
the given identity. When called on the server side, the given identity
represents the psk identity sent by the client within the ClientKeyExchange message.
When called on the client side, the given identity represents the
psk identity hint that may have been sent by the server within the
ServerKeyExchange message. Note that the TLS-PSK specification
(RFC 4279) does NOT recommend to use a psk identity hint. Unless not explicitly
required by the application environment, the server SHOULD NOT send
a psk identity hint,
and the client MUST ignore
a psk identity hint if sent by the server.
default
PSKManager implementation requires that each
identity is unique for the whole application environment. Thus, if the identity
argument is not null
the second argument (SSLTransport
) of
this method is not used by the DefaultPSKManager except for on the client side when
having received a psk identity hint but not found a proper PSKCredential. In this case
the DefaultPSKManager looks if he has a PSKCredential with the peer id of the server
(got from the SSLTransport
argument).
identity
argument is null
this method is called by iSaSiLk to search for a pre-shared key based
on peer information provided by the given SSLTransport object.
The default
PSKManager implementation asks the given
SSLTransport for peer identification information by calling the following methods
(in that order):
transport.getRemotePeerName()
transport.getRemoteIndetAddress()
.getHostAddress()
transport.getRemotePeerId()
If you are, for instance, on the client side and want to go into a psk based TLS session with a server "pskserver.iaik.tugraz.at" with ip address "129.27.142.47" listening on port 4433, the SSL(Socket)Transport methods above will return the following values (in that order):
pskserver.iaik.tugraz.at
129.27.142.47
129.27.142.47:4433
Thus, when registering
a
PSKCredential to be used for a TLS communication with the "pskserver.iaik.tugraz.at"
server, it must have one of the three identification information values
from above as remote peer id, e.g.:
// the psk identity String identity = ...; // the pre-shared key PreSharedKey psk = ...; // create PSKCredential PSKCredential pskCredential = new PSKCredential(identity, psk); // set remote peer id int serverPort = 4433; String serverName = "pskserver.iaik.tugraz.at"; pskCredential.setRemotePeerId(serverName); // create SSLClientContext and add the credential SSLClientContext context = new SSLClientContext(); // calling this method forwards the PSKCredential to the internal PSKManager context.addPSKCredential(pskCredential);When now connecting to server "pskserver.iaik.tugraz.at", iSaSiLk asks the PSK manager for a PSKCredential with remote peer id "pskserver.iaik.tugraz.at" and the connection can succeed if both parties support the negotiated cipher suite and have a corresponding pre-shared key:
// enable PSK cipher suites CipherSuiteList suites = new CipherSuiteList(); suites.add(CipherSuite.CS_ALL_PSK); SSLSocket socket = new SSLSocket(serverName, serverPort, context); // start handshake socket.startHandshake(); // psk identity String pskIdentity = socket.getPSKIdentity(); if (pskIdentity != null) { System.out.println("PSK Identity: " + pskIdentity); } // send GET-request System.out.println("Sending HTTPS request to " + serverName); PrintWriter writer = Utils.getASCIIWriter(socket.getOutputStream()); BufferedReader reader = Utils.getASCIIReader(socket.getInputStream()); writer.println("GET / HTTP/1.0"); writer.println(); writer.flush(); // read response while( true ) { String line = reader.readLine(); if( line == null ) { break; } System.out.print(":"); System.out.println(line); } socket.close();Note, that if the psk identity already represents any of the remote peer ids, it may be not necessary to explicitly set it as remote peer id for the psk credential (the
DefaultPSKManager
implementation looks for the id in this case, too), e.g.:
String serverName = "pskserver.iaik.tugraz.at"; // the psk identity String identity = serverName; // the pre-shared key PreSharedKey psk = ...; // create PSKCredential PSKCredential pskCredential = new PSKCredential(identity, psk);In similar way, if the remote peer id is equal to the psk identity hint, it may be sufficient to only set the psk identity hint.
On the server side searching for a PSKCredential based on peer id is only
required if the server is configured to send a psk identity hint
. However, sending a psk identity hint is not recommended by the
TLS-PSK
specification (see RFC 4279).
identity
- the identity, if not null
identifying the PSK
for which to searchtransport
- the SSLTransport to maybe used for getting information
about the remote peer (if identity
is
null
or if required by the psk management
implementation)null
if no such PSKCredential is includedSSLException
- if an error occurs when trying to get the requested
PSKCredential (e.g. if the given identity cannot
be UTF-8 decoded to give the identity String key)