The Password-authenticated key exchange by juggling (J-PAKE) algorithm. This is J-PAKE as defined by RFC 8236, instantiated with the following parameters: - The group can be either an elliptic curve or defined over a finite field. - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the J-PAKE algorithm. - A cryptographic hash function. To select these parameters and set up the cipher suite, call these functions in any order:
psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE);
psa_pake_cs_set_primitive(cipher_suite,
PSA_PAKE_PRIMITIVE(type, family, bits));
psa_pake_cs_set_hash(cipher_suite, hash);
For more information on how to set a specific curve or field, refer to the documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. After initializing a J-PAKE operation, call
psa_pake_setup(operation, cipher_suite);
psa_pake_set_user(operation, ...);
psa_pake_set_peer(operation, ...);
psa_pake_set_password_key(operation, ...);
The password is provided as a key. This can be the password text itself, in an agreed character encoding, or some value derived from the password as required by a higher level protocol. (The implementation converts the key material to a number as described in Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here \c q is order of the group defined by the primitive set in the cipher suite. The \c psa_pake_set_password_key() function returns an error if the result of the reduction is 0.) The key exchange flow for J-PAKE is as follows: -# To get the first round data that needs to be sent to the peer, call
// Get g1
psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
// Get the ZKP public key for x1
psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
// Get the ZKP proof for x1
psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
// Get g2
psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
// Get the ZKP public key for x2
psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
// Get the ZKP proof for x2
psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
-# To provide the first round data received from the peer to the operation, call
// Set g3
psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
// Set the ZKP public key for x3
psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
// Set the ZKP proof for x3
psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
// Set g4
psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
// Set the ZKP public key for x4
psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
// Set the ZKP proof for x4
psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
-# To get the second round data that needs to be sent to the peer, call
// Get A
psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
// Get ZKP public key for x2*s
psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
// Get ZKP proof for x2*s
psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
-# To provide the second round data received from the peer to the operation, call
// Set B
psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
// Set ZKP public key for x4*s
psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
// Set ZKP proof for x4*s
psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
-# To access the shared secret call
// Get Ka=Kb=K
psa_pake_get_implicit_key()
For more information consult the documentation of the individual \c PSA_PAKE_STEP_XXX constants. At this point there is a cryptographic guarantee that only the authenticated party who used the same password is able to compute the key. But there is no guarantee that the peer is the party it claims to be and was able to do so. That is, the authentication is only implicit (the peer is not authenticated at this point, and no action should be taken that assume that they are - like for example accessing restricted files). To make the authentication explicit there are various methods, see Section 5 of RFC 8236 for two examples.