102 lines
2.6 KiB
PHP
102 lines
2.6 KiB
PHP
|
<?php
|
||
|
// CSRFPToken.php
|
||
|
// Created: 2021-06-11
|
||
|
// Updated: 2022-02-27
|
||
|
|
||
|
namespace Index\Security;
|
||
|
|
||
|
use ErrorException;
|
||
|
use InvalidArgumentException;
|
||
|
use Stringable;
|
||
|
use Index\Serialisation\Serialiser;
|
||
|
|
||
|
/**
|
||
|
* Represents a CSRF prevention token.
|
||
|
*/
|
||
|
class CSRFPToken implements Stringable {
|
||
|
private int $timestamp;
|
||
|
private int $tolerance;
|
||
|
private string $hash;
|
||
|
|
||
|
/**
|
||
|
* Construct a CSRFPToken instance.
|
||
|
*
|
||
|
* @param int $timestamp Timestamp at which the token was generated.
|
||
|
* @param int $tolerance Period for how long this token is valid.
|
||
|
* @param string $hash A HMAC hash to prevent tampering.
|
||
|
* @return CSRFPToken A new instance of CSRFPToken.
|
||
|
*/
|
||
|
public function __construct(
|
||
|
int $timestamp,
|
||
|
int $tolerance,
|
||
|
string $hash
|
||
|
) {
|
||
|
$this->timestamp = $timestamp;
|
||
|
$this->tolerance = $tolerance;
|
||
|
$this->hash = $hash;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the timestamp value of this token.
|
||
|
*
|
||
|
* @return int Timestamp for this token.
|
||
|
*/
|
||
|
public function getTimestamp(): int {
|
||
|
return $this->timestamp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the tolerance value of this token.
|
||
|
*
|
||
|
* @return int Tolerance for this token.
|
||
|
*/
|
||
|
public function getTolerance(): int {
|
||
|
return $this->tolerance;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the hash of this token.
|
||
|
*
|
||
|
* @return string Hash for this token.
|
||
|
*/
|
||
|
public function getHash(): string {
|
||
|
return $this->hash;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Encodes the CSRFPToken instance as a token string.
|
||
|
*
|
||
|
* @return string CSRF prevention token string.
|
||
|
*/
|
||
|
public function encode(): string {
|
||
|
return Serialiser::uriBase64()->serialise(pack('Vv', $this->timestamp, $this->tolerance) . $this->hash);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Decodes a token string to a CSRFPToken instance.
|
||
|
*
|
||
|
* If an invalid token is provided, no exception will be thrown.
|
||
|
*
|
||
|
* @param string $token Input token string.
|
||
|
* @return CSRFPToken Instance representing the provided token.
|
||
|
*/
|
||
|
public static function decode(string $token): CSRFPToken {
|
||
|
$token = Serialiser::uriBase64()->deserialise($token);
|
||
|
try {
|
||
|
$decode = unpack('Vtimestamp/vtolerance', $token);
|
||
|
} catch(ErrorException $ex) {
|
||
|
$decode = [
|
||
|
'timestamp' => -1,
|
||
|
'tolerance' => 0,
|
||
|
];
|
||
|
}
|
||
|
// arbitrary length
|
||
|
$hash = substr($token, 6, 128);
|
||
|
return new CSRFPToken($decode['timestamp'], $decode['tolerance'], $hash);
|
||
|
}
|
||
|
|
||
|
public function __toString(): string {
|
||
|
return $this->encode();
|
||
|
}
|
||
|
}
|