Key Agreements
==============

Protocols
=========

A key agreement protocol is a means by which two parties engage in an exchange of incoming/outgoing messages, at the end of which, both participants would share a common secret.  Such a shared secret can then be used to provide different security services such as replay detection, integrity protection, and confidentiality protection.

Figure 12: Key agreement class diagram

Four key agreement protocols are implemented in this library. They are:

  * Diffie-Hellman basic version, also known as the Static-Static Mode in RFC-2631. [RFC2631]

  * ElGamal version, knwon as half-certified Diffie-Hellman key agreement, as well as Ephemeral-Static Mode in RFC-2631. [RFC2631]

  * Secure Remote Password protocol known as SRP-6. [Wu02]

  * The version of SRP-6 as used in the SASL-SRP proposed mechanism.

The following sequence diagram shows a possible use of the key agreement API classes to negotiate a Diffie-Hellman protocol:

Figure 13: Key agreement sequence diagram

The IKeyAgreementParty Interface
================================

 -- Function: java.lang.String name ()
     Returns the canonical name of the key agreement protocol.

 -- Function: void init (java.util.Map ATTRIBUTES) throws gnu.crypto.key.KeyAgreementException
     Initializes this instance. The ATTRIBUTES parameter must be a java.util.Map that has the required name-value pairs needed for this instance. An instance of gnu.crypto.key.KeyAgreementException is thrown if an exception occurs during this process.

 -- Function: gnu.crypto.key.OutgoingMessage processMessage (gnu.crypto.key.IncomingMessage IN) throws gnu.crypto.key.KeyAgreementException
     Processes an incoming message (IN) at one end, generating a message (the returned object which may be null) that will be processed by the other party(ies). A gnu.crypto.key.KeyAgreementException may be thrown if an exception occurs during this process.

 -- Function: boolean isComplete ()
     Returns true if the party in the key agreement protocol exchange has completed its part of the exchange; and false otherwise. If this method returns false, then an java.lang.IllegalStateException is thrown for any method invocation except init.

 -- Function: byte[] getSharedSecret () throws gnu.crypto.key.KeyAgreementException
     Returns the byte array containing the shared secret as generated by this party. A gnu.crypto.key.KeyAgreementException is thrown if the key agreement is not yet initialised, or is initialised but the exchange is still in progress.

 -- Function: void reset ()
     Resets this instance for re-use with another set of attributes.

The KeyAgreementFactory class
=============================

Instances for two-party key agreement protocols can be instantiated with the Factory methods of this class:

 -- Function: gnu.crypto.key.IKeyAgreementParty getPartyAInstance (java.lang.String NAME)
     Creates an instance of an initiator of a key agreement protocol given the NAME of this protocol. A null if there is no such protocol implementation.

 -- Function: gnu.crypto.key.IKeyAgreementParty getPartyBInstance (java.lang.String NAME)
     Creates an instance of a recipient of a key agreement protocol given the NAME of this protocol. A null if there is no such protocol implementation.

 -- Function: java.util.Set getNames ()
     Returns a set of the names (java.lang.String) of all available key agreement protocols.

Example, Key agreement
======================

The following example shows ...

     IKeyPairGenerator kpg =
         KeyPairGeneratorFactory.getInstance(Registry.DH_KPG);
     kpg.setup(new HashMap()); // use default values
     KeyPair kpA = kpg.generate();
     KeyPair kpB = kpg.generate();
     IKeyAgreementParty A = new DiffieHellmanSender();
     IKeyAgreementParty B = new DiffieHellmanReceiver();

     Map mapA = new HashMap();
     mapA.put(DiffieHellmanKeyAgreement.KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY,
              kpA.getPrivate());
     Map mapB = new HashMap();
     mapB.put(DiffieHellmanKeyAgreement.KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY,
              kpB.getPrivate());

     A.init(mapA);
     B.init(mapB);

     // (1) A -> B: g**x mod p
     OutgoingMessage out = A.processMessage(null);

     // (2) B -> A: g^^y mod p
     out = B.processMessage(new IncomingMessage(out.toByteArray()));

     byte[] k2 = B.getSharedSecret();

     // A computes the shared secret
     out = A.processMessage(new IncomingMessage(out.toByteArray()));

     byte[] k1 = A.getSharedSecret();