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):
createRound1PayloadToSend() - and send the payload to the other participantvalidateRound1PayloadReceived(JPAKERound1Payload) - use the payload received from the other participantcreateRound2PayloadToSend() - and send the payload to the other participantvalidateRound2PayloadReceived(JPAKERound2Payload) - use the payload received from the other participantcalculateKeyingMaterial()createRound3PayloadToSend(BigInteger) - and send the payload to the other participantvalidateRound3PayloadReceived(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).
| Modifier and Type | Field and Description |
|---|---|
| private BigInteger | b
Alice's B or Bob's A. |
| private final Digest | digest
Digest to use during calculations. |
| private final BigInteger | |
| 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 | |
| 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 | |
| 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. |
| Access | Constructor 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 password)calculateKeyingMaterial() is called).
Caller should clear the input password as soon as possible.Convenience constructor for a new |
| 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 password, JPAKEPrimeOrderGroup calculateKeyingMaterial() is called).
Caller should clear the input password as soon as possible.prime order group.
See group)JPAKEPrimeOrderGroups for standard groupsConvenience constructor for a new |
| 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 password, JPAKEPrimeOrderGroup calculateKeyingMaterial() is called).
Caller should clear the input password as soon as possible.prime order group.
See group, Digest JPAKEPrimeOrderGroups for standard groupsdigest 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 |
| Modifier and Type | Method and Description |
|---|---|
| public BigInteger | |
| 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 keyingMaterial)calculateKeyingMaterial().Creates and returns the payload to send to the other participant during round 3. |
| public int | |
| 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 keyingMaterial)calculateKeyingMaterial().Validates the payload received from the other participant during round 3. |
| b | back to summary |
|---|---|
| private BigInteger b Alice's B or Bob's A. | |
| digest | back to summary |
|---|---|
| private final Digest digest Digest to use during calculations. | |
| g | back to summary |
|---|---|
| private final BigInteger g | |
| gx1 | back to summary |
|---|---|
| private BigInteger gx1 Alice's g^x1 or Bob's g^x3. | |
| gx2 | back to summary |
|---|---|
| private BigInteger gx2 Alice's g^x2 or Bob's g^x4. | |
| gx3 | back to summary |
|---|---|
| private BigInteger gx3 Alice's g^x3 or Bob's g^x1. | |
| gx4 | back to summary |
|---|---|
| private BigInteger gx4 Alice's g^x4 or Bob's g^x2. | |
| p | back to summary |
|---|---|
| private final BigInteger p | |
| participantId | back to summary |
|---|---|
| private final String participantId Unique identifier of this participant. The two participants in the exchange must NOT share the same id. | |
| partnerParticipantId | back to summary |
|---|---|
| private String partnerParticipantId The participantId of the other participant in this exchange. | |
| password | back to summary |
|---|---|
| private char[] password Shared secret. This only contains the secret between construction
and the call to
i.e. When | |
| q | back to summary |
|---|---|
| private final BigInteger q | |
| random | back to summary |
|---|---|
| private final SecureRandom random Source of secure random data. | |
| state | back to summary |
|---|---|
| private int state The current state. See the STATE_* constants for possible values. | |
| STATE_INITIALIZED | back to summary |
|---|---|
| public static final int STATE_INITIALIZED | |
| STATE_KEY_CALCULATED | back to summary |
|---|---|
| public static final int STATE_KEY_CALCULATED | |
| STATE_ROUND_1_CREATED | back to summary |
|---|---|
| public static final int STATE_ROUND_1_CREATED | |
| STATE_ROUND_1_VALIDATED | back to summary |
|---|---|
| public static final int STATE_ROUND_1_VALIDATED | |
| STATE_ROUND_2_CREATED | back to summary |
|---|---|
| public static final int STATE_ROUND_2_CREATED | |
| STATE_ROUND_2_VALIDATED | back to summary |
|---|---|
| public static final int STATE_ROUND_2_VALIDATED | |
| STATE_ROUND_3_CREATED | back to summary |
|---|---|
| public static final int STATE_ROUND_3_CREATED | |
| STATE_ROUND_3_VALIDATED | back to summary |
|---|---|
| public static final int STATE_ROUND_3_VALIDATED | |
| x1 | back to summary |
|---|---|
| private BigInteger x1 Alice's x1 or Bob's x3. | |
| x2 | back to summary |
|---|---|
| private BigInteger x2 Alice's x2 or Bob's x4. | |
| JPAKEParticipant | back to summary |
|---|---|
| public JPAKEParticipant(String participantId, char[] password) Convenience constructor for a new
After construction, the
| |
| JPAKEParticipant | back to summary |
|---|---|
| public JPAKEParticipant(String participantId, char[] password, JPAKEPrimeOrderGroup group) Convenience constructor for a new
After construction, the
| |
| JPAKEParticipant | back to summary |
|---|---|
| public JPAKEParticipant(String participantId, char[] password, JPAKEPrimeOrderGroup group, Digest digest, SecureRandom random) Construct a new
After construction, the
| |
| calculateKeyingMaterial | back 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
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 The keying material will be in the range [0, p-1].
As a side effect, the internal
After execution, the
| |
| calculateS | back to summary |
|---|---|
| private BigInteger calculateS() | |
| createRound1PayloadToSend | back to summary |
|---|---|
| public JPAKERound1Payload createRound1PayloadToSend() Creates and returns the payload to send to the other participant during round 1.
After execution, the | |
| createRound2PayloadToSend | back to summary |
|---|---|
| public JPAKERound2Payload createRound2PayloadToSend() Creates and returns the payload to send to the other participant during round 2.
After execution, the
| |
| createRound3PayloadToSend | back to summary |
|---|---|
| public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial) Creates and returns the payload to send to the other participant during round 3.
See
After execution, the
| |
| getState | back to summary |
|---|---|
| public int getState() Gets the current state of this participant. See the STATE_* constants for possible values. | |
| validateRound1PayloadReceived | back 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
After execution, the
| |
| validateRound2PayloadReceived | back 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
After execution, the
| |
| validateRound3PayloadReceived | back to summary |
|---|---|
| public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial) throws CryptoException Validates the payload received from the other participant during round 3.
See
After execution, the
| |