org.bouncycastle.crypto.agreement.owl

## Class OwlClient

- java.lang.Object
- - org.bouncycastle.crypto.agreement.owl.OwlClient

-     public class OwlClient
      extends java.lang.Object

  A client in the Elliptic Curve Owl key exchange protocol.

  Owl is an augmented password-authenticated key exchange (PAKE) protocol, defined by Feng Hao, Samiran Bag, Liqun Chen, and Paul C. van Oorschot in the paper "Owl: An Augmented Password-Authenticated Key Exchange Scheme". Owl builds on the same idea as J-PAKE (using Schnorr zero-knowledge proofs to enforce participants to follow the protocol specification honestly), but it is augmented to provide additional protection against server compromise. While J-PAKE is symmetric, Owl is asymmetric. Like J-PAKE, Owl can be implemented in either elliptic curve (EC) or finite field (FF) settings. This implementation is done in the elliptic curve setting. Any elliptic curve that is suitable for cryptography can be used for Owl (same for J-PAKE).

  Owl is an academic protocol — not (yet) an IETF standard. Callers who need a standardised PAKE should prefer the existing J-PAKE in `org.bouncycastle.crypto.agreement.jpake` / `org.bouncycastle.crypto.agreement.ecjpake`.

  In Owl, there is one client and one server communicating between each other. An instance of `OwlServer` represents one server, and an instance of `OwlClient` represents one client. These together make up the main machine through which the protocol is facilitated.

  There are two distinct phases that can be taken in Owl: user registration - where the client registers as a new user on the server; login - where an existing user (client) attempts to log in and establish a shared session key with the server based on password authentication. Using the session key, the user (client) can perform further actions (e.g., password update) over a secure channel, but these actions are outside the scope of this key exchange program.

  The user registration phase involves only one pass of communication from the client to the server. It's assumed that the following communication is done over a secure channel (e.g., using an out-of-band method).

  1. `OwlClientRegistration.initiateUserRegistration()` - The client sends payload to the server.
  After receiving the payload, the server calls `OwlServerRegistration.registerUseronServer(OwlInitialRegistration)` to generate a user credential file `OwlFinishRegistration` and safely store it on the server. The login phase involves three passes of communication between the client and the server. The following communications do not have to be sent via secure channels. Call the following methods in this order, with the client initiating every key exchange process.
  1. `authenticationInitiate()` - The client sends payload to the server
  2. `OwlServer.authenticationServerResponse(OwlAuthenticationInitiate, OwlFinishRegistration)` - The server validates the payload received from the client, retrieves the user credentials stored in the server from user registration, and sends the payload generated to the client.
  3. `authenticationFinish(OwlAuthenticationServerResponse)` - The client validates the payload from the server, and sends next payload generated by this function back to the server.

  After the third pass, the client has completed client-to-server authentication. At this point, both the client and the server can compute a shared key. They call the following methods to compute a raw keying material and do key confirmation.

  - `OwlServer.authenticationServerEnd(OwlAuthenticationFinish)` - The server validates the payload from the client in the third pass.
  - `calculateKeyingMaterial()` - Both the client and the server execute this to generate a common key material.
  - `initiateKeyConfirmation(BigInteger)` - Either the client or the server sends the payload to the other participant for explicit key confirmation in this exchange. This is called by both client and server.
  - `validateKeyConfirmation(OwlKeyConfirmation, BigInteger)` - Either the client or the server validates the payload received from the other participant to check if the same key has been derived. This is called by both client and server.

  Each side should derive a session key from the keying material returned by `calculateKeyingMaterial()`. The caller is responsible for deriving the session key using a secure key derivation function (KDF).

  The explicit key confirmation process is optional but highly recommended. It does not affect the round efficiency and adds a negligible computational cost. The client-to-server key confirmation string can be piggybacked in the third pass along with `OwlAuthenticationFinish`. The server-to-client key confirmation string can be sent in the next pass together with encrypted data. If you do not execute key confirmation, then there is no assurance that both client and server have actually derived the same key, and the ensuing secure communication may fail. If the key confirmation succeeds, then the keys are guaranteed to be the same on both sides.

  The key confirmation process is implemented as specified in NIST SP 800-56A Revision 3, Section 5.9.1 Unilateral Key Confirmation for Key Agreement Schemes.

  This class is stateful and NOT threadsafe. Each instance should only be used for ONE complete Owl key exchange (i.e. a new `OwlServer` and `OwlClient` should be constructed for each new Owl key exchange).

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static int` | `STATE_INITIALISED`
    `static int` | `STATE_KC_INITIALISED`
    `static int` | `STATE_KC_VALIDATED`
    `static int` | `STATE_KEY_CALCULATED`
    `static int` | `STATE_LOGIN_FINISHED`
    `static int` | `STATE_LOGIN_INITIALISED`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `OwlClient(java.lang.String clientId, char[] password)` Convenience constructor for a new `OwlClient` that uses the `OwlCurves.NIST_P256` elliptic curve, a SHA-256 digest, and a default `SecureRandom` implementation.
    `OwlClient(java.lang.String clientId, char[] password, OwlCurve curve)` Convenience constructor for a new `OwlClient` that uses a SHA-256 digest and a default `SecureRandom` implementation.
    `OwlClient(java.lang.String clientId, char[] password, OwlCurve curve, Digest digest, java.security.SecureRandom random)` Construct a new `OwlClient`.

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `OwlAuthenticationFinish` | `authenticationFinish(OwlAuthenticationServerResponse authenticationServerResponse)` Finalises the login authentication protocol by creating and sending the final payload to the server.
    `OwlAuthenticationInitiate` | `authenticationInitiate()` Creates and returns the payload to send to the server as part of the first pass of the protocol.
    `java.math.BigInteger` | `calculateKeyingMaterial()` Calculates and returns the key material.
    `int` | `getState()` Gets the current state of this client.
    `OwlKeyConfirmation` | `initiateKeyConfirmation(java.math.BigInteger keyingMaterial)` Creates and returns the payload to send to the server as part of Key Confirmation.
    `void` | `validateKeyConfirmation(OwlKeyConfirmation keyConfirmationPayload, java.math.BigInteger keyingMaterial)` Validates the key confirmation payload received by the server.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### STATE_INITIALISED

          public static final int STATE_INITIALISED

      See Also:
        Constant Field Values

    - #### STATE_LOGIN_INITIALISED

          public static final int STATE_LOGIN_INITIALISED

      See Also:
        Constant Field Values

    - #### STATE_LOGIN_FINISHED

          public static final int STATE_LOGIN_FINISHED

      See Also:
        Constant Field Values

    - #### STATE_KEY_CALCULATED

          public static final int STATE_KEY_CALCULATED

      See Also:
        Constant Field Values

    - #### STATE_KC_INITIALISED

          public static final int STATE_KC_INITIALISED

      See Also:
        Constant Field Values

    - #### STATE_KC_VALIDATED

          public static final int STATE_KC_VALIDATED

      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### OwlClient

          public OwlClient(java.lang.String clientId,
                           char[] password)

      Convenience constructor for a new `OwlClient` that uses the `OwlCurves.NIST_P256` elliptic curve, a SHA-256 digest, and a default `SecureRandom` implementation.

      After construction, the `state` will be `STATE_INITIALISED`.

      Parameters:
        `clientId` - unique identifier of this client. The server and client in the exchange must NOT share the same id.
        `password` - shared secret. A defensive copy of this array is made (and cleared once `calculateKeyingMaterial()` is called). Caller should clear the input password as soon as possible.
      Throws:
        `java.lang.NullPointerException` - if any argument is null
        `java.lang.IllegalArgumentException` - if password is empty

    - #### OwlClient

          public OwlClient(java.lang.String clientId,
                           char[] password,
                           OwlCurve curve)

      Convenience constructor for a new `OwlClient` that uses a SHA-256 digest and a default `SecureRandom` implementation.

      After construction, the `state` will be `STATE_INITIALISED`.

      Parameters:
        `clientId` - unique identifier of this client. The server and client in the exchange must NOT share the same id.
        `password` - shared secret. A defensive copy of this array is made (and cleared once `calculateKeyingMaterial()` is called). Caller should clear the input password as soon as possible.
        `curve` - elliptic curve See `OwlCurves` for standard curves.
      Throws:
        `java.lang.NullPointerException` - if any argument is null
        `java.lang.IllegalArgumentException` - if password is empty

    - #### OwlClient

          public OwlClient(java.lang.String clientId,
                           char[] password,
                           OwlCurve curve,
                           Digest digest,
                           java.security.SecureRandom random)

      Construct a new `OwlClient`.

      After construction, the `state` will be `STATE_INITIALISED`.

      Parameters:
        `clientId` - unique identifier of this client. The server and client in the exchange must NOT share the same id.
        `password` - shared secret. A defensive copy of this array is made (and cleared once `calculateKeyingMaterial()` is called). Caller should clear the input password as soon as possible.
        `curve` - elliptic curve. See `OwlCurves` for standard curves
        `digest` - digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
        `random` - source of secure random data for x1 and x2, and for the zero knowledge proofs
      Throws:
        `java.lang.NullPointerException` - if any argument is null
        `java.lang.IllegalArgumentException` - if password is empty

  - ### Method Detail

    - #### getState

          public int getState()

      Gets the current state of this client. See the `STATE_*` constants for possible values.
      Returns:
        the state of the client

    - #### authenticationInitiate

          public OwlAuthenticationInitiate authenticationInitiate()

      Creates and returns the payload to send to the server as part of the first pass of the protocol.

      Must be called prior to `authenticationFinish(OwlAuthenticationServerResponse)` After execution, the `state` will be `STATE_LOGIN_INITIALISED`.

      Returns:
        `OwlAuthenticationInitiate`
      Throws:
        `java.lang.IllegalStateException` - if called multiple times.

    - #### authenticationFinish

          public OwlAuthenticationFinish authenticationFinish(OwlAuthenticationServerResponse authenticationServerResponse)
                                                       throws CryptoException

      Finalises the login authentication protocol by creating and sending the final payload to the server. Validates the payload sent by the `OwlServer.authenticationServerResponse(OwlAuthenticationInitiate, OwlFinishRegistration)` after login initilisation.

      Must be called prior to `calculateKeyingMaterial()`.

      After execution, the `state` will be `STATE_LOGIN_FINISHED`.

      Parameters:
        `authenticationServerResponse` - The payload sent by `OwlServer.authenticationServerResponse(OwlAuthenticationInitiate, OwlFinishRegistration)` and to be validated.
      Returns:
        `OwlAuthenticationFinish`
      Throws:
        `CryptoException` - if validation fails.
        `java.lang.IllegalStateException` - if called prior to `authenticationInitiate()` or called multiple times.

    - #### calculateKeyingMaterial

          public java.math.BigInteger calculateKeyingMaterial()

      Calculates and returns the key material. A session key must be derived from this key material using a secure key derivation function (KDF). The KDF used to derive the key is handled externally (i.e. not by `OwlClient`).

      The keying material will be identical for client and server if and only if the login password is the same as the password stored by the server. i.e. If the client and server do not share the same password, then each will derive a different key. Therefore, if you immediately start using a key derived from the keying material, then you must handle detection of incorrect keys. If you want to handle this detection explicitly, you can perform explicit key confirmation. See `OwlClient` for details on how to execute key confirmation.

      If the passwords used for registration and login are different then this will be caught when validating r during `OwlServer.authenticationServerEnd(OwlAuthenticationFinish)`.

      `authenticationFinish(OwlAuthenticationServerResponse)` must be called prior to this method.

      As a side effect, the internal `password` array is cleared, since it is no longer needed.

      After execution, the `state` will be `STATE_KEY_CALCULATED`.

      Returns:
        raw key material
      Throws:
        `java.lang.IllegalStateException` - if called prior to `authenticationFinish(OwlAuthenticationServerResponse)`, or if called multiple times.

    - #### initiateKeyConfirmation

          public OwlKeyConfirmation initiateKeyConfirmation(java.math.BigInteger keyingMaterial)

      Creates and returns the payload to send to the server as part of Key Confirmation.

      See `OwlClient` for more details on Key Confirmation.

      After execution, the `state` will be `STATE_KC_INITIALISED`.

      Parameters:
        `keyingMaterial` - The keying material as returned from `calculateKeyingMaterial()`.
      Returns:
        `OwlKeyConfirmation`
      Throws:
        `java.lang.IllegalStateException` - if called prior to `calculateKeyingMaterial()`, or multiple times

    - #### validateKeyConfirmation

          public void validateKeyConfirmation(OwlKeyConfirmation keyConfirmationPayload,
                                              java.math.BigInteger keyingMaterial)
                                       throws CryptoException

      Validates the key confirmation payload received by the server.

      See `OwlClient` for more details on Key Confirmation.

      After execution, the `state` will be `STATE_KC_VALIDATED`.

      Parameters:
        `keyConfirmationPayload` - The key confirmation payload received from the other client.
        `keyingMaterial` - The keying material as returned from `calculateKeyingMaterial()`.
      Throws:
        `CryptoException` - if validation fails.
        `java.lang.IllegalStateException` - if called prior to `calculateKeyingMaterial()`, or multiple times