105 lines
3.1 KiB
PHP
105 lines
3.1 KiB
PHP
|
<?php
|
||
|
// CSRFP.php
|
||
|
// Created: 2021-06-11
|
||
|
// Updated: 2022-02-27
|
||
|
|
||
|
namespace Index\Security;
|
||
|
|
||
|
/**
|
||
|
* Contains info shared between sessions as well as shorthand methods.
|
||
|
*/
|
||
|
class CSRFP {
|
||
|
private const TOLERANCE = 30 * 60;
|
||
|
private const EPOCH = 1619956800;
|
||
|
private const HASH_ALGO = 'sha1';
|
||
|
|
||
|
private string $secretKey;
|
||
|
private int $tolerance;
|
||
|
private int $epoch;
|
||
|
private string $hashAlgo;
|
||
|
|
||
|
private array $identities = [];
|
||
|
|
||
|
/**
|
||
|
* Creates a new CSRFP instance.
|
||
|
*
|
||
|
* @param string $secretKey Secret key for HMAC hashes.
|
||
|
* @param int $tolerance Amount of time a token should remain valid for.
|
||
|
* @param int $epoch First possible date and time.
|
||
|
* @param string $hashAlgo Hashing algorithm to use for HMAC.
|
||
|
* @return CSRFP New CSRFP instance.
|
||
|
*/
|
||
|
public function __construct(
|
||
|
string $secretKey,
|
||
|
int $tolerance = self::TOLERANCE,
|
||
|
int $epoch = self::EPOCH,
|
||
|
string $hashAlgo = self::HASH_ALGO
|
||
|
) {
|
||
|
$this->secretKey = $secretKey;
|
||
|
$this->tolerance = $tolerance;
|
||
|
$this->epoch = $epoch;
|
||
|
$this->hashAlgo = $hashAlgo;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the amount of time a token should remain valid for.
|
||
|
*
|
||
|
* @return int Token expiry tolerance.
|
||
|
*/
|
||
|
public function getTolerance(): int {
|
||
|
return $this->tolerance;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets an identity instance.
|
||
|
*
|
||
|
* @param string $identity String that represents the identity.
|
||
|
* @return CSRFPIdentity An identity instance representing the given string.
|
||
|
*/
|
||
|
public function getIdentity(string $identity): CSRFPIdentity {
|
||
|
return $this->identities[$identity] ?? ($this->identities[$identity] = new CSRFPIdentity($this, $identity));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the time with the offset applied.
|
||
|
*
|
||
|
* @return int Current time, with offset.
|
||
|
*/
|
||
|
public function time(): int {
|
||
|
return time() - $this->epoch;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a hash with the given arguments.
|
||
|
*
|
||
|
* @param string $identity Identity string to verify for.
|
||
|
* @param int $timestamp Timestamp to verify.
|
||
|
* @param int $tolerance Tolerance to verify.
|
||
|
* @return string Hash representing the given arguments.
|
||
|
*/
|
||
|
public function createHash(string $identity, int $timestamp, int $tolerance): string {
|
||
|
return hash_hmac($this->hashAlgo, "{$identity}!{$timestamp}!{$tolerance}", $this->secretKey, true);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a token string using a given identity string.
|
||
|
*
|
||
|
* @param string $identity Identity to create token for.
|
||
|
* @return string Token string.
|
||
|
*/
|
||
|
public function createToken(string $identity): string {
|
||
|
return $this->getIdentity($identity)->createToken();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Verifies a token string using a given identity string.
|
||
|
*
|
||
|
* @param string $identity Identity to test the token with.
|
||
|
* @param string $token Token to test.
|
||
|
* @return bool true if the token is valid, false if not.
|
||
|
*/
|
||
|
public function verifyToken(string $identity, string $token): bool {
|
||
|
return $this->getIdentity($identity)->verifyToken(CSRFPToken::decode($token));
|
||
|
}
|
||
|
}
|