rosavox/lib/alveolata/auth/implementation-srp/functions-server.php
2025-05-23 07:33:29 +00:00

194 lines
4.5 KiB
PHP

<?php
namespace alveolata\auth;
require_once(DIR_ALVEOLATA . '/auth/implementation-srp/core.php');
/**
* @param \Closure $handler {
* function<
* tuple<
* string,
* string,
* string
* >,
* 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/*<type_number>*/(
struct_srp_subject/*<type_number>*/ $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/*<type_number>*/(
struct_srp_subject/*<type_number>*/ $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/*<type_number>*/(
struct_srp_subject/*<type_number>*/ $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'],
];
}
}
);
}