Un client du secteur médical nous demande de stocker, dans les métadonnées d’une fiche patient gérée par une extension maison, des informations sensibles au sens du RGPD. Les droits d’accès WordPress limitent qui peut consulter cette fiche dans l’administration, mais ils ne protègent rien si la base de données elle-même est un jour exfiltrée par un autre biais : une sauvegarde mal sécurisée, un accès direct au serveur, une injection SQL dans une tout autre extension du même site.
Chiffrer ces données directement en base ajoute une couche de protection qui survit à ce genre de scénario : même en possession du contenu brut de la table, un attaquant sans la clé de chiffrement ne peut rien en tirer. PHP intègre depuis la version 7.2 l’extension sodium, une bibliothèque de cryptographie moderne, directement utilisable sans dépendance externe.
Étape 1 : générer et stocker la clé hors de la base de données
La clé de chiffrement ne doit jamais résider dans la même base de données que les données qu’elle protège : cela reviendrait à verrouiller un coffre-fort et laisser la clé collée dessus. Elle se génère une seule fois, puis se stocke dans une variable d’environnement ou une constante définie dans wp-config.php, en dehors du dépôt de code versionné :
// Génération, à exécuter une seule fois en ligne de commande
php -r "echo sodium_bin2hex(sodium_crypto_secretbox_keygen());"
// Dans wp-config.php, jamais commité dans le dépôt
define( 'MON_EXTENSION_CLE_CHIFFREMENT', 'valeur-hexadecimale-generee' );
Étape 2 : chiffrer une donnée avant de l’enregistrer
sodium_crypto_secretbox() attend un message, un nonce unique par chiffrement et la clé secrète. Le nonce n’est pas confidentiel : il peut être stocké à côté de la donnée chiffrée, à condition de ne jamais être réutilisé avec la même clé pour deux messages différents.
function mon_extension_chiffrer( $texte_clair ) {
$cle = sodium_hex2bin( MON_EXTENSION_CLE_CHIFFREMENT );
$nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
$chiffre = sodium_crypto_secretbox( $texte_clair, $nonce, $cle );
return base64_encode( $nonce . $chiffre );
}

Étape 3 : déchiffrer au moment de l’affichage
Le déchiffrement inverse l’opération, en séparant d’abord le nonce du message chiffré à partir de la longueur fixe du nonce :
function mon_extension_dechiffrer( $donnee_encodee ) {
$decodee = base64_decode( $donnee_encodee );
$cle = sodium_hex2bin( MON_EXTENSION_CLE_CHIFFREMENT );
$nonce = mb_substr( $decodee, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit' );
$chiffre = mb_substr( $decodee, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit' );
$resultat = sodium_crypto_secretbox_open( $chiffre, $nonce, $cle );
if ( false === $resultat ) {
return false; // Donnée corrompue ou clé incorrecte
}
return $resultat;
}
La fonction retourne explicitement false si le déchiffrement échoue, ce qui permet de distinguer une donnée corrompue ou une clé erronée d’un simple résultat vide, et d’agir en conséquence côté extension.
Étape 4 : intégrer au cycle de vie des métadonnées
Les hooks update_post_meta et son pendant en lecture permettent d’automatiser le chiffrement sans modifier chaque appel dans le reste du code :
add_filter( 'sanitize_post_meta_numero_secu', 'mon_extension_chiffrer' );
function mon_extension_lire_numero_secu( $id_article ) {
$valeur = get_post_meta( $id_article, 'numero_secu', true );
return $valeur ? mon_extension_dechiffrer( $valeur ) : '';
}
La limite à connaître : la recherche sur données chiffrées
Une donnée chiffrée avec sodium_crypto_secretbox() produit un résultat différent à chaque chiffrement, même pour un texte identique, à cause du nonce aléatoire. Il devient donc impossible d’effectuer une recherche SQL directe du type WHERE meta_value = '...' sur la valeur chiffrée. Pour un besoin de recherche exacte (retrouver une fiche par numéro), une solution consiste à stocker en parallèle un hachage non réversible de la valeur, utilisé uniquement pour l’indexation et la recherche, jamais pour retrouver la valeur en clair.
Chiffrer une donnée sensible est un engagement à long terme : perdre la clé revient exactement à perdre la donnée elle-même, sans recours possible.
En résumé
L’extension sodium, intégrée nativement à PHP depuis la version 7.2, permet de chiffrer des données réellement sensibles stockées par une extension WordPress sans dépendance externe. La clé, stockée hors de la base de données, et la gestion rigoureuse du nonce restent les deux points de vigilance qui conditionnent la solidité réelle de cette protection.