Secure Ajax: SRP Hermetic
By Antonio Caciuc, Ovidiu Gheorghies
(c) Copyright 2009 Galini Associates Ltd., Jean-Marie Carrara

SRP-Hermetic provides secure user authentication, communication integrity and communication privacy to AJAX applications. Its goal is to offer an efficient, scalable and customizable secure channel as an alternative to HTTPS. The source code is released under the MIT License.
It encapsulates an implementation of Stanford’s Secure Remote Password protocol, a pseudo-random number generator, symmetric encryption, message authentication and cryptographic hash functions into an easy to use API. A JavaScript client and a PHP server back-end are currently available.
How secure is SRP-Hermetic?
A secure conversation over a network requires 3 components:
- authentication – the parties involved need to prove their identity to each other
- confidentiality – the messages exchanged in a conversation must be unreadable to anyone except the participants
- integrity and authenticity – the messages can not be created or modified by attackers without the recipient’s knowledge
Assuming the user trusts the client code, the entire conversation (user session) should be invulnerable to active or passive network attacks, even when using low entropy passwords.
Once the SRP authentication protocol is completed successfully, a virtual secure channel can be established between the client and the server. SRP-Hermetic gives the developer the option to select between two security modes:
- Signing mode, in which messages are sent in plain text, but are signed (currently using HMAC) – this mode provides integrity and authentication
- Encryption mode, in which messages are fully encrypted (currently using AES CTR), and then signed – this mode also provides confidentiality
The keys for signing and encrypting the messages are derived from the key obtained after the completion of the SRP authentication protocol.
How do I use SRP-Hermetic in my web application?
Your .html file needs to include the Hermetic JavaScript code:
<script type="text/javascript" src="hermetic/js/hermetic-all.js"></script>
Then, in a <script> section of the page, declare and start the SRP authentication, using the hQuery singleton object (a shortcut for “hermetic query”). Here, authSuccess and authFailure are callback functions invoked upon authentication success and failure, respectively.
hQuery.setup({authUrl: "hermetic/php/auth.php", authSuccess: authSuccess, authFailure: authFailure});
hQuery.authenticate(username, password);
function authSuccess() {
hQuery.send(urlService, requestData, function (responseData, responseStatus) {
if (responseData) {
console.log(responseData.firstName, " ", responseData.lastName);
} else {
console.log("error: ", responseStatus.reason);
}
});
}
In the example above, once the authentication is completed successfully, a secure Ajax call is made to the server. By default, both the request and the reply from the server are encrypted. This way application logic works transparently with the exchanged data, as if a regular Ajax API from Prototype or jQuery is used.
The responseStatus is set to the string "success" unless an error occurs, in which case an object detailing the cause of the problem (http error, message integrity verification failure, message format error) is returned. In addition, in case of an error, the responseData parameter is set to null.
Let us look now at the matching code on the server side. The PHP code needs to include the hermetic.php file, then simply instantiate the Hermetic class and use it to unpack the request and pack the response:
require_once("hermetic/php/include/hermetic.php");
$hermetic = new Hermetic();
$request = $hermetic->unpack( $_POST );
if ( $request ) {
$response = process( $request );
echo $hermetic->pack( $response );
} else {
handleError();
}
The process() function performs your business logic, and returns the $response object, which is packed by the SRP Hermetic library and sent back to the client.
That’s it, we have established an encrypted end-to-end communication channel between the browser application and the server. It is possible to further customize this channel to use message signing instead of full encryption, and more on this is presented in the section SRP-Hermetic customization.
But first, have a look at the next section to see what needs to be installed on the server side to make it work.
Sample application setup
Download the source code archive srp-hermetic.tgz and untar. Just run these commands:
wget http://www.denksoft.com/public/srp-hermetic.tgz
tar -xzvf srp-hermetic.tgz
cd srp-hermetic
SRP-Hermetic comes with a demo application that creates and edits users in a simple fashion. You can use its code as a starting point for your application.
On the server side a web server capable of serving php 5.2 is required, such as apache2 with mod_php. A database server (we use PostgreSQL), is needed to store the user names and password, and a cache server (Memcache in our case) is used.
In the Fedora world, these are installed with yum:
# run as root
yum -y install httpd php mod_suphp php-bcmath
yum -y install postgresql postgresql-devel postgresql-server pgadmin3 php-pgsql
yum -y install libevent memcached php-pecl-memcache
Allow Postgresql to receive TCP connections and make sure all servers are started:
# run as root
perl -pi -e 's/postmaster -p/postmaster -i -p /' /etc/init.d/postgresql
chkconfig --level 345 postgresql on
service postgresql initdb
service postgresql start
chkconfig --level 345 memcached on
service memcached start
chkconfig --level 345 httpd on
service httpd start
If you have SELinux enabled, you may need to run these commands too.
# run as root
setsebool -P httpd_can_network_connect on
setsebool -P httpd_can_network_connect_db on
Once the database server is up and running, you must create and configure a database for the application, and then run the sql script from demo/db.sql to create and initialize the verifier storage.
This script will create a “login” table containing 3 important pieces of information:
- the username – uniquely identifies the client
- the salt – used to make the verifier more secure
- the verifier – used to determine whether the client knows the password
Here’s a sketch of the steps you may want to take:
# run as root
APP="srp_hermetic_demo"
DB=${APP}_db
USR=${APP}_user
PWD="shdu"
PGSQL_PERMISSION="host ${DB} ${USR} 127.0.0.1 255.255.255.255 md5"
if [ `grep -xc "$PGSQL_PERMISSION" /var/lib/pgsql/data/pg_hba.conf` == 0 ]; then echo "${PGSQL_PERMISSION}" >> /var/lib/pgsql/data/pg_hba.conf; fi
perl -pi -e 's/^host\s*all/#host all/mg' /var/lib/pgsql/data/pg_hba.conf
service postgresql restart
sudo -u postgres psql -d template1 -c "DROP DATABASE ${DB}"
sudo -u postgres psql -d template1 -c "CREATE USER ${USR} ENCRYPTED PASSWORD '${PWD}' NOCREATEDB NOCREATEUSER;"
sudo -u postgres psql -d template1 -c "CREATE DATABASE ${DB} OWNER ${USR} ENCODING='UNICODE';"
psql -d ${DB} -h 127.0.0.1 -U ${USR} -f demo/db.sql
Then, configure hermetic/php/config/config.php to tell the library where the password verifiers are stored and where to store session information by changing the connection string and memcache connection information. The default database connection settings configuration is compatible with the database setup above, make sure to make the necessary updates to it if you have changed the setup in any way.
$dbConnectString = 'host=127.0.0.1 port=5432 dbname=srp_hermetic_demo_db user=srp_hermetic_demo_user password=shdu';
If you don’t want to use postgresql or memcache, you will have to do more work and translate the queries and methods from storage.php, but you need to be careful to preserve the functionality of the existing code. In future, we intend to offer support for other data storage backends.
To deploy the demo application, execute, with proper permissions (e.g. root):
# run this in srp-hermetic directory extracted from the downloaded archive
./demo/deploy_php.sh
This will copy the needed files in the target directories specified in demo/deploy_php.conf.
With the default settings, you should be able to access the demo application at http://localhost/demo/demo/html/usermanagement.html.
You can log in with user name admin, password admin. In Firefox, you can use Firebug to monitor the Ajax traffic created by the application.
SRP-Hermetic customization
Any web service handled by the SRP-Hermetic library must use one single communication mode. For example, it must be established beforehand between the client and the server that all requests to test-service.php have to be signed (not encrypted, not plain-text), and that all responses sent back to the client must be encrypted (not signed, not plain-text). It is impossible for the user to select the communication mode for a given service at runtime, as the server will accept only one communication mode for one particular service URL. Doing otherwise will open the possibility of downgrade attacks, in which a service request which is supposed to be highly confidential is requested by the client in a less secure manner (e.g. plain-text), either as a consequence of the user being tricked into doing so by a third party, or as a consequence of the user’s intention to claim that the confidential information could have been exposed to third parties.
For a given web service URL, one of the following communication modes has to be selected, both on client and server side.
| Request/Reponse | Plain | Signed | Encrypted |
| Plain | hQuery.Plain | hQuery.PlainSigned | hQuery.PlainEncrypted |
| Signed | hQuery.SignedPlain | hQuery.Signed | hQuery.SignedEncrypted |
| Encrypted | hQuery.EncryptedPlain | hQuery.EncryptedSigned | hQuery.Encrypted |
When the communication mode name has two components, the first one gives the send mode or how the service is requested by the browser, while the second one gives the receive mode or how the message is to be answered by the server. For example, hQuery.EncryptedSigned means that the service request must be encrypted and the server will answer in a signed message. When only one mode is mentioned, then both the request and the response are sent in the same manner. For example, hQuery.Signed means that the service request must be signed and the server will answer in a signed message.
Let us have a brief look at some possible consequences of using a given communication mode.
A request sent in plain text can be easily forged and be used to put unnecessary load on the server. A response sent in plain text, apart from being viewable by any host between the client and the server, can be easily modified by an attacker. Because of that, only modes listed in bold in the table above are recommended in production applications. Encrypting is typically more expensive than signing, so when the contents of a piece information is not necessarily confidential (e.g. the server only needs to respond with “OK/Failed” to an encrypted service request), application designers can choose a less expensive method for exchanging information, in this case hQuery.EncryptedSigned.
Note that the URL is not part of the signed message so it is possible for an attacker to modify it while in transit. To elliminate the risk of executing an unwanted command that has identical parameters with another one (e.g. deleteUser.php instead of viewUser.php with the parameter userId), it is recommended that the application introduces a service identifier with each request. For example the service should also receive a parameter operationName (”delete” or “view”) along with the userId.
Although login sessions can’t be replayed, individual messages can be replayed while the session is still active, and this leaves the responsibility of dealing with duplicate messages to the application layer. In most cases this is not a problem, for example, replaying a “delete” message would not cause any damage but replaying a “debit account” message could have a significant impact.
Here is how the communication mode is selected in the client code:
hQuery.send(urlService, requestData, function (responseData, responseStatus) {
if (responseData) {
console.log(data.firstName, " ", data.lastName);
} else {
console.log("error: ", textStatus);
}
}, hQuery.SignedEncrypted);
On the server side, specify the communication mode as an argument to the Hermetic constructor, for example:
$hermetic = new Hermetic(Hermetic::SignedEncrypted);
$request = $hermetic->unpack( $_POST );
If the client uses a mode that the server doesn’t expect, the request will fail.
Implementation Overview
The library consists of several progressively larger building blocks: large integer arithmetic functions, cryptographic hash functions, pseudo-random number generators, storage interfaces, encryption functions, message authentication functions and the SRP protocol handler.
Some of these building blocks have several interchangeable implementations which can be configured or customized when building an application. For example, the hash function can be one of MD5, SHA-1, SHA256, SHA512, Tiger or WHIRLPOOL, without impacting the rest of the library. This doesn’t mean that all hash functions offer the same security or performance. All these building blocks come in pairs, they have an implementation for the client side (in JavaScript) and another one for the server side.
Client side
Large integer operations are part of the Variable class, which also encapsulates the conversion between UTF strings, hex and array representations. This makes it easier to implement cryptographic functions where strings are treated as numbers and different functions need numbers in different representations. For example one can multiply a password by the username and hash the result in one line of code:
Hermetic.Hash(new Hermetic.Variable().fromUtfString("username").mult(Hermetic.Variable().fromUtfString("password").toHex());
Notice the use of Hermetic.Hash in the example above. Hermetic.Hash along with Hermetic.Hmac and Hermetic.Cipher are the public interface to the crypto engine.
You can use these outside an authenticated session as part of your application logic as follows:
var hexMac = Hermetic.Hmac(hexMessage, hexMacKey);
var base64EncryptedMessage = Hermetic.Cipher.encrypt( utfMessage, hexEncryptKey, keyBits);
var decryptedUtfMessage = Hermetic.Cipher.decrypt(base64EncryptedMessage, hexEncryptKey, keyBits);
// in the case of AES keyBits can be one of 128, 196, 256
The SRP protocol logic and computations are encapsulated within Hermetic.Srp. While you can instantiate a SRP session by calling:
var session = Hermetic.Srp.createSession(username,password,nonce);
you shouldn’t need to instantiate a session by yourself, as this is handled internally.
However Hermetic.Srp does have a more useful function, as it can be used to create verifiers:
var verifier = Hermetic.Srp.computeVerifier(username, password, salt);
The username and password are the raw values given by the user, and the salt is the hex representation of 10 random bytes that can be obtained from the pseudo-random number generator Hermetic.Prng:
var salt = Hermetic.Prng.getRandomBytes(10);
The distribution contains a simple page demonstrating this use case (generateverifier.html).
Server side
Working with large numbers in PHP is simpler on the server side thanks to the bcmath library. Most of the math is done in the SrpServerSession class (srp.php), which implements the server part of the SRP protocol.
The crypto functions are either implemented in crypto_util.php (hmac, prng), aes.php (aes) or native (sha1).
Generally a developer will work with the Hermetic class, defined in “hermetic.php”. This class packs and unpacks request data using, in the case of signed or encrypted messages, a SecureChannel (channel.php) object. The secure channel offers methods for signing, encoding and decoding messages using the current session keys.
The sequence diagram below details the SRP authentication process:
Possible advantages of SRP-Hermetic
In the age of blogs, hosted services, web applications, social-networking sites, video-sharing sites and wikis your identity is defined by a username / password combination and your sensitive information lives in the cloud.
Most of the time both users and developers act as if the client and the server are two good friends having a conversation in a safe and quiet private office. In reality it’s more like two people passing notes across a busy bazaar. You never see the other party to make sure they really are who they claim, and you cannot be sure that the note you receive is not read, replaced or modified by someone in the crowd.
Some developers choose to ignore even the most basic security practices, not even bothering to hash the password in the database, although their code handles the personal data of millions of users. Other developers come up with home-brewed security schemes that offer little protection even from an unsophisticated but determined attacker. When security is deemed to be of concern (or just a useful feature from a marketing perspective), developers just turn to the “industry standard” – HTTPS. This not only gives a false sense of security, as many attacks work around https or exploit implementation mistakes, but can also be more costly than justifiable for some usage scenarios. Developing a cross-browser web application using HTTPS can be lot more painful than developing with SRP-Hermetic, mostly because of the different security policies of browsers and quirky implementations. While securing a web application is never going to be a simple task, we think it may be better to use an open source library that is peer-reviewed, rather than dealing with the problems of many implementations of an “industry standard”, which cannot always be inspected.
For example, SRP Hermetic is potentially more resilient in the event of a server compromise. Losing the private key for a signing certificate can be catastrophic and could go unnoticed for a long time. Stealing the verifier for all the users of a server would require significantly more work because (in a hardened system) the verifiers would have to be stolen one by one and this could potentially draw the attention of the administrators.
The goal of SRP-Hermetic is not to replace HTTPS, but to be used as an alternative, simpler and possibly cheaper secure channel. Note that although there is some overlap between our library and https, because both of them enable the secure transfer of information, they are actually complementary technologies, working at different levels of the protocol stack and providing different security guarantees. In fact, in situations where the performance price is justified, SRP-Hermetic and HTTPS could be used together for increased security.
Possible drawbacks and proposed solutions
The Achilles’s heel of this library, and of all javascript code is ensuring safe initial delivery to the client. A possible solution to this is using signed javascript, but this is a non-standard feature and is not supported by all browsers. Other, more involved, solutions may be implemented, based on bookmarks, similar to BeamAuth or WebIBC. Launching the application from a bookmarklet or a local html file could also aleviate this problem, and it is simple enough to be understood by most users.
While SRP network traffic can’t be used to find out the password, the verifiers stored on the server can be broken by brute force attacks if the passwords are weak. To mitigate this risk it is important to both educate users to use stronger passwords and harden the security of the verifier database by separating it from the rest of the application.
Because SRP relies on discrete exponentiation, which is computationally expensive, a denial of service attack can quickly overload the server. In order to mitigate this risk a client puzzle protocol could be implemented.
Download
You can download the gzipped tar archive containing the library code and the demo application from:
srp-hermetic.tgz
Feedback
We welcome your feedback and suggestions on our approach and implementation, and we look forward to building together an easy-to-use and secure toolkit for web applications. Please write to us at denksoft.devel@gmail.com.
References
The secure remote password protocol: http://srp.stanford.edu/
Advanced Encryption Standard (AES) in Counter Mode http://islab.oregonstate.edu/koc/ece575/04Project1/Liang-Witit/proj.pdf
The Keyed-Hash Message Authentication Code (HMAC) http://www.csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
A model and Architecture for Pseudo-Random Generation and Applications to /dev/random http://eprint.iacr.org/2005/029
Five DRBG Algorithms Based on Hash Functions and Block Ciphers http://csrc.nist.gov/groups/ST/toolkit/documents/rng/HashBlockCipherDRBG.pdf
Client Puzzles: A Cryptographic Countermeasure Against Connection Depletion Attacks http://www.rsa.com/rsalabs/staff/bios/ajuels/publications/client-puzzles/clientpuzzles.ps
Lessons Learned in Implementing and Deploying Crypto Software http://www.cs.auckland.ac.nz/~pgut001/pubs/usenix02.pdf
Credits
This library includes work by:
Leemon Baird, author of the Big Integer library
Paul Johnston, author of the SHA1 library
Chris Veness, author of the AES library
Tom Wu, inventor of the Secure Password Protocol



