880 lines
18 KiB
PHP
880 lines
18 KiB
PHP
<?php
|
|
|
|
declare(strict_types = 1);
|
|
|
|
namespace alveolata\auth;
|
|
|
|
// require_once('vendor/autoload.php');
|
|
require_once(DIR_ALVEOLATA . '/math/functions.php');
|
|
|
|
|
|
/**
|
|
* @template type_number
|
|
* @author Christian Fraß <frass@greenscale.de>
|
|
*/
|
|
class struct_srp_toolset/*<type_number>*/
|
|
{
|
|
|
|
/**
|
|
* @var function<tuple<type_number>,string>
|
|
*/
|
|
public $encode;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<string>,type_number>
|
|
*/
|
|
public $decode;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<int,string>,type_number>
|
|
*/
|
|
public $make;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<>,type_number>
|
|
*/
|
|
public $zero;
|
|
|
|
|
|
/**
|
|
* @todo check if really needed
|
|
* @var function<tuple<>,type_number>
|
|
*/
|
|
public $one;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number>,string>
|
|
*/
|
|
public $to_string;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number,type_number>,boolean>
|
|
*/
|
|
public $equal;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number,type_number>,type_number>
|
|
*/
|
|
public $add;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number,type_number>,type_number>
|
|
*/
|
|
public $subtract;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number,type_number>,type_number>
|
|
*/
|
|
public $multiply;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number,type_number>,type_number>
|
|
*/
|
|
public $xor;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number,type_number>,type_number>
|
|
*/
|
|
public $mod;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<type_number,type_number,type_number>,type_number>
|
|
*/
|
|
public $modpow;
|
|
|
|
|
|
/**
|
|
* @var function<list<string>,string>
|
|
*/
|
|
public $join;
|
|
|
|
|
|
/**
|
|
* @var function<>
|
|
*/
|
|
public $compute_hash;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<string,string>,string>
|
|
*/
|
|
public $compute_password_hash;
|
|
|
|
|
|
/**
|
|
* @var function<tuple<>,type_number>
|
|
*/
|
|
public $compute_random;
|
|
|
|
|
|
/**
|
|
* @param array $tools {
|
|
* record<
|
|
* encode:function<tuple<type_number>,string>,
|
|
* decode:function<tuple<string>,type_number>,
|
|
* make:function<tuple<int,string>,type_number>,
|
|
* zero:function<tuple<>,type_number>,
|
|
* one:function<tuple<>,type_number>,
|
|
* to_string:function<tuple<type_number>,string>,
|
|
* equal:function<tuple<type_number,type_number>,boolean>,
|
|
* add:function<tuple<type_number,type_number>,type_number>,
|
|
* subtract:function<tuple<type_number,type_number>,type_number>,
|
|
* multiply:function<tuple<type_number,type_number>,type_number>,
|
|
* xor:function<tuple<type_number,type_number>,type_number>,
|
|
* mod:function<tuple<type_number,type_number>,type_number>,
|
|
* modpow:function<tuple<type_number,type_number,type_number>,type_number>,
|
|
* join:function<list<string>,string>,
|
|
* compute_hash:function<>,
|
|
* compute_password_hash:function<tuple<string,string>,string>,
|
|
* compute_random:function<tuple<>,type_number>,
|
|
* >
|
|
* }
|
|
*/
|
|
public function __construct(
|
|
array $tools
|
|
)
|
|
{
|
|
$this->encode = $tools['encode'];
|
|
$this->decode = $tools['decode'];
|
|
$this->make = $tools['make'];
|
|
$this->zero = $tools['zero'];
|
|
$this->one = $tools['one'];
|
|
$this->to_string = $tools['to_string'];
|
|
$this->equal = $tools['equal'];
|
|
$this->add = $tools['add'];
|
|
$this->subtract = $tools['subtract'];
|
|
$this->multiply = $tools['multiply'];
|
|
$this->xor = $tools['xor'];
|
|
$this->mod = $tools['mod'];
|
|
$this->modpow = $tools['modpow'];
|
|
$this->join = $tools['join'];
|
|
$this->compute_hash = $tools['compute_hash'];
|
|
$this->compute_password_hash = $tools['compute_password_hash'];
|
|
$this->compute_random = $tools['compute_random'];
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @author Christian Fraß <frass@greenscale.de>
|
|
*/
|
|
function _srp_toolset_simple(
|
|
) : struct_srp_toolset/*<int>*/
|
|
{
|
|
return (new struct_srp_toolset/*<int>*/(
|
|
[
|
|
'encode' => (fn($number) => \sprintf('%X', $number)),
|
|
'decode' => (fn($string) => \intval($string, 16)),
|
|
'make' => (fn($base, $digits) => \intval($digits, $base)),
|
|
'zero' => (fn() => 0),
|
|
'one' => (fn() => 1),
|
|
'to_string' => (fn($number) => \sprintf('%X', $number)),
|
|
'equal' => (fn($x, $y) => ($x === $y)),
|
|
'add' => (fn($x, $y) => ($x + $y)),
|
|
'subtract' => (fn($x, $y) => ($x - $y)),
|
|
'multiply' => (fn($x, $y) => ($x * $y)),
|
|
'xor' => (fn($x, $y) => ($x ^ $y)),
|
|
// 'mod' => (fn($x, $y) => ($x % $y)),
|
|
'mod' => (fn($x, $y) => \alveolata\math\mod($x, $y)),
|
|
// 'modpow' => (fn($base, $exponent, $modulus) => (($base ** $exponent) % $modulus)),
|
|
'modpow' => (fn($base, $exponent, $modulus) => \alveolata\math\modpow($base, $exponent, $modulus)),
|
|
'join' => (fn($parts) => \implode('', $parts)),
|
|
'compute_hash' => (fn($string) => $string),
|
|
'compute_password_hash' => (fn($salt, $password) => \sprintf(
|
|
'%04X',
|
|
\alveolata\list_\reduce(
|
|
\alveolata\list_\map(
|
|
\str_split($password . $salt),
|
|
(fn($character) => \ord($character))
|
|
),
|
|
0,
|
|
(fn($x, $y) => (($x + $y) & 0xFFFF))
|
|
)
|
|
)),
|
|
'compute_random' => (fn() => \rand(1, 7)),
|
|
]
|
|
));
|
|
}
|
|
|
|
|
|
/**
|
|
* requires composer package phpseclib/phpseclib
|
|
*
|
|
* @see https://api.phpseclib.com/master/phpseclib3/Math/BigInteger.html
|
|
* @author Christian Fraß <frass@greenscale.de>
|
|
*/
|
|
function _srp_toolset_biginteger(
|
|
) : struct_srp_toolset/*<\phpseclib3\Math\BigInteger>*/
|
|
{
|
|
return (new struct_srp_toolset/*<\phpseclib3\Math\BigInteger>*/(
|
|
[
|
|
'encode' => (fn($number) => $number->toHex()),
|
|
'decode' => (fn($string) => (new \phpseclib3\Math\BigInteger($string, 16))),
|
|
'make' => (fn($base, $digits) => (new \phpseclib3\Math\BigInteger($digits, $base))),
|
|
'zero' => (fn() => (new \phpseclib3\Math\BigInteger('0', 16))),
|
|
'one' => (fn() => (new \phpseclib3\Math\BigInteger('1', 16))),
|
|
'to_string' => (fn($number) => $number->toHex()),
|
|
'equal' => (fn($x, $y) => $x->equals($y)),
|
|
'add' => (fn($x, $y) => $x->add($y)),
|
|
'subtract' => (fn($x, $y) => $x->subtract($y)),
|
|
'multiply' => (fn($x, $y) => $x->multiply($y)),
|
|
'xor' => (fn($x, $y) => $x->bitwise_xor($y)),
|
|
'mod' => (fn($x, $y) => $x->modPow(new \phpseclib3\Math\BigInteger('1', 16), $y)),
|
|
'modpow' => (fn($base, $exponent, $modulus) => $base->modPow($exponent, $modulus)),
|
|
'join' => (fn($parts) => \implode('', $parts)),
|
|
'compute_hash' => (fn($string) => $string),
|
|
/*
|
|
'compute_password_hash' => (fn($salt, $password) => \Vinsaj9\Crypto\Scrypt\scrypt(
|
|
$password,
|
|
$salt,
|
|
16384, // TODO: wadd is dadd?
|
|
8, // TODO: wadd is dadd?
|
|
1, // TODO: wadd is dadd?
|
|
64 // TODO: wadd is dadd?
|
|
)),
|
|
*/
|
|
/*
|
|
'compute_password_hash' => (fn($salt, $password) => \password_hash(
|
|
$password,
|
|
\PASSWORD_BCRYPT,
|
|
[
|
|
'salt' => $salt,
|
|
]
|
|
)),
|
|
*/
|
|
'compute_password_hash' => (fn($salt, $password) => \hash(
|
|
'sha256',
|
|
($password . $salt)
|
|
)),
|
|
'compute_random' => (fn() => \phpseclib3\Math\BigInteger::random(24)),
|
|
]
|
|
));
|
|
}
|
|
|
|
|
|
/**
|
|
* @author Christian Fraß <frass@greenscale.de>
|
|
*/
|
|
class struct_srp_subject/*<type_number>*/
|
|
{
|
|
|
|
/**
|
|
* @var struct_srp_toolset<type_number>
|
|
*/
|
|
public $toolset;
|
|
|
|
|
|
/**
|
|
* @var type_number
|
|
*/
|
|
public $base;
|
|
|
|
|
|
/**
|
|
* @var type_number
|
|
*/
|
|
public $modulus;
|
|
|
|
|
|
/**
|
|
*/
|
|
public function __construct(
|
|
struct_srp_toolset/*<type_number>*/ $toolset,
|
|
/*type_number */$base,
|
|
/*type_number */$modulus
|
|
)
|
|
{
|
|
$this->toolset = $toolset;
|
|
$this->base = $base;
|
|
$this->modulus = $modulus;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
function srp_subject_make/*<type_number>*/(
|
|
struct_srp_toolset/*<type_number>*/ $toolset,
|
|
/*type_number */$base,
|
|
/*type_number */$modulus
|
|
)
|
|
{
|
|
return (
|
|
new struct_srp_subject(
|
|
$toolset,
|
|
$base,
|
|
$modulus
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* @return struct_srp_subject<int>
|
|
*/
|
|
function srp_subject_test(
|
|
) : struct_srp_subject/*<int>*/
|
|
{
|
|
$toolset = _srp_toolset_simple();
|
|
// <2>_19 = {2,4,8,16,13,7,14,9,18,17,15,11,3,6,12,5,10,1}
|
|
return (new struct_srp_subject/*<int>*/(
|
|
$toolset,
|
|
($toolset->decode)('2'),
|
|
($toolset->decode)('1323') // wollte eigentlich 19 nehmen, aber das ist zu klein :/
|
|
));
|
|
}
|
|
|
|
|
|
/**
|
|
* sind die Werte, die bytegod immer nimmt
|
|
* requires composer package phpseclib/phpseclib
|
|
*
|
|
* @return struct_srp_subject<\phpseclib3\Math\BigInteger>
|
|
*/
|
|
function srp_subject_biginteger_1(
|
|
) : struct_srp_subject/*<\phpseclib3\Math\BigInteger>*/
|
|
{
|
|
$toolset = _srp_toolset_biginteger();
|
|
return (new struct_srp_subject/*<\phpseclib3\Math\BigInteger>*/(
|
|
$toolset,
|
|
($toolset->decode)('2'),
|
|
($toolset->decode)('AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73')
|
|
));
|
|
}
|
|
|
|
|
|
/**
|
|
* @author Christian Fraß <frass@greenscale.de>
|
|
*/
|
|
class _state
|
|
{
|
|
public static $subject_default = null;
|
|
}
|
|
|
|
|
|
/**
|
|
* @author Christian Fraß <frass@greenscale.de>
|
|
*/
|
|
function srp_set_default_subject(
|
|
\Closure $factory
|
|
) : void
|
|
{
|
|
_state::$subject_default = $factory;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return struct_srp_subject<any>
|
|
* @author Christian Fraß <frass@greenscale.de>
|
|
*/
|
|
function srp_subject_default(
|
|
) : struct_srp_subject
|
|
{
|
|
if (_state::$subject_default === null) {
|
|
srp_set_default_subject(fn() => srp_subject_biginteger_1());
|
|
}
|
|
return (_state::$subject_default)();
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $salt
|
|
* @param string $password
|
|
* @return array {
|
|
* record<
|
|
* x:type_number,
|
|
* v:type_number
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_verifier/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
string $salt,
|
|
string $password
|
|
) : array
|
|
{
|
|
$x = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_password_hash)($salt, $password)
|
|
);
|
|
// g^x
|
|
$verifier = ($subject->toolset->modpow)(
|
|
$subject->base,
|
|
$x,
|
|
$subject->modulus
|
|
);
|
|
return [
|
|
'x' => $x,
|
|
'verifier' => ($verifier),
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* compute A
|
|
*
|
|
* @return array {
|
|
* record<
|
|
* k:type_number,
|
|
* a_exponent:type_number,
|
|
* a_value:type_number
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_a/*<type_number>*/(
|
|
struct_srp_subject $subject
|
|
) : array
|
|
{
|
|
// set asymmetry factor
|
|
$k = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
($subject->toolset->join)([
|
|
($subject->toolset->to_string)($subject->modulus),
|
|
($subject->toolset->to_string)($subject->base),
|
|
])
|
|
)
|
|
);
|
|
// compute random until it fits requirements by specification
|
|
while (true) {
|
|
$a_exponent = ($subject->toolset->compute_random)();
|
|
// g^a % N
|
|
$a_value = ($subject->toolset->modpow)($subject->base, $a_exponent, $subject->modulus);
|
|
// (g^a % N) % N == 0
|
|
// if (! ($subject->toolset->equal)(($subject->toolset->mod)($a_value, $subject->modulus), ($subject->toolset->zero)())) {
|
|
if (! ($subject->toolset->equal)($a_value, ($subject->toolset->zero)())) {
|
|
break;
|
|
}
|
|
}
|
|
return [
|
|
'k' => $k,
|
|
'a_exponent' => $a_exponent,
|
|
'a_value' => $a_value,
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* compute B
|
|
*
|
|
* @param type_number $verifier
|
|
* @return array {
|
|
* record<
|
|
* k:type_number,
|
|
* b_exponent:type_number,
|
|
* b_value:type_number
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_b/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*<type_number>*/ $verifier
|
|
) : array
|
|
{
|
|
// asymmetry factor
|
|
$k = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
($subject->toolset->join)([
|
|
($subject->toolset->to_string)($subject->modulus),
|
|
($subject->toolset->to_string)($subject->base),
|
|
])
|
|
)
|
|
);
|
|
$b_exponent = ($subject->toolset->compute_random)();
|
|
// k*v
|
|
$Bl = ($subject->toolset->multiply)($k, $verifier);
|
|
// g^b
|
|
$Br = ($subject->toolset->modpow)($subject->base, $b_exponent, $subject->modulus);
|
|
// k*v + g^b
|
|
$Bn = ($subject->toolset->add)($Bl, $Br);
|
|
// (k*v + g^b) % N
|
|
$b_value = ($subject->toolset->mod)($Bn, $subject->modulus);
|
|
return [
|
|
'k' => $k,
|
|
'b_exponent' => $b_exponent,
|
|
'b_value' => $b_value,
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* k_client:string
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_k_client/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$a_exponent,
|
|
/*type_number */$a_value,
|
|
/*type_number */$b_value,
|
|
/*type_number */$x,
|
|
/*type_number */$k
|
|
) : array
|
|
{
|
|
$u = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
($subject->toolset->join)([
|
|
($subject->toolset->to_string)($a_value),
|
|
($subject->toolset->to_string)($b_value),
|
|
])
|
|
)
|
|
);
|
|
// B - k*g^x
|
|
$Sl = ($subject->toolset->subtract)(
|
|
$b_value,
|
|
($subject->toolset->multiply)(
|
|
$k,
|
|
($subject->toolset->modpow)(
|
|
$subject->base,
|
|
$x,
|
|
$subject->modulus
|
|
)
|
|
)
|
|
);
|
|
// a + u*x
|
|
$Sr = ($subject->toolset->add)(
|
|
$a_exponent,
|
|
($subject->toolset->multiply)(
|
|
$u,
|
|
$x
|
|
)
|
|
);
|
|
// (B - k*g^x) ^ (a + u*x)
|
|
$S = ($subject->toolset->modpow)(
|
|
$Sl,
|
|
$Sr,
|
|
$subject->modulus
|
|
);
|
|
$k_client = ($subject->toolset->compute_hash)(($subject->toolset->to_string)($S));
|
|
return [
|
|
'k_client' => $k_client,
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* k_server:string
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_k_server/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$a_value,
|
|
/*type_number */$b_exponent,
|
|
/*type_number */$b_value,
|
|
/*type_number */$verifier
|
|
) : array
|
|
{
|
|
$u = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
($subject->toolset->join)([
|
|
($subject->toolset->to_string)($a_value),
|
|
($subject->toolset->to_string)($b_value),
|
|
])
|
|
)
|
|
);
|
|
// A*v^u
|
|
$Sl = ($subject->toolset->multiply)(
|
|
$a_value,
|
|
($subject->toolset->modpow)(
|
|
$verifier,
|
|
$u,
|
|
$subject->modulus
|
|
)
|
|
);
|
|
// (A*v^u)^b
|
|
$S = ($subject->toolset->modpow)(
|
|
$Sl,
|
|
$b_exponent,
|
|
$subject->modulus
|
|
);
|
|
$k_server = ($subject->toolset->compute_hash)(($subject->toolset->to_string)($S));
|
|
return [
|
|
'k_server' => $k_server,
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* m1:string
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_m1_generic/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
string $s,
|
|
/*type_number */$a_value,
|
|
/*type_number */$b_value,
|
|
string $identifier,
|
|
string $k
|
|
) : array
|
|
{
|
|
$HN = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
($subject->toolset->to_string)($subject->modulus)
|
|
)
|
|
);
|
|
$Hg = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
($subject->toolset->to_string)($subject->base)
|
|
)
|
|
);
|
|
$HI = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
$identifier
|
|
)
|
|
);
|
|
// H(H(N) XOR H(g), H(I), s, A, B, k)
|
|
$m1 = ($subject->toolset->compute_hash)(
|
|
($subject->toolset->join)([
|
|
($subject->toolset->to_string)(($subject->toolset->xor)($HN, $Hg)),
|
|
($subject->toolset->to_string)($HI),
|
|
$s,
|
|
($subject->toolset->to_string)($a_value),
|
|
($subject->toolset->to_string)($b_value),
|
|
$k,
|
|
])
|
|
) ;
|
|
return [
|
|
'm1' => $m1,
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* m1_client:string,
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_m1_client/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
string $s,
|
|
/*type_number */$a_value,
|
|
/*type_number */$b_value,
|
|
string $identifier,
|
|
string $k_client
|
|
) : array
|
|
{
|
|
return ['m1_client' => srp_compute_m1_generic(
|
|
$subject,
|
|
$s,
|
|
$a_value,
|
|
$b_value,
|
|
$identifier,
|
|
$k_client
|
|
)['m1']];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* m1_server:string
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_m1_server/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
string $s,
|
|
/*type_number */$a_value,
|
|
/*type_number */$b_value,
|
|
string $identifier,
|
|
string $k_server
|
|
) : array
|
|
{
|
|
return ['m1_server' => srp_compute_m1_generic(
|
|
$subject,
|
|
$s,
|
|
$a_value,
|
|
$b_value,
|
|
$identifier,
|
|
$k_server
|
|
)['m1']];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* M2:string
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_m2_generic/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$a_value,
|
|
string $m1,
|
|
string $k
|
|
) : array
|
|
{
|
|
$M2 = ($subject->toolset->compute_hash)(
|
|
($subject->toolset->join)([
|
|
($subject->toolset->to_string)($a_value),
|
|
$m1,
|
|
$k,
|
|
])
|
|
);
|
|
return [
|
|
'M2' => $M2,
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* m2_client:string
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_m2_client/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$a_value,
|
|
string $m1_client,
|
|
string $k_client
|
|
) : array
|
|
{
|
|
return ['m2_client' => srp_compute_m2_generic(
|
|
$subject,
|
|
$a_value,
|
|
$m1_client,
|
|
$k_client
|
|
)['M2']];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return array {
|
|
* record<
|
|
* m2_server:string
|
|
* >
|
|
* }
|
|
*/
|
|
function srp_compute_m2_server/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$a_value,
|
|
string $m1_server,
|
|
string $k_server
|
|
) : array
|
|
{
|
|
return ['m2_server' => srp_compute_m2_generic(
|
|
$subject,
|
|
$a_value,
|
|
$m1_server,
|
|
$k_server
|
|
)['M2']];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return boolean
|
|
*/
|
|
function srp_verify_a/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$a_value
|
|
) : bool
|
|
{
|
|
if (! ($subject->toolset->equal)($a_value, ($subject->toolset->zero)())) {
|
|
if (! ($subject->toolset->equal)(($subject->toolset->mod)($a_value, $subject->modulus), ($subject->toolset->zero)())) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @return boolean
|
|
*/
|
|
function srp_verify_b/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$b_value
|
|
) : bool
|
|
{
|
|
if (! ($subject->toolset->equal)($b_value, ($subject->toolset->zero)())) {
|
|
if (! ($subject->toolset->equal)(($subject->toolset->mod)($b_value, $subject->modulus), ($subject->toolset->zero)())) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @return boolean
|
|
*/
|
|
function srp_verify_hab/*<type_number>*/(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
/*type_number */$a_value,
|
|
/*type_number */$b_value
|
|
) : bool
|
|
{
|
|
$u = ($subject->toolset->decode)(
|
|
($subject->toolset->compute_hash)(
|
|
($subject->toolset->join)([
|
|
($subject->toolset->to_string)($a_value),
|
|
($subject->toolset->to_string)($b_value),
|
|
])
|
|
)
|
|
);
|
|
if (! ($subject->toolset->equal)($u, ($subject->toolset->zero)())) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @return boolean
|
|
*/
|
|
function srp_verify_k(
|
|
struct_srp_subject/*<type_number>*/ $subject,
|
|
string $k_client,
|
|
string $k_server
|
|
) : bool
|
|
{
|
|
if (($k_client != null) && ($k_server != null)) {
|
|
if ($k_client === $k_server) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
?>
|