Top Description Fields Constructors Methods
org.bouncycastle.crypto.agreement.jpake

public Class JPAKEParticipant

extends Object
Class Inheritance
Imports
java.math.BigInteger, java.security.SecureRandom, org.bouncycastle.crypto.CryptoException, .CryptoServicesRegistrar, .Digest, org.bouncycastle.crypto.digests.SHA256Digest, org.bouncycastle.util.Arrays, .Exceptions

A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.

The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper "Password Authenticated Key Exchange by Juggling, 2008."

The J-PAKE protocol is symmetric. There is no notion of a client or server, but rather just two participants. An instance of JPAKEParticipant represents one participant, and is the primary interface for executing the exchange.

To execute an exchange, construct a JPAKEParticipant on each end, and call the following 7 methods (once and only once, in the given order, for each participant, sending messages between them as described):

  1. createRound1PayloadToSend() - and send the payload to the other participant
  2. validateRound1PayloadReceived(JPAKERound1Payload) - use the payload received from the other participant
  3. createRound2PayloadToSend() - and send the payload to the other participant
  4. validateRound2PayloadReceived(JPAKERound2Payload) - use the payload received from the other participant
  5. calculateKeyingMaterial()
  6. createRound3PayloadToSend(BigInteger) - and send the payload to the other participant
  7. validateRound3PayloadReceived(JPAKERound3Payload, BigInteger) - use the payload received from the other participant

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).

Round 3 is an optional key confirmation process. If you do not execute round 3, then there is no assurance that both participants are using the same key. (i.e. if the participants used different passwords, then their session keys will differ.)

If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.

The symmetric design can easily support the asymmetric cases when one party initiates the communication. e.g. Sometimes the round1 payload and round2 payload may be sent in one pass. Also, in some cases, the key confirmation payload can be sent together with the round2 payload. These are the trivial techniques to optimize the communication.

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

This class is stateful and NOT threadsafe. Each instance should only be used for ONE complete J-PAKE exchange (i.e. a new JPAKEParticipant should be constructed for each new J-PAKE exchange).

Field Summary

Modifier and TypeField and Description
private BigInteger
b

Alice's B or Bob's A.

private final Digest
digest

Digest to use during calculations.

private final BigInteger
g

private BigInteger
gx1

Alice's g^x1 or Bob's g^x3.

private BigInteger
gx2

Alice's g^x2 or Bob's g^x4.

private BigInteger
gx3

Alice's g^x3 or Bob's g^x1.

private BigInteger
gx4

Alice's g^x4 or Bob's g^x2.

private final BigInteger
p

private final String
participantId

Unique identifier of this participant.

private String
partnerParticipantId

The participantId of the other participant in this exchange.

private char[]
password

Shared secret.

private final BigInteger
q

private final SecureRandom
random

Source of secure random data.

private int
state

The current state.

public static final int
public static final int
public static final int
public static final int
public static final int
public static final int
public static final int
public static final int
private BigInteger
x1

Alice's x1 or Bob's x3.

private BigInteger
x2

Alice's x2 or Bob's x4.

Constructor Summary

AccessConstructor and Description
public
JPAKEParticipant(String
unique identifier of this participant. The two participants in the exchange must NOT share the same id.
participantId
,
char[]
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.
password
)

Convenience constructor for a new JPAKEParticipant that uses the JPAKEPrimeOrderGroups#NIST_3072 prime order group, a SHA-256 digest, and a default SecureRandom implementation.

public
JPAKEParticipant(String
unique identifier of this participant. The two participants in the exchange must NOT share the same id.
participantId
,
char[]
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.
password
,
JPAKEPrimeOrderGroup
prime order group. See JPAKEPrimeOrderGroups for standard groups
group
)

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

public
JPAKEParticipant(String
unique identifier of this participant. The two participants in the exchange must NOT share the same id.
participantId
,
char[]
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.
password
,
JPAKEPrimeOrderGroup
prime order group. See JPAKEPrimeOrderGroups for standard groups
group
,
Digest
digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
digest
,
SecureRandom
source of secure random data for x1 and x2, and for the zero knowledge proofs
random
)

Construct a new JPAKEParticipant.

Method Summary

Modifier and TypeMethod and Description
public BigInteger
calculateKeyingMaterial()

Calculates and returns the key material.

private BigInteger
public JPAKERound1Payload
createRound1PayloadToSend()

Creates and returns the payload to send to the other participant during round 1.

public JPAKERound2Payload
createRound2PayloadToSend()

Creates and returns the payload to send to the other participant during round 2.

public JPAKERound3Payload
createRound3PayloadToSend(BigInteger
The keying material as returned from calculateKeyingMaterial().
keyingMaterial
)

Creates and returns the payload to send to the other participant during round 3.

public int
getState()

Gets the current state of this participant.

public void
validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)

Validates the payload received from the other participant during round 1.

public void
validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)

Validates the payload received from the other participant during round 2.

public void
validateRound3PayloadReceived(JPAKERound3Payload
The round 3 payload received from the other participant.
round3PayloadReceived
,
BigInteger
The keying material as returned from calculateKeyingMaterial().
keyingMaterial
)

Validates the payload received from the other participant during round 3.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

bback to summary
private BigInteger b

Alice's B or Bob's A.

digestback to summary
private final Digest digest

Digest to use during calculations.

gback to summary
private final BigInteger g
gx1back to summary
private BigInteger gx1

Alice's g^x1 or Bob's g^x3.

gx2back to summary
private BigInteger gx2

Alice's g^x2 or Bob's g^x4.

gx3back to summary
private BigInteger gx3

Alice's g^x3 or Bob's g^x1.

gx4back to summary
private BigInteger gx4

Alice's g^x4 or Bob's g^x2.

pback to summary
private final BigInteger p
participantIdback to summary
private final String participantId

Unique identifier of this participant. The two participants in the exchange must NOT share the same id.

partnerParticipantIdback to summary
private String partnerParticipantId

The participantId of the other participant in this exchange.

passwordback to summary
private char[] password

Shared secret. This only contains the secret between construction and the call to calculateKeyingMaterial().

i.e. When calculateKeyingMaterial() is called, this buffer overwritten with 0's, and the field is set to null.

qback to summary
private final BigInteger q
randomback to summary
private final SecureRandom random

Source of secure random data.

stateback to summary
private int state

The current state. See the STATE_* constants for possible values.

STATE_INITIALIZEDback to summary
public static final int STATE_INITIALIZED
STATE_KEY_CALCULATEDback to summary
public static final int STATE_KEY_CALCULATED
STATE_ROUND_1_CREATEDback to summary
public static final int STATE_ROUND_1_CREATED
STATE_ROUND_1_VALIDATEDback to summary
public static final int STATE_ROUND_1_VALIDATED
STATE_ROUND_2_CREATEDback to summary
public static final int STATE_ROUND_2_CREATED
STATE_ROUND_2_VALIDATEDback to summary
public static final int STATE_ROUND_2_VALIDATED
STATE_ROUND_3_CREATEDback to summary
public static final int STATE_ROUND_3_CREATED
STATE_ROUND_3_VALIDATEDback to summary
public static final int STATE_ROUND_3_VALIDATED
x1back to summary
private BigInteger x1

Alice's x1 or Bob's x3.

x2back to summary
private BigInteger x2

Alice's x2 or Bob's x4.

Constructor Detail

JPAKEParticipantback to summary
public JPAKEParticipant(String participantId, char[] password)

Convenience constructor for a new JPAKEParticipant that uses the JPAKEPrimeOrderGroups#NIST_3072 prime order group, a SHA-256 digest, and a default SecureRandom implementation.

After construction, the state will be STATE_INITIALIZED.

Parameters
participantId:String

unique identifier of this participant. The two participants in the exchange must NOT share the same id.

password:char[]

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.

Exceptions
NullPointerException:
if any argument is null
IllegalArgumentException:
if password is empty
JPAKEParticipantback to summary
public JPAKEParticipant(String participantId, char[] password, JPAKEPrimeOrderGroup group)

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

After construction, the state will be STATE_INITIALIZED.

Parameters
participantId:String

unique identifier of this participant. The two participants in the exchange must NOT share the same id.

password:char[]

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.

group:JPAKEPrimeOrderGroup

prime order group. See JPAKEPrimeOrderGroups for standard groups

Exceptions
NullPointerException:
if any argument is null
IllegalArgumentException:
if password is empty
JPAKEParticipantback to summary
public JPAKEParticipant(String participantId, char[] password, JPAKEPrimeOrderGroup group, Digest digest, SecureRandom random)

Construct a new JPAKEParticipant.

After construction, the state will be STATE_INITIALIZED.

Parameters
participantId:String

unique identifier of this participant. The two participants in the exchange must NOT share the same id.

password:char[]

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.

group:JPAKEPrimeOrderGroup

prime order group. See JPAKEPrimeOrderGroups for standard groups

digest:Digest

digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)

random:SecureRandom

source of secure random data for x1 and x2, and for the zero knowledge proofs

Exceptions
NullPointerException:
if any argument is null
IllegalArgumentException:
if password is empty

Method Detail

calculateKeyingMaterialback to summary
public 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 JPAKEParticipant).

The keying material will be identical for each participant if and only if each participant's password is the same. i.e. If the participants do not share the same password, then each participant 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 optionally perform rounds 3 and 4. See JPAKEParticipant for details on how to execute rounds 3 and 4.

The keying material will be in the range [0, p-1].

validateRound2PayloadReceived(JPAKERound2Payload) 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.

Exceptions
IllegalStateException:
if called prior to validateRound2PayloadReceived(JPAKERound2Payload), or if called multiple times.
calculateSback to summary
private BigInteger calculateS()
createRound1PayloadToSendback to summary
public JPAKERound1Payload createRound1PayloadToSend()

Creates and returns the payload to send to the other participant during round 1.

After execution, the state will be STATE_ROUND_1_CREATED.

createRound2PayloadToSendback to summary
public JPAKERound2Payload createRound2PayloadToSend()

Creates and returns the payload to send to the other participant during round 2.

validateRound1PayloadReceived(JPAKERound1Payload) must be called prior to this method.

After execution, the state will be STATE_ROUND_2_CREATED.

Exceptions
IllegalStateException:
if called prior to validateRound1PayloadReceived(JPAKERound1Payload), or multiple times
createRound3PayloadToSendback to summary
public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial)

Creates and returns the payload to send to the other participant during round 3.

See JPAKEParticipant for more details on round 3.

After execution, the state will be STATE_ROUND_3_CREATED.

Parameters
keyingMaterial:BigInteger

The keying material as returned from calculateKeyingMaterial().

Exceptions
IllegalStateException:
if called prior to calculateKeyingMaterial(), or multiple times
getStateback to summary
public int getState()

Gets the current state of this participant. See the STATE_* constants for possible values.

validateRound1PayloadReceivedback to summary
public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived) throws CryptoException

Validates the payload received from the other participant during round 1.

Must be called prior to createRound2PayloadToSend().

After execution, the state will be STATE_ROUND_1_VALIDATED.

Exceptions
CryptoException:
if validation fails.
IllegalStateException:
if called multiple times.
validateRound2PayloadReceivedback to summary
public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived) throws CryptoException

Validates the payload received from the other participant during round 2.

Note that this DOES NOT detect a non-common password. The only indication of a non-common password is through derivation of different keys (which can be detected explicitly by executing round 3 and round 4)

Must be called prior to calculateKeyingMaterial().

After execution, the state will be STATE_ROUND_2_VALIDATED.

Exceptions
CryptoException:
if validation fails.
IllegalStateException:
if called prior to validateRound1PayloadReceived(JPAKERound1Payload), or multiple times
validateRound3PayloadReceivedback to summary
public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial) throws CryptoException

Validates the payload received from the other participant during round 3.

See JPAKEParticipant for more details on round 3.

After execution, the state will be STATE_ROUND_3_VALIDATED.

Parameters
round3PayloadReceived:JPAKERound3Payload

The round 3 payload received from the other participant.

keyingMaterial:BigInteger

The keying material as returned from calculateKeyingMaterial().

Exceptions
CryptoException:
if validation fails.
IllegalStateException:
if called prior to calculateKeyingMaterial(), or multiple times