auth-hash: Authentification par hachage de lien sécurisé
Installation
Vous pouvez installer ce module dans n'importe quelle distribution basée sur RHEL, y compris, mais sans s'y limiter :
- RedHat Enterprise Linux 7, 8, 9 et 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 et Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-auth-hash
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-auth-hash
Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_http_auth_hash_module.so;
Ce document décrit nginx-module-auth-hash v0.1.0 publié le 06 janvier 2026.
Description :
Le module de lien sécurisé HASH de Nginx améliore la sécurité et la fonctionnalité du module de lien sécurisé standard.
Un jeton sécurisé est créé en utilisant une construction de hachage sécurisé avec un algorithme de hachage arbitraire pris en charge par OpenSSL, par exemple :
blake2b512, blake2s256, gost, md4, md5, mdc2, rmd160, sha1, sha224, sha256,
sha3-224, sha3-256, sha3-384, sha3-512, sha384, sha512, sha512-224, sha512-256, shake128, shake256, sm3.
Utilisation :
Le message à hacher est défini par auth_hash_message, secret_key est donné par auth_hash_secret, et l'algorithme de hachage H est défini par auth_hash_algorithm.
Pour une sécurité accrue, le temps ou un horodatage (selon le format de date spécifié par le paramètre de format) doit être ajouté au message à hacher.
Il est possible de créer des liens avec une durée de vie limitée. Cela est défini par les paramètres optionnels range_start ou range_end. Si la période d'expiration n'est pas spécifiée, un lien a une durée de vie illimitée.
Exemple de configuration pour le côté serveur.
location ^~ /files/ {
# Active la fonctionnalité, si désactivée, $auth_hash sera toujours vide
auth_hash on;
# Définir la valeur de temps utilisée pour la vérification.
# Vous pouvez définir la plage de temps d'expiration, le format de la valeur de temps et le fuseau horaire de la valeur de temps
auth_hash_check_time $arg_ts range_end=$arg_e format=%s;
# Définir la valeur du jeton utilisée pour la vérification
# Les formats disponibles sont hex (par défaut), base64, base64url et bin
auth_hash_check_token $arg_st format=hex;
# Clé secrète
auth_hash_secret "my_secret_key";
# Message à vérifier
auth_hash_message "$uri|$arg_ts|$arg_e|$auth_hash_secret";
# Fonction de hachage cryptographique à utiliser
auth_hash_algorithm sha256;
# Dans un environnement de production, nous ne devrions pas révéler à un attaquant potentiel
# pourquoi l'authentification par hachage a échoué
# - Si le hachage est incorrect, alors $auth_hash est une chaîne NULL.
# - Si le hachage est correct et que le lien n'a pas expiré, alors $auth_hash est "1".
if ($auth_hash != "1") {
return 403;
}
rewrite ^/files/(.*)$ /files/$1 break;
}
Le côté application doit utiliser une fonction de hachage standard pour générer le hachage, qui doit ensuite être encodé en hex ou en base64url. Exemple en Perl ci-dessous.
La variable $data contient le jeton sécurisé, l'horodatage au format ISO 8601, et la période d'expiration en secondes
perl_set $secure_token '
sub {
use Digest::SHA qw(sha256_base64);
use POSIX qw(strftime);
my $now = time();
my $secret = "my_very_secret_key";
my $expire = 60;
my $tz = strftime("%z", localtime($now));
$tz =~ s/(\d{2})(\d{2})/$1:$2/;
my $timestamp = strftime("%Y-%m-%dT%H:%M:%S", localtime($now)) . $tz;
my $r = shift;
my $data = $r->uri;
# hex
my $string_to_hash = $data . "|" . $timestamp . "|" . $expire . "|" . $secret;
my $digest_binary = sha256($string_to_hash);
my $digest = unpack("H*", $digest_binary);
# base64url
# my $digest = sha256_base64($data . "|" . $timestamp . "|" . $expire . "|" . $secret);
# $digest =~ tr/+/_/;
# $digest =~ s/=+$//;
$data = "st=" . $digest . "&ts=" . $timestamp . "&e=" . $expire;
return $data;
}
';
Une fonction similaire en PHP
$secret = 'my_very_secret_key';
$expire = 60;
$algo = 'sha256';
$timestamp = date('c');
$unixtimestamp = time();
$stringtosign = "/files/top_secret.pdf|{$unixtimestamp}|{$expire}|{$secret}";
// hex
$hash = bin2hex(hash($algo, $stringtosign, true));
// base64url
// $hash = base64_encode(hash($algo, $stringtosign, true));
// $hash = strtr($hash, '+/', '-_');
// $hash = str_replace('=', '', $hash);
$host = $_SERVER['HTTP_HOST'];
$loc = "https://{$host}/files/top_secret.pdf?st={$hash}&ts={$unixtimestamp}&e={$expire}";
Utilisation de l'horodatage Unix en Node.js
const crypto = require("crypto");
const secret = 'my_very_secret_key';
const expire = 60;
const unixTimestamp = Math.round(Date.now() / 1000.);
const stringToSign = `/files/top_secret.pdf|${unixTimestamp}|${expire}|${secret}`;
// hex
const hash = crypto.createHash('sha256').update(stringToSign).digest('hex')
// base64url
// const hash = crypto.createHash('sha256').update(stringToSign).digest('base64')
// .replace(/=/g, '')
// .replace(/\+/g, '-')
// .replace(/\//g, '_');
const loc = `https://host/files/top_secret.pdf?st=${hash}&ts=${unixTimestamp}&e=${expire}`;
Version Bash
#!/bin/bash
SECRET="my_super_secret"
TIME_STAMP="$(date -d "today + 0 minutes" +%s)";
EXPIRES="3600"; # secondes
URL="/file/my_secret_file.txt"
ST="$URL|$TIME_STAMP|$EXPIRES|$SECRET"
## hex
TOKEN="$(echo -n $ST | openssl dgst -sha256 | awk '{print $1}')"
## Base64url
## TOKEN="$(echo -n $ST | openssl dgst -sha256 -binary | openssl base64 | tr +/ -_ | tr -d =)"
echo "http://127.0.0.1$URL?st=$TOKEN&ts=$TIME_STAMP&e=$EXPIRES"
Variables intégrées
$auth_hash- Si le hachage est correct et que le lien n'a pas expiré, alors $auth_hash est "1". Sinon, il est nul.$auth_hash_secret- La valeur de la directive auth_hash_secret
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-auth-hash.