|
|
|
@ -1,7 +1,8 @@
|
|
|
|
<?php
|
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
|
|
namespace BradyMcD\TAATP\URI;
|
|
|
|
namespace BradyMcD\TAATP\URI;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use InvalidArgumentException;
|
|
|
|
|
|
|
|
|
|
|
|
class Otpauth
|
|
|
|
class Otpauth
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -15,17 +16,17 @@ class Otpauth
|
|
|
|
)
|
|
|
|
)
|
|
|
|
{}
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
public static function from_string(string $uri): self
|
|
|
|
public static function fromString(string $uri): self
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// This is definitely from writing Scheme.
|
|
|
|
// This is definitely from writing Scheme.
|
|
|
|
$run_check = function(array $check_array, $target)
|
|
|
|
$runCheck = function(array $checkArray, $target)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
foreach($check_array as $c)
|
|
|
|
foreach($checkArray as $c)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
!($c[0]($target))? :throw new \InvalidArgumentException($c[1]);
|
|
|
|
!($c[0]($target))? :throw new InvalidArgumentException($c[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$uri_checks = [
|
|
|
|
$uriChecks = [
|
|
|
|
[ function($arr)
|
|
|
|
[ function($arr)
|
|
|
|
{ return $arr !== false; },
|
|
|
|
{ return $arr !== false; },
|
|
|
|
$uri . " is not a valid URI."],
|
|
|
|
$uri . " is not a valid URI."],
|
|
|
|
@ -40,32 +41,32 @@ class Otpauth
|
|
|
|
$uri . " lacks query information."]
|
|
|
|
$uri . " lacks query information."]
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$parsed_uri = \parse_url($uri);
|
|
|
|
$parsedUri = \parse_url($uri);
|
|
|
|
$run_check($uri_checks, $parsed_uri)
|
|
|
|
$runCheck($uriChecks, $parsedUri);
|
|
|
|
|
|
|
|
|
|
|
|
$query_checks = [
|
|
|
|
$queryChecks = [
|
|
|
|
[ function($que)
|
|
|
|
[ function($que)
|
|
|
|
{ return \array_key_exists('issuer', $que);},
|
|
|
|
{ return \array_key_exists('issuer', $que);},
|
|
|
|
$parsed_uri['query'] . " has no issuer information."],
|
|
|
|
$parsedUri['query'] . " has no issuer information."],
|
|
|
|
[ function($que)
|
|
|
|
[ function($que)
|
|
|
|
{ return \array_key_exists('secret', $que);},
|
|
|
|
{ return \array_key_exists('secret', $que);},
|
|
|
|
$parsed_uri['query'] . "has no secret key."]
|
|
|
|
$parsedUri['query'] . "has no secret key."]
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$parsed_query = [];
|
|
|
|
$parsedQuery = [];
|
|
|
|
\parse_str($parsed['query'], $parsed_query);
|
|
|
|
\parse_str($parsedUri['query'], $parsedQuery);
|
|
|
|
$run_check($query_checks, $parsed_query);
|
|
|
|
$runCheck($queryChecks, $parsedQuery);
|
|
|
|
|
|
|
|
|
|
|
|
$label_checks = [
|
|
|
|
$labelChecks = [
|
|
|
|
[ function($lab)
|
|
|
|
[ function($lab)
|
|
|
|
{ return \count($lab) === 2;},
|
|
|
|
{ return \count($lab) === 2;},
|
|
|
|
$parsed_uri['path'] . " doesn't have the correct number of components."]
|
|
|
|
$parsedUri['path'] . " doesn't have the correct number of components."]
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
$label = \explode(":", $parsed['path']);
|
|
|
|
$label = \explode(":", $parsedUri['path']);
|
|
|
|
$run_check($label_checks, $label);
|
|
|
|
$runCheck($labelChecks, $label);
|
|
|
|
|
|
|
|
|
|
|
|
$apply_defaults = function(array &$arr, array $defaults) {
|
|
|
|
$applyDefaults = function(array &$arr, array $defaults) {
|
|
|
|
foreach($defaults as $k => $v)
|
|
|
|
foreach($defaults as $k => $v)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(\array_key_exists($k, $arr))
|
|
|
|
if(\array_key_exists($k, $arr))
|
|
|
|
@ -73,44 +74,28 @@ class Otpauth
|
|
|
|
$arr[$k] = $v;
|
|
|
|
$arr[$k] = $v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$query_defaults = [
|
|
|
|
$queryDefaults = [
|
|
|
|
"algorithm" => "SHA1",
|
|
|
|
"algorithm" => "SHA1",
|
|
|
|
"period" => 30,
|
|
|
|
"period" => 30,
|
|
|
|
"digits" => 6,
|
|
|
|
"digits" => 6,
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
$applyDefaults($queryDefaults, $parsedQuery);
|
|
|
|
$apply_defaults($query_defaults, $parsed_query)
|
|
|
|
|
|
|
|
// END SCHEMEING
|
|
|
|
// END SCHEMEING
|
|
|
|
\ltrim($label[0], "/") !== $parsed_query['issuer']
|
|
|
|
|
|
|
|
|| throw new \InvalidArgumentException($uri . " has mismatching issuer information.");
|
|
|
|
\ltrim($label[0], "/") !== $parsedQuery['issuer']
|
|
|
|
|
|
|
|
|| throw new InvalidArgumentException($uri . " has mismatching issuer information.");
|
|
|
|
|
|
|
|
|
|
|
|
return self(
|
|
|
|
return self(
|
|
|
|
$parsed_query['issuer'],
|
|
|
|
$parsedQuery['issuer'],
|
|
|
|
$label[1],
|
|
|
|
$label[1],
|
|
|
|
$parsed_query['secret'],
|
|
|
|
$parsedQuery['secret'],
|
|
|
|
$parsed_query['algorithm'],
|
|
|
|
$parsedQuery['algorithm'],
|
|
|
|
$parsed_query['period'],
|
|
|
|
$parsedQuery['period'],
|
|
|
|
$parsed_query['digits']
|
|
|
|
$parsedQuery['digits']
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function from_string(string $uri): self
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
$parsed = self._pre($uri);
|
|
|
|
|
|
|
|
$parsed_uri = $parsed[0];
|
|
|
|
|
|
|
|
$parsed_query = $parsed[1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$label = \explode(":", $parsed_uri['path']);
|
|
|
|
|
|
|
|
$issuer = \ltrim($label[0], "/");
|
|
|
|
|
|
|
|
$user = $label[1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$secret = $query['secret'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\array_key_exists('algorithm', $query) ? $algo = $query['algorithm'] : $algo = null;
|
|
|
|
|
|
|
|
return new self($issuer, $user, $secret, $algo);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function emitStr(): string
|
|
|
|
public function emitStr(): string
|
|
|
|
{
|
|
|
|
{
|
|
|
|
$label = $this->provider . ":" . $this->userid;
|
|
|
|
$label = $this->provider . ":" . $this->userid;
|
|
|
|
@ -119,9 +104,9 @@ class Otpauth
|
|
|
|
$digits = "digits=" . $this->digits;
|
|
|
|
$digits = "digits=" . $this->digits;
|
|
|
|
$period = "period=" . $this->period;
|
|
|
|
$period = "period=" . $this->period;
|
|
|
|
$secret = "secret=" . $this->secret;
|
|
|
|
$secret = "secret=" . $this->secret;
|
|
|
|
$query = \implode("&", [$secret, $provider, $period, $digits])
|
|
|
|
$query = \implode("&", [$secret, $provider, $period, $digits, $algo]);
|
|
|
|
|
|
|
|
|
|
|
|
return "otpauth://totp/" $label . "?" . $query;
|
|
|
|
return "otpauth://totp/" . $label . "?" . $query;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|