RIM Crypto API: Key Agreement

Key agreement provides a way for two independent parties to establish a secure channel over an insecure network. Key agreement protocols generally use both parties' public and private keys, along with any algorithm-specific parameters, to create a secret piece of data that, although derived from public data, is never sent out over the network. In other words, the secret data is created independently by both parties through the use of the publicly shared information. This secret data can be used as a secret session key for secure communication.

This tutorial provides an overview of key agreement and common key agreement schemes.

Using Key Agreement Schemes

One relatively easy to use key agreement scheme is Diffie-Hellman Elliptic Curve key agreement (ECDHKeyAgreement). It requires the use of a public key and a private key. Each party uses their own private key and the public key of the other party. When each party uses the key agreement algorithm, the same secret data is created.

NOTE: This code assumes the methods sendPublicKey() and receivePublicKey() exist and enable the exchange of keys between the two clients. If something is sent by one client, it will be received by the other, and vice versa.

The first step in the process is to create the local secret. Below, the generateLocalSecret method is run on the local client to generate the local secret.


public void generateLocalSecret()
{

    // Create an EC crypto system for key creation
    ECCryptoSystem cryptoSystem = new ECCryptoSystem();

    // Create the first party's public and private keys
    ECKeyPair client1KeyPair = new ECKeyPair( cryptoSystem );

Once the local keyPair is created, the local (client1) client's public key is sent to the remote user and the remote user's public key is received using the previously implemented and mutually agreed upon exchange protocol. The local client's private key and the remote user's public key are then used by the generateSharedSecret method to create a local shared secret. The local shared secret will be identical to the secret generated by the remote client.

    // Send and receive keys
    sendPublicKey( client1KeyPair.getECPublicKey() );
    ECPublicKey client2PublicKey = receivePublicKey();

    // Generate the shared secret for this client.
    byte[] client1Secret =
        ECDHKeyAgreement.generateSharedSecret(
            client1KeyPair.getECPrivateKey(),
            client2PublicKey );

    // Create a shared secret key based on the shared secret
    DESKey secretKey = new DESKey( client1Secret );
}
Finally, the secret key, of type DESKey, is generated. This is the shared key that will be used for communication between clients.

Below, the generateRemoteSecret method creates the remote user's shared secret and key using the same technique as above.


public void generateRemoteSecret()
{

    // Create an EC crypto system for key creation
    ECCryptoSystem cryptoSystem = new ECCryptoSystem();

    // Create the remote public and private keys
    ECKeyPair client2KeyPair = new ECKeyPair( cryptoSystem );

Like the above example, the local (client2) client's private key and the remote user's public key are then used by the generateSharedSecret method to create a local shared secret. The local shared secret will be identical to the secret generated in the above example.

    // Send and receive the keys
    sendPublicKey( client2KeyPair.getECPublicKey() );
    ECPublicKey client1PublicKey = receivePublicKey();

    // Generate the secret data based upon the client1 public
    // key and client2 private key
    byte[] client2Secret =
        ECDHKeyAgreement.generateSharedSecret(
            client2KeyPair.getECPrivateKey(),
            client1PublicKey );

    // Create a shared secret key based
    // on this secret data
    DESKey secretKey = new DESKey( client2Secret );
}

The above examples are strictly theoretical since both operations will occur locally and the details of the key exchange are not displayed. In an actual situation, the public keys would have to be exchanged over the network and the private keys would be kept securely by each party. The shared secrets created by each client (client1Secret and client2Secret) will be identical.

An Example of ECMQV Key Agreement

Another, newer key agreement scheme is Elliptic Curve MQV (Menezes, Qu, and Vanstone) Key Agreement (ECMQVKeyAgreement). This scheme makes use of an additional set of ephemeral keys for added security. Ephemeral keys are keys that are stored and used for only a limited amount of time. This way, if a key is compromised, a new key is created periodically and the compromised key is no longer used.

The code required is very similar to ECDH key agreement above.

NOTE: This code assumes the methods sendPublicKey() and receivePublicKey() exist and enable the exchange of keys between the two clients. If something is sent by one client, it will be received by the other, and vice versa.


public void generateLocalSecret()
{

    // Create an EC crypto system for key creation
    ECCryptoSystem cryptoSystem = new ECCryptoSystem();

    // Create the first client's static and
    // ephemeral key pairs
    ECKeyPair client1StaticPair =
                        new ECKeyPair( cryptoSystem );
    ECKeyPair client1EphemeralPair =
                        new ECKeyPair( cryptoSystem );

Above, the keys are created. This step is distinct from the previous example in that both a static, or regular keyPair, and an ephemeral, or temporary, keyPair are created.

Below, both the newly created public and public ephemeral keyPair are sent to the user and received from the user using a predetermined key exchange protocol.


    // Send and receive public keys
    sendPublicKey( client1StaticPair.getECPublicKey() );
    sendPublicKey( client1EphemeralPair.getECPublicKey() );
    ECPublicKey client2StaticKey = receivePublicKey();
    ECPublicKey client2EphemeralKey = receivePublicKey();

    // Generate the shared secret for this client. This
    // will be identical to that generated by client2.
    byte[] client1Secret =
        ECMQVKeyAgreement.generateSharedSecret(
            client1StaticPair.getECPrivateKey(),
            client1EphemeralPair,
            client2StaticKey,
            client2EphemeralKey );

    // Create a shared secret key based
    // on this secret data
    DESKey secretKey = new DESKey( client1Secret );
}
Like in the previous example, a shared secret is created and a shared secret key is then created using this shared secret. Since the operation is uses ephemeral keys, the generateSharedSecret method uses the clients private key, the remote user's public key, the local ephemeral keyPair and the remote ephemeral public key.

public void generateRemoteSecret()
{

    // Create an EC crypto system for key creation
    ECCryptoSystem cryptoSystem = new ECCryptoSystem();

    // Create the second client's static and
    // ephemeral key pairs
    ECKeyPair client2StaticPair =
                        new ECKeyPair( cryptoSystem );
    ECKeyPair client2EphemeralPair =
                        new ECKeyPair( cryptoSystem );

    // Send and receive the keys
    sendPublicKey( client2StaticPair.getECPublicKey() );
    sendPublicKey( client2EphemeralPair.getECPublicKey() );
    ECPublicKey client1StaticKey = receivePublicKey();
    ECPublicKey client1EphemeralKey = receivePublicKey();

    // Generate the shared secret for this client.
    byte[] client2Secret =
        ECMQVKeyAgreement.generateSharedSecret(
            client2StaticPair.getECPrivateKey(),
            client2EphemeralPair,
            client1StaticKey,
            client1EphemeralKey );

    // Now we can create a shared secret key based
    // on this secret data
    DESKey secretKey = new DESKey( client2Secret );
}

Again, this example is strictly theoretical since both operations will occur locally and the details of the key exchange are not displayed. In an actual situation, the keys would have to be exchanged over the network and the private keys would be kept securely by each party. The shared secrets created by each client (client1Secret and client2Secret) will be identical.

This scheme, in effect, uses five keys. The local public and private ephemeral keys, the local private static key, the remote public static key, and the remote public ephemeral key.

The Crypto API supports the following key agreement schemes: