Current File : /home/igihango/public_html/ecrire/src/Chiffrer/Chiffrement.php |
<?php
/***************************************************************************\
* SPIP, Système de publication pour l'internet *
* *
* Copyright © avec tendresse depuis 2001 *
* Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribué sous licence GNU/GPL. *
\***************************************************************************/
namespace Spip\Chiffrer;
/**
* Chiffrement / déchiffrement symétrique.
*
* @link https://fr.wikipedia.org/wiki/Cryptographie_sym%C3%A9trique
* @link https://www.php.net/manual/fr/book.sodium.php
*/
class Chiffrement {
/** Chiffre un message en utilisant une clé ou un mot de passe */
public static function chiffrer(
string $message,
#[\SensitiveParameter]
string $key
): ?string {
// create a random salt for key derivation
$salt = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES);
$key = self::deriveKeyFromPassword($key, $salt);
$nonce = random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$padded_message = sodium_pad($message, 16);
$encrypted = sodium_crypto_secretbox($padded_message, $nonce, $key);
$encoded = base64_encode($salt . $nonce . $encrypted);
sodium_memzero($key);
sodium_memzero($nonce);
sodium_memzero($salt);
#spip_log("chiffrer($message)=$encoded", 'chiffrer' . _LOG_DEBUG);
return $encoded;
}
/** Déchiffre un message en utilisant une clé ou un mot de passe */
public static function dechiffrer(
string $encoded,
#[\SensitiveParameter]
string $key
): ?string {
$decoded = base64_decode($encoded);
$salt = substr($decoded, 0, \SODIUM_CRYPTO_PWHASH_SALTBYTES);
$nonce = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES, \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$encrypted = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES + \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$key = self::deriveKeyFromPassword($key, $salt);
$padded_message = sodium_crypto_secretbox_open($encrypted, $nonce, $key);
sodium_memzero($key);
sodium_memzero($nonce);
sodium_memzero($salt);
if ($padded_message === false) {
spip_log("dechiffrer() chiffre corrompu `$encoded`", 'chiffrer' . _LOG_DEBUG);
return null;
}
$message = sodium_unpad($padded_message, 16);
#spip_log("dechiffrer($encoded)=$message", 'chiffrer' . _LOG_DEBUG);
return $message;
}
/** Génère une clé de la taille attendue pour le chiffrement */
public static function keygen(): string {
return sodium_crypto_secretbox_keygen();
}
/**
* Retourne une clé de la taille attendue pour le chiffrement
*
* Notamment si on utilise un mot de passe comme clé, il faut le hacher
* pour servir de clé à la taille correspondante.
*/
private static function deriveKeyFromPassword(
#[\SensitiveParameter]
string $password,
string $salt
): string {
if (strlen($password) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
return $password;
}
$key = sodium_crypto_pwhash(
\SODIUM_CRYPTO_SECRETBOX_KEYBYTES,
$password,
$salt,
\SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
\SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);
sodium_memzero($password);
return $key;
}
}