, * void * > * } procedure that shall store the data (username, salt, verifier) (e.g. by creating a new database entry) * @return \Closure { * function< * tuple< * string, * string, * type_number, * >, * void * > * } */ function srp_server_register/**/( struct_srp_subject/**/ $subject, \Closure $handler ) : \Closure { return ( function ($username, $salt, $verifier_encoded) use (&$subject, &$handler) { $handler( $username, $salt, /*($subject->toolset->encode)($verifier)*/$verifier_encoded ); return true; } ); } /** * @param \Closure $get_salt_and_verifier { * function< * tuple< * >, * record< * found:boolean, * salt:string, * verifier:string, * > * > * } * @param \Closure $state_save { * function< * tuple< * any, * >, * void * > * } * @return \Closure { * function< * tuple< * string, * string, * >, * record< * passed:boolean, * salt:string, * b_value:string, * > * > * } */ function srp_server_login_1/**/( struct_srp_subject/**/ $subject, \Closure $get_salt_and_verifier, \Closure $state_save ) : \Closure { return ( function (string $username, string $a_value_encoded) use (&$subject, &$get_salt_and_verifier, &$state_save) { $a_value = ($subject->toolset->decode)($a_value_encoded); $salt_and_verifier = $get_salt_and_verifier($username); $found = $salt_and_verifier['found']; if (! $found) { return [ 'passed' => false, 'salt' => null, 'b_value' => null, ]; } else { $salt = $salt_and_verifier['salt']; $verifier = ($subject->toolset->decode)($salt_and_verifier['verifier']); $verified_a = srp_verify_a($subject, $a_value); if (! $verified_a) { return [ 'passed' => false, 'salt' => null, 'b_value' => null, ]; } else { $computeBResult = srp_compute_b( $subject, $verifier ); $b_value = $computeBResult['b_value']; $b_exponent = $computeBResult['b_exponent']; $state_save( [ 'salt' => $salt, 'identifier' => $username, 'a_value' => ($subject->toolset->encode)($a_value), 'verifier' => ($subject->toolset->encode)($verifier), 'b_exponent' => ($subject->toolset->encode)($b_exponent), 'b_value' => ($subject->toolset->encode)($b_value), ] ); return [ 'passed' => true, 'salt' => $salt, 'b_value' => ($subject->toolset->encode)($b_value), ]; } } } ); } /** * @param \Closure $state_load { * function< * tuple< * >, * state:any * > * } * @return \Closure { * function< * tuple< * type_number * >, * record< * passed:boolean, * m2_server:type_number, * > * > * } */ function srp_server_login_2/**/( struct_srp_subject/**/ $subject, \Closure $state_load ) : \Closure { return ( function (string $m1_client) use (&$subject, &$state_load) { $state = $state_load(); $salt = $state['salt']; $a_value = ($subject->toolset->decode)($state['a_value']); $b_exponent = ($subject->toolset->decode)($state['b_exponent']); $b_value = ($subject->toolset->decode)($state['b_value']); $verifier = ($subject->toolset->decode)($state['verifier']); $identifier = $state['identifier']; $compute_k_server_result = srp_compute_k_server($subject, $a_value, $b_exponent, $b_value, $verifier); $k_server = $compute_k_server_result['k_server']; $compute_m1_server_result = srp_compute_m1_server($subject, $salt, $a_value, $b_value, $identifier, $k_server); $m1_server = $compute_m1_server_result['m1_server']; if (! ($m1_client === $m1_server)) { return [ 'passed' => false, 'm2_server' => null, ]; } else { $compute_m2_server_result = srp_compute_m2_server($subject, $a_value, $m1_server, $k_server); return [ 'passed' => true, 'm2_server' => $compute_m2_server_result['m2_server'], ]; } } ); }