<?php
  final class StatelessCSRF {
    private $hash_algorithm = 'sha256';
    private $secret_key;

    public function __construct() {
      $this->secret_key = CSRF_TOKEN_SECRET;
    }

    public function create() {
      $seed = $this->urlSafeEncode(random_bytes(8));
      $time = time();
      $hash = $this->urlSafeEncode(hash_hmac($this->hash_algorithm, session_id() . $seed . $time, $this->secret_key, true));
      return $this->urlSafeEncode($hash . '|' . $seed . '|' . $time);
    }
  
    public function validate($token) {
      $parts = explode('|', $this->urlSafeDecode($token));
      if(count($parts) === 3) {
        $hash = hash_hmac($this->hash_algorithm, session_id() . $parts[1] . $parts[2], $this->secret_key, true);
        if(hash_equals($hash, $this->urlSafeDecode($parts[0]))) {
          return true;
        }
      }
      return false;
    }
  
    function urlSafeEncode($m) {
      return rtrim(strtr(base64_encode($m), '+/', '-_'), '=');
    }

    function urlSafeDecode($m) {
      return base64_decode(strtr($m, '-_', '+/'));
    }
  }
?>