index/src/Security/CSRFP.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));
}
}