JBoss.orgCommunity Documentation
The Secure Remote Password (SRP) protocol is an implementation of a public key exchange handshake described in the Internet standards working group request for comments 2945(RFC2945). The RFC2945 abstract states:
This document describes a cryptographically strong network authentication mechanism known as the Secure Remote Password (SRP) protocol. This mechanism is suitable for negotiating secure connections using a user-supplied password, while eliminating the security problems traditionally associated with reusable passwords. This system also performs a secure key exchange in the process of authentication, allowing security layers (privacy and/or integrity protection) to be enabled during the session. Trusted key servers and certificate infrastructures are not required, and clients are not required to store or manage any long-term keys. SRP offers both security and deployment advantages over existing challenge-response techniques, making it an ideal drop-in replacement where secure password authentication is needed.
The complete RFC2945 specification can be obtained from http://www.rfc-editor.org/rfc.html. Additional information on the SRP algorithm and its history can be found at http://www-cs-students.stanford.edu/~tjw/srp/.
Algorithms like Diffie-Hellman and RSA are known as public key exchange algorithms. The concept of public key algorithms is that you have two keys, one public that is available to everyone, and one that is private and known only to you. When someone wants to send encrypted information to you, then encrypt the information using your public key. Only you are able to decrypt the information using your private key. Contrast this with the more traditional shared password based encryption schemes that require the sender and receiver to know the shared password. Public key algorithms eliminate the need to share passwords.
The JBossSX framework includes an implementation of SRP that consists of the following elements:
An implementation of the SRP handshake protocol that is independent of any particular client/server protocol
An RMI implementation of the handshake protocol as the default client/server SRP implementation
A client side JAAS LoginModule
implementation that uses the RMI implementation for use in authenticating clients in a secure fashion
A JMX MBean for managing the RMI server implementation. The MBean allows the RMI server implementation to be plugged into a JMX framework and externalizes the configuration of the verification information store. It also establishes an authentication cache that is bound into the JBoss server JNDI namespace.
A server side JAAS LoginModule
implementation that uses the authentication cache managed by the SRP JMX MBean.
Figure 19.1, “The JBossSX components of the SRP client-server framework.” describes the key components involved in the JBossSX implementation of the SRP client/server framework.
On the client side, SRP shows up as a custom JAAS LoginModule
implementation that communicates with the authentication server through an org.jboss.security.srp.SRPServerInterface
proxy. A client enables authentication using SRP by creating a login configuration entry that includes the org.jboss.security.srp.jaas.SRPLoginModule
. This module supports the following configuration options:
Constant value, set to org.jboss.security.srp.jaas.SRPPrincipal
.
JNDI name of the SRPServerInterface
object used to communicate with the SRP authentication server. If both srpServerJndiName
and srpServerRmiUrl
options are specified, srpServerJndiName
takes priority over srpServerRmiUrl
.
RMI protocol URL string for the location of the SRPServerInterface
proxy used to communicate with the SRP authentication server.
Flag that specifies whether the random component of the client public key "A" should come from the user callback. This can be used to input a strong cryptographic random number coming from a hardware token. If set to true
, the feature is activated.
Flag that specifies whether a string will be sent to the server as an additional challenge for the server to validate. If the client session supports an encryption cipher then a temporary cipher will be created using the session private key and the challenge object sent as a javax.crypto.SealedObject
. If set to true
, the feature is activated.
Flag that specifies whether a given client may have multiple SRP login sessions active.
If set to true
, the feature is activated.
Any other passed options that do not match one of the previously named options are treated as a JNDI property to use for the environment passed to the InitialContext
constructor. This is useful if the SRP server interface is not available from the default InitialContext
.
The SRPLoginModule
and the standard ClientLoginModule
must be configured to allow SRP authentication credentials to be used for access validation to security Java EE components. An example login configuration is described in Example 19.1, “Login Configuration Entry”.
Example 19.1. Login Configuration Entry
srp { org.jboss.security.srp.jaas.SRPLoginModule required srpServerJndiName="SRPServerInterface" ; org.jboss.security.ClientLoginModule required password-stacking="useFirstPass" ; };
On the JBoss server side, there are two MBeans that manage the objects that collectively make up the SRP server. The primary service is the org.jboss.security.srp.SRPService
MBean. The other MBean isorg.jboss.security.srp.SRPVerifierStoreService
.
org.jboss.security.srp.SRPService
is responsible for exposing an RMI accessible version of the SRPServerInterface as well as updating the SRP authentication session cache.
The configurable SRPService MBean attributes include the following:
Specifies the name from which the SRPServerInterface proxy should be available. This is the location where the SRPService
binds the serializable dynamic proxy to the SRPServerInterface
. The default value is srp/SRPServerInterface
.
Specifies the name of the SRPVerifierSource
implementation the SRPService
must use. The source JNDI name defaults to srp/DefaultVerifierSource
.
Specifies the name under which the org.jboss.util.CachePolicy
authentication implementation used for caching authentication information is bound. The SRP session cache is made available for use through this binding. The authentication JNDI cache defaults to srp/AuthenticationCache
.
RMI port for the SRPRemoteServerInterface
. The default value is 10099.
Optional custom java.rmi.server.RMIClientSocketFactory
implementation class name used during the export of the SRPServerInterface
. The default value is RMIClientSocketFactory
.
Optional custom java.rmi.server.RMIServerSocketFactory
implementation class name used during the export of the SRPServerInterface
. The default value is RMIServerSocketFactory
.
Cache policy timeout (in seconds). The default value is 1800 (30 minutes).
Specifies the timed cache policy resolution (in seconds). This controls the interval between checks for timeouts. The default value is 60 (1 minute).
Set if the client must supply an auxiliary challenge as part of the verify phase. This gives control over whether the SRPLoginModule
configuration used by the client must have the useAuxChallenge
option enabled.
Specifies whether a successful user authentication for an existing session should overwrite the current session. This controls the behavior of the server SRP session cache when clients have not enabled the multiple session per user mode. If set to false
, the second user authentication attempt will succeed, however the resulting SRP session will not overwrite the previous SRP session state.
The default value is false
.
Specifies the location of the SRP password information store implementation that must be provided and made available through JNDI.
org.jboss.security.srp.SRPVerifierStoreService
is an example MBean service that binds an implementation of the SRPVerifierStore
interface that uses a file of serialized objects as the persistent store. Although not realistic for a production environment, it does allow for testing of the SRP protocol and provides an example of the requirements for an SRPVerifierStore
service.
The configurable SRPVerifierStoreService
MBean attributes include the following:
JNDI name from which the SRPVerifierStore
implementation should be available. If not specified it defaults to srp/DefaultVerifierSource
.
Location of the user password verifier serialized object store file. This can be either a URL or a resource name to be found in the classpath. If not specified it defaults to SRPVerifierStore.ser
.
The SRPVerifierStoreService
MBean also supports addUser
and delUser
operations for addition and deletion of users. The signatures are:
public void addUser(String username, String password) throws IOException;
public void delUser(String username) throws IOException;
An example configuration of these services is presented in Example 19.2, “The SRPVerifierStore interface”.
The appeal of the SRP algorithm is that is allows for mutual authentication of client and server using simple text passwords without a secure communication channel.
Additional information on the SRP algorithm and its history can be found at http://srp.stanford.edu/.
There are six steps that are performed to complete authentication:
The client side SRPLoginModule
retrieves from the naming service the SRPServerInterface instance for the remote authentication server.
The client side SRPLoginModule
next requests the SRP parameters associated with the username attempting the login. There are a number of parameters involved in the SRP algorithm that must be chosen when the user password is first transformed into the verifier form used by the SRP algorithm. Rather than hard-coding the parameters (which could be done with minimal security risk), the JBossSX implementation allows a user to retrieve this information as part of the exchange protocol. The getSRPParameters(username)
call retrieves the SRP parameters for the given username.
The client side SRPLoginModule
begins an SRP session by creating an SRPClientSession
object using the login username, clear-text password, and SRP parameters obtained from step 2. The client then creates a random number A that will be used to build the private SRP session key. The client then initializes the server side of the SRP session by invoking the SRPServerInterface.init
method and passes in the username and client generated random number A
. The server returns its own random number B
. This step corresponds to the exchange of public keys.
The client side SRPLoginModule
obtains the private SRP session key that has been generated as a result of the previous messages exchanges. This is saved as a private credential in the login Subject
. The server challenge response M2
from step 4 is verified by invoking the SRPClientSession.verify
method. If this succeeds, mutual authentication of the client to server, and server to client have been completed. The client side SRPLoginModule
next creates a challenge M1
to the server by invoking SRPClientSession.response
method passing the server random number B
as an argument. This challenge is sent to the server via the SRPServerInterface.verify
method and server's response is saved as M2
. This step corresponds to an exchange of challenges. At this point the server has verified that the user is who they say they are.
The client side SRPLoginModule
saves the login username and M1
challenge into the LoginModule
sharedState map. This is used as the Principal name and credentials by the standard JBoss ClientLoginModule
. The M1
challenge is used in place of the password as proof of identity on any method invocations on Java EE components. The M1
challenge is a cryptographically strong hash associated with the SRP session. Its interception via a third partly cannot be used to obtain the user's password.
At the end of this authentication protocol, the SRPServerSession has been placed into the SRPService authentication cache for subsequent use by the SRPCacheLoginModule
.
Although SRP has many interesting properties, it is still an evolving component in the JBossSX framework and has some limitations of which you should be aware. Issues of note include the following:
Where authentication is performed, the way in which JBoss detaches the method transport protocol from the component container could allow a user to snoop the SRP M1
challenge and effectively use the challenge to make requests as the associated username. Custom interceptors can be used to prevent the issue, by encrypting the challenge using the SRP session key.
The SRPService maintains a cache of SRP sessions that time out after a configurable period. Once they time out, any subsequent Java EE component access will fail because there is currently no mechanism for transparently renegotiating the SRP authentication credentials. You must either set the authentication cache timeout quite high, or handle re-authentication in your code on failure.
The SRPService supports timeout durations up to 2,147,483,647 seconds, or approximately 68 years.
There can only be one SRP session for a given username by default. The session is classed as stateful, because the negotiated SRP session produces a private session key that can be used for encryption and decryption between the client and server. JBoss supports multiple SRP sessions per user, however it is not possible to encrypt data with one session key, and decrypt it with another.
To use end-to-end SRP authentication for Java EE component calls, you must configure the security domain under which the components are secured to use the org.jboss.security.srp.jaas.SRPCacheLoginModule
. The SRPCacheLoginModule
has a single configuration option named cacheJndiName
that sets the JNDI location of the SRP authentication CachePolicy
instance. This must correspond to the AuthenticationCacheJndiName
attribute value of the SRPService
MBean.
The SRPCacheLoginModule
authenticates user credentials by obtaining the client challenge from the SRPServerSession
object in the authentication cache and comparing this to the challenge passed as the user credentials. Figure 19.2, “SRPCacheLoginModule with SRP Session Cache” illustrates the operation of the SRPCacheLoginModule.login method implementation.
You must create a MBean service that provides an implementation of the SRPVerifierStore
interface that integrates with your existing security information stores. The SRPVerifierStore
interface is shown in Example 19.2, “The SRPVerifierStore interface”.
The default implementation of the SRPVerifierStore
interface is not recommended for a production security environment because it requires all password hash information to be available as a file of serialized objects.
Example 19.2. The SRPVerifierStore interface
package org.jboss.security.srp;
import java.io.IOException;
import java.io.Serializable;
import java.security.KeyException;
public interface SRPVerifierStore
{
public static class VerifierInfo implements Serializable
{
public String username;
public byte[] salt;
public byte[] g;
public byte[] N;
}
public VerifierInfo getUserVerifier(String username)
throws KeyException, IOException;
public void setUserVerifier(String username, VerifierInfo info)
throws IOException;
public void verifyUserChallenge(String username, Object auxChallenge)
throws SecurityException;
}
The primary function of a SRPVerifierStore
implementation is to provide access to the SRPVerifierStore.VerifierInfo
object for a given username. The getUserVerifier(String)
method is called by the SRPService
at that start of a user SRP session to obtain the parameters needed by the SRP algorithm. The elements of the VerifierInfo
objects are:
The user's name or id used to login.
One-way hash of the password or PIN the user enters as proof of identity. The org.jboss.security.Util
class has a calculateVerifier
method that performs that password hashing algorithm. The output password takes the form H(salt | H(username | ':' | password))
, where H
is the SHA secure hash function as defined by RFC2945. The username is converted from a string to a byte[]
using UTF-8 encoding.
Random number used to increase the difficulty of a brute force dictionary attack on the verifier password database in the event that the database is compromised. The value should be generated from a cryptographically strong random number algorithm when the user's existing clear-text password is hashed.
SRP algorithm primitive generator. This can be a well known fixed parameter rather than a per-user setting. The org.jboss.security.srp.SRPConf
utility class provides several settings for g
, including a suitable default obtained via SRPConf.getDefaultParams().g()
.
SRP algorithm safe-prime modulus. This can be a well known fixed parameter rather than a per-user setting. The org.jboss.security.srp.SRPConf
utility class provides several settings for N
including a good default which can obtained via SRPConf.getDefaultParams().N()
.
Procedure 19.1. Integrate Existing Password Store
Read this procedure to understand the steps involved to integrate your existing password store.
Create Hashed Password Information Store
If your passwords are already stored in an irreversible hashed form, then this can only be done on a per-user basis (for example, as part of an upgrade procedure).
You can implement setUserVerifier(String, VerifierInfo)
as a noOp
method, or a method that throws an exception stating that the store is read-only.
Create SRPVerifierStore Interface
You must create a custom SRPVerifierStore
interface implementation that understands how to obtain the VerifierInfo
from the store you created.
The verifyUserChallenge(String, Object)
can be used to integrate existing hardware token based schemes like SafeWord or Radius into the SRP algorithm. This interface method is called only when the client SRPLoginModule
configuration specifies the hasAuxChallenge
option.
Create JNDI MBean
You must create a MBean that exposes the SRPVerifierStore
interface available to JNDI, and exposes any configurable parameters required.
The default org.jboss.security.srp.SRPVerifierStoreService
will allow you to implement this, however you can also implement the MBean using a Java properties file implementation of SRPVerifierStore
(refer to Section 19.3, “Secure Remote Password Example”).
The example presented in this section demonstrates client side authentication of the user via SRP as well as subsequent secured access to a simple EJB using the SRP session challenge as the user credential. The test code deploys an EJB JAR that includes a SAR for the configuration of the server side login module configuration and SRP services.
The server side login module configuration is dynamically installed using the SecurityConfig
MBean. A custom implementation of the SRPVerifierStore
interface is also used in the example. The interface uses an in-memory store that is seeded from a Java properties file, rather than a serialized object store as used by the SRPVerifierStoreService
.
This custom service is org.jboss.book.security.ex3.service.PropertiesVerifierStore
. The following shows the contents of the JAR that contains the example EJB and SRP services.
[examples]$ jar tf output/security/security-ex3.jar META-INF/MANIFEST.MF META-INF/ejb-jar.xml META-INF/jboss.xml org/jboss/book/security/ex3/Echo.class org/jboss/book/security/ex3/EchoBean.class org/jboss/book/security/ex3/EchoHome.class roles.properties users.properties security-ex3.sar
The key SRP related items in this example are the SRP MBean services configuration, and the SRP login module configurations. The jboss-service.xml
descriptor of the security-ex3.sar
is described in Example 19.3, “The security-ex3.sar jboss-service.xml Descriptor”.
The example client side and server side login module configurations are described in Example 19.4, “The client side standard JAAS configuration” and Example 19.5, “The server side XMLLoginConfig configuration” give .
Example 19.3. The security-ex3.sar jboss-service.xml Descriptor
<server>
<!-- The custom JAAS login configuration that installs
a Configuration capable of dynamically updating the
config settings -->
<mbean code="org.jboss.book.security.service.SecurityConfig"
name="jboss.docs.security:service=LoginConfig-EX3">
<attribute name="AuthConfig">META-INF/login-config.xml</attribute>
<attribute name="SecurityConfigName">jboss.security:name=SecurityConfig</attribute>
</mbean>
<!-- The SRP service that provides the SRP RMI server and server side
authentication cache -->
<mbean code="org.jboss.security.srp.SRPService"
name="jboss.docs.security:service=SRPService">
<attribute name="VerifierSourceJndiName">srp-test/security-ex3</attribute>
<attribute name="JndiName">srp-test/SRPServerInterface</attribute>
<attribute name="AuthenticationCacheJndiName">srp-test/AuthenticationCache</attribute>
<attribute name="ServerPort">0</attribute>
<depends>jboss.docs.security:service=PropertiesVerifierStore</depends>
</mbean>
<!-- The SRP store handler service that provides the user password verifier
information -->
<mbean code="org.jboss.security.ex3.service.PropertiesVerifierStore"
name="jboss.docs.security:service=PropertiesVerifierStore">
<attribute name="JndiName">srp-test/security-ex3</attribute>
</mbean>
</server>
The example services are the ServiceConfig
and the PropertiesVerifierStore
and SRPService
MBeans. Note that the JndiName
attribute of the PropertiesVerifierStore
is equal to the VerifierSourceJndiName
attribute of the SRPService
, and that the SRPService
depends on the PropertiesVerifierStore
. This is required because the SRPService
needs an implementation of the SRPVerifierStore
interface for accessing user password verification information.
Example 19.4. The client side standard JAAS configuration
srp { org.jboss.security.srp.jaas.SRPLoginModule required srpServerJndiName="srp-test/SRPServerInterface" ; org.jboss.security.ClientLoginModule required password-stacking="useFirstPass" ; };
The client side login module configuration makes use of the SRPLoginModule
with a srpServerJndiName
option value that corresponds to the JBoss server component SRPService
JndiName attribute value(srp-test/SRPServerInterface
). The ClientLoginModule
must also be configured with the password-stacking="useFirstPass"
value to propagate the user authentication credentials generated by the SRPLoginModule
to the EJB invocation layer.
Example 19.5. The server side XMLLoginConfig configuration
<application-policy name="security-ex3">
<authentication>
<login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule"
flag = "required">
<module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag = "required">
<module-option name="password-stacking">useFirstPass</module-option>
</login-module>
</authentication>
</application-policy>
There are two issues to note about the server side login module configuration:
The cacheJndiName=srp-test/AuthenticationCache
configuration option tells the SRPCacheLoginModule
the location of the CachePolicy
that contains the SRPServerSession
for users who have authenticated against the SRPService
. This value corresponds to the SRPService
AuthenticationCacheJndiName
attribute value.
The configuration includes a UsersRolesLoginModule
with the password-stacking=useFirstPass
configuration option. You must use a second login module with the SRPCacheLoginModule
because SRP is only an authentication technology. To set the principal's roles that in turn determine the associated permissions, a second login module must be configured to accept the authentication credentials validated by the SRPCacheLoginModule
.
The UsersRolesLoginModule
is augmenting the SRP authentication with properties file based authorization. The user's roles are obtained from the roles.properties
file included in the EJB JAR.
Run the example 3 client by executing the following command from the book examples directory:
[examples]$ ant -Dchap=security -Dex=3 run-example ... run-example3: [echo] Waiting for 5 seconds for deploy... [java] Logging in using the 'srp' configuration [java] Created Echo [java] Echo.echo()#1 = This is call 1 [java] Echo.echo()#2 = This is call 2
In the examples/logs
directory, the ex3-trace.log
file contains a detailed trace of the client side of the SRP algorithm. The traces show step-by-step the construction of the public keys, challenges, session key and verification.
Observe that the client takes a long time to run, relative to the other simple examples. The reason for this is the construction of the client's public key. This involves the creation of a cryptographically strong random number, and this process takes longer when it first executes. Subsequent authentication attempts within the same VM are much faster.
Note that Echo.echo()#2
fails with an authentication exception. The client code sleeps for 15 seconds after making the first call to demonstrate the behavior of the SRPService
cache expiration. The SRPService
cache policy timeout has been set to 10 seconds to force this issue. As discussed in Section 19.3, “Secure Remote Password Example” you must set the cache timeout correctly, or handle re-authentication on failure.