Crypt::hmacBase64() versus CsrfTokenGenerator::get() and CsrfTokenGenerator::validate()
I made a quick test using the following code.

use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Site\Settings;
use Drupal\Core\Access\CsrfToken;
use Drupal\Component\Utility\Crypt;

$autoloader = require_once 'autoload.php';

/**
 * Global flag to identify update.php and authorize.php runs.
 *
 * Identifies update.php and authorize.php runs, avoiding unwanted operations
 * such as css/js preprocessing and translation, and solves some theming issues.
 * The flag is checked in other places in Drupal code (not just authorize.php).
 */
const MAINTENANCE_MODE = 'update';

try {
  $request = Request::createFromGlobals();
  $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
  $kernel-&gt;prepareLegacyRequest($request);
}
catch (HttpExceptionInterface $e) {
  $response = new Response('', $e-&gt;getStatusCode());
  $response-&gt;prepare($request)-&gt;send();
  exit;
}

\Drupal::moduleHandler()-&gt;addModule('system', 'core/modules/system');
\Drupal::moduleHandler()-&gt;addModule('user', 'core/modules/user');
\Drupal::moduleHandler()-&gt;load('system');
\Drupal::moduleHandler()-&gt;load('user');

drupal_maintenance_theme();

$csrf_token = \Drupal::csrfToken();

$content[] = [
  '#markup' =&gt; t('First method: %token.&lt;br /&gt;', ['%token' =&gt; Crypt::hmacBase64(123456, \Drupal::service('private_key')-&gt;get())]),
  '#cache' =&gt; ['max-age' =&gt; 0],
];
$content[] = [
  '#markup' =&gt; t('Second method: %token.&lt;br /&gt;', ['%token' =&gt; $csrf_token-&gt;get(123456)]),
  '#cache' =&gt; ['max-age' =&gt; 0],
];

$renderer = \Drupal::service('bare_html_page_renderer');
$response = $renderer-&gt;renderBarePage($content, 'Test results', 'maintenance_page', array(
  '#show_messages' =&gt; FALSE,
));

$response-&gt;setStatusCode(400);
$response-&gt;send();


I then opened three different Firefox windows pointing them at the test script I wrote. This is what I got:

First window


  First method: r3xavuZbwgsk1RJTPm-zOs3kUSeSY4-BDnj-UCwgyr0.
  Second method: OndzLnnASZLsuzABJltD_HwK8dr48fEW_hdWG9Lu02I.


Second window


  First method: r3xavuZbwgsk1RJTPm-zOs3kUSeSY4-BDnj-UCwgyr0.
  Second method: J6oHkKdXeL9RUKHX4B1Sn418Yh8XD0tJbRrs459BI7A.


Third window


  First method: r3xavuZbwgsk1RJTPm-zOs3kUSeSY4-BDnj-UCwgyr0.
  Second method: TYvxZiF7xS6hD2nn8pfHu0GR9OPw0X8xT1HfVDNWkXc.


With the second method, different users are going to get different values, even in the case the input value is the same.
I would say that using the csrf_token service is preferable, in my case.