An elliptic curve implementation of the Owl PAKE protocol using Java.
Owl is an Augmented Password Key Exchange Protocol, developed by Feng Hao, Samiran Bag, Liqun Chan, Paul van Oorschot, in this paper: Owl: An Augmented Password-Authenticated Key Exchange Scheme.
Functionality includes the registration of a new user on the a server, and the authentication of an existing user through the username and password login system.
Owl can be implemented by using either elliptic curve cryptography or a finite field setting. This implementation was developed using the former.
To install the package, run:
git clone https://github.com/dawmit/OWL.git
This will clone the repository locally.
To build the package, run:
./gradlew build
To run the tests manually, run:
./gradlew test
To run without the tests, run:
./gradlew run -x test
To use this protocol as part of your application go to the Owl_ Example class to see an example usage of this protocol.
There are two seperate modes of functionality: user registration and user authentication:
To register a user on the server you must first construct an Owl_ClientRegistration and Owl_ServerRegistration package.
Owl_ServerRegistration server = new Owl_ServerRegistration("serverId", curve, digest2, random2);
Remember that the elliptic curve you choose has to be the same for both server and client otherwise the calculations will fail. You should choose a pre-existing from Owl_Curves, to avoid any vulnerabilities caused by insecure curve parameters.
Now to register a user, the client creates an Owl_InitialRegistration payload that must be sent to the server over a secure communications channel, otherwise passive attackers will be able to calculate the secret password.
Owl_FinishRegistration toBeStoredOnServer = server.registerUseronServer(registrationPayload);
Then server uses the payload generated by the client, to generate its own secret payload Owl_FinishRegistration that is to be stored externally, and securely, for use in the authentication phase.
For authentication, similar to registration, we must create a client and server, again remember to use the same curve for each client and server as well as the same curve used to register the users currently attempting to log in.
Owl_Server serve = new Owl_Client("serverId", curve, digest, random);
Passwords must mach for authentication to proceed.
Now call the following methods in this order:
Owl_AuthenticationServerResponse serverLoginResponse = server.authenticationServerResponse(clientLoginStart, serverUserRegistration);
Owl_AuthenticationFinish clientLoginEnd = client.authenticationFinish(serverLoginResponse);
server.authenticationServerEnd(clientLoginEnd);
This completes the handshake protocol, now to generate the keying material:
BigInteger serverKeyingMaterial = server.calculateKeyingMaterial();
To derive a full session key, a secure Key Derivation Function must be used, this is to be handled externally by the user.
Explicit key confirmation allows the client and the server to explicitly check whether or not they have generated the same keys after the key exchange handshake. Without performing this step, the user has no way of knowing whether or not both the client and server generated the same keys (as they should). The client can perform explicit key confirmation by adding a key confirmation string in the third pass, whilst the server can perform explicit key confirmation in the fourth pass.
Owl_KeyConfirmation serverKCPayload = server.initiateKeyConfirmation(serverKeyingMaterial);
client.validateKeyConfirmation(serverKCPayload, clientKeyingMaterial);
server.validateKeyConfirmation(clientKCPayload, serverKeyingMaterial);
If there are no errors, then the keys are a match! Using you're own KDF you can derive a session key from the clientKeyingMaterial and serverKeyingMaterial.
The password update functionality is to be handled externally at the application layer.
Thank you to Prof. Hao Feng from Warwick University, Department of Computer Science for helping build and overseeing this implementation.