Class JPAKEParticipant
- java.lang.Object
-
- org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant
-
public class JPAKEParticipant extends java.lang.Object
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):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).
-
-
Field Summary
Fields Modifier and Type Field Description static int
STATE_INITIALIZED
static int
STATE_KEY_CALCULATED
static int
STATE_ROUND_1_CREATED
static int
STATE_ROUND_1_VALIDATED
static int
STATE_ROUND_2_CREATED
static int
STATE_ROUND_2_VALIDATED
static int
STATE_ROUND_3_CREATED
static int
STATE_ROUND_3_VALIDATED
-
Constructor Summary
Constructors Constructor Description JPAKEParticipant(java.lang.String participantId, char[] password)
Convenience constructor for a newJPAKEParticipant
that uses theJPAKEPrimeOrderGroups.NIST_3072
prime order group, a SHA-256 digest, and a defaultSecureRandom
implementation.JPAKEParticipant(java.lang.String participantId, char[] password, JPAKEPrimeOrderGroup group)
Convenience constructor for a newJPAKEParticipant
that uses a SHA-256 digest and a defaultSecureRandom
implementation.JPAKEParticipant(java.lang.String participantId, char[] password, JPAKEPrimeOrderGroup group, Digest digest, java.security.SecureRandom random)
Construct a newJPAKEParticipant
.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description java.math.BigInteger
calculateKeyingMaterial()
Calculates and returns the key material.JPAKERound1Payload
createRound1PayloadToSend()
Creates and returns the payload to send to the other participant during round 1.JPAKERound2Payload
createRound2PayloadToSend()
Creates and returns the payload to send to the other participant during round 2.JPAKERound3Payload
createRound3PayloadToSend(java.math.BigInteger keyingMaterial)
Creates and returns the payload to send to the other participant during round 3.int
getState()
Gets the current state of this participant.void
validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)
Validates the payload received from the other participant during round 1.void
validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)
Validates the payload received from the other participant during round 2.void
validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, java.math.BigInteger keyingMaterial)
Validates the payload received from the other participant during round 3.
-
-
-
Field Detail
-
STATE_INITIALIZED
public static final int STATE_INITIALIZED
- See Also:
- Constant Field Values
-
STATE_ROUND_1_CREATED
public static final int STATE_ROUND_1_CREATED
- See Also:
- Constant Field Values
-
STATE_ROUND_1_VALIDATED
public static final int STATE_ROUND_1_VALIDATED
- See Also:
- Constant Field Values
-
STATE_ROUND_2_CREATED
public static final int STATE_ROUND_2_CREATED
- See Also:
- Constant Field Values
-
STATE_ROUND_2_VALIDATED
public static final int STATE_ROUND_2_VALIDATED
- See Also:
- Constant Field Values
-
STATE_KEY_CALCULATED
public static final int STATE_KEY_CALCULATED
- See Also:
- Constant Field Values
-
STATE_ROUND_3_CREATED
public static final int STATE_ROUND_3_CREATED
- See Also:
- Constant Field Values
-
STATE_ROUND_3_VALIDATED
public static final int STATE_ROUND_3_VALIDATED
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
JPAKEParticipant
public JPAKEParticipant(java.lang.String participantId, char[] password)
Convenience constructor for a newJPAKEParticipant
that uses theJPAKEPrimeOrderGroups.NIST_3072
prime order group, a SHA-256 digest, and a defaultSecureRandom
implementation.After construction, the
state
will beSTATE_INITIALIZED
.- Parameters:
participantId
- unique identifier of this participant. The two participants in the exchange must NOT share the same id.password
- shared secret. A defensive copy of this array is made (and cleared oncecalculateKeyingMaterial()
is called). Caller should clear the input password as soon as possible.- Throws:
java.lang.NullPointerException
- if any argument is nulljava.lang.IllegalArgumentException
- if password is empty
-
JPAKEParticipant
public JPAKEParticipant(java.lang.String participantId, char[] password, JPAKEPrimeOrderGroup group)
Convenience constructor for a newJPAKEParticipant
that uses a SHA-256 digest and a defaultSecureRandom
implementation.After construction, the
state
will beSTATE_INITIALIZED
.- Parameters:
participantId
- unique identifier of this participant. The two participants in the exchange must NOT share the same id.password
- shared secret. A defensive copy of this array is made (and cleared oncecalculateKeyingMaterial()
is called). Caller should clear the input password as soon as possible.group
- prime order group. SeeJPAKEPrimeOrderGroups
for standard groups- Throws:
java.lang.NullPointerException
- if any argument is nulljava.lang.IllegalArgumentException
- if password is empty
-
JPAKEParticipant
public JPAKEParticipant(java.lang.String participantId, char[] password, JPAKEPrimeOrderGroup group, Digest digest, java.security.SecureRandom random)
Construct a newJPAKEParticipant
.After construction, the
state
will beSTATE_INITIALIZED
.- Parameters:
participantId
- unique identifier of this participant. The two participants in the exchange must NOT share the same id.password
- shared secret. A defensive copy of this array is made (and cleared oncecalculateKeyingMaterial()
is called). Caller should clear the input password as soon as possible.group
- prime order group. SeeJPAKEPrimeOrderGroups
for standard groupsdigest
- 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 nulljava.lang.IllegalArgumentException
- if password is empty
-
-
Method Detail
-
getState
public int getState()
Gets the current state of this participant. See the STATE_* constants for possible values.
-
createRound1PayloadToSend
public JPAKERound1Payload createRound1PayloadToSend()
Creates and returns the payload to send to the other participant during round 1.After execution, the
state
will beSTATE_ROUND_1_CREATED
.
-
validateRound1PayloadReceived
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 beSTATE_ROUND_1_VALIDATED
.- Throws:
CryptoException
- if validation fails.java.lang.IllegalStateException
- if called multiple times.
-
createRound2PayloadToSend
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 beSTATE_ROUND_2_CREATED
.- Throws:
java.lang.IllegalStateException
- if called prior tovalidateRound1PayloadReceived(JPAKERound1Payload)
, or multiple times
-
validateRound2PayloadReceived
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 beSTATE_ROUND_2_VALIDATED
.- Throws:
CryptoException
- if validation fails.java.lang.IllegalStateException
- if called prior tovalidateRound1PayloadReceived(JPAKERound1Payload)
, or 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 byJPAKEParticipant
).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 beSTATE_KEY_CALCULATED
.- Throws:
java.lang.IllegalStateException
- if called prior tovalidateRound2PayloadReceived(JPAKERound2Payload)
, or if called multiple times.
-
createRound3PayloadToSend
public JPAKERound3Payload createRound3PayloadToSend(java.math.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 beSTATE_ROUND_3_CREATED
.- Parameters:
keyingMaterial
- The keying material as returned fromcalculateKeyingMaterial()
.- Throws:
java.lang.IllegalStateException
- if called prior tocalculateKeyingMaterial()
, or multiple times
-
validateRound3PayloadReceived
public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, java.math.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 beSTATE_ROUND_3_VALIDATED
.- Parameters:
round3PayloadReceived
- The round 3 payload received from the other participant.keyingMaterial
- The keying material as returned fromcalculateKeyingMaterial()
.- Throws:
CryptoException
- if validation fails.java.lang.IllegalStateException
- if called prior tocalculateKeyingMaterial()
, or multiple times
-
-