194 lines
4.5 KiB
PHP
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'],
|
|
];
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|