Comment programmer une fonction de hash non décodable ?

WRInaute accro
Bonjour

Voilà, je me suis mis en tête, de programmer une fonction de hashing impossible à décoder.

J'envisage de mettre l'équivalent d'un salt avant la string à coder, mais ce salt devrait lui-même provenir ( sous forme codée ), de cette string, avec éventuellement une combinaison entre le salt codé , et la string non codée.

Par exemple, fusionner le salt codé et la string de manière spécifique fixée.

Ou bien, combinaison de suites de caractères codées et non codées.

Le salt devrait obligatoirement être déduit de la string à hasher.

Quel serait l'algorithme le plus approprié, pour que la string ne puisse pas être décodée même par brute force ?

Merci beaucoup de votre aide.




,
 
WRInaute accro
Pour plus de précisions.

Un algorithme de décodage brute force, pourrait éventuellement restaurer une suite de caractères, mais rien dans son apparence ne pourrait suggérer l'algorithme de production de cette suite de caractères à partir de la string de départ.

Surtout si ces algorithmes sont à plusieurs étages.

Le degré de complexité de l'algorithme entier, serait alors plus que linéairement, proportionnel aux nombre d'étages.
 
Dernière édition:
WRInaute discret
un hash ne se décode jamais. Contrairement au chiffrement (qui est bidirectionnel), le hashing est une fonction à sens unique. Le défi n'est donc pas d'empêcher le "décodage", mais de résister aux attaques par dictionnaire ou par force brute.
 
WRInaute accro
Oui ?

Encore faut-il que l'attaque force brute sache quelle fonction de hashing utiliser.

Là, avec plusieurs fonctions de hash successives, et des résultats intermédiaires non interprétables?

Merci beaucoup de ton aide.
 
WRInaute accro
Voilà voilà :

PHP:
  $str1 = hash1($string);

  $salt = F1($str1);             // F1() éventuellement type hash

  $str3 = F2($str1, $salt);      // F2() fonction de fusion/combinaison type permutation

  $str_cible = hash2($str3);


Merci beaucoup de votre aide et suggestions.
 
WRInaute discret
Solution A : L'ajout d'un "Pepper" (Poivre)


Au lieu que le salt vienne uniquement de la string, mélangez-y une clé secrète (le poivre) stockée sur un serveur sécurisé.


• Votre logique modifiée : salt = F_1(string, secret\_key)


• Résultat : Même si l'attaquant vole votre base de données de hashs, il ne peut rien faire sans la clé secrète restée sur le serveur.
 
WRInaute accro
Bonjour voyante

Voilà :

PHP:
function hash_code($str) {

        $str1 = hash('algo1', $str);

        $salt = hash('algo2', $str1);             // F1() éventuellement type hash

        $str3 = fusion($str1, $salt);      // F2() fonction de fusion/combinaison

        $str_cible = hash('algo3', $str3);

        return $str_cible;
}


Les trois algos sont masqués.

La fonction fusion() est aussi masquée.

Cette fusion est variable suivant les longueurs des paramètres.

Mêmes paramètres => même fusion.

Merci beaucoup de vos suggestions.
 
WRInaute discret
function hash_code($str) {
// 1. On crée une empreinte de base
$str1 = hash('sha512', $str);

// 2. Votre Salt déduit (F1)
// On peut utiliser une partie du hash pour complexifier
$salt = hash('whirlpool', str_rot13($str1));

// 3. Votre Fusion personnalisée (F2)
$str3 = fusion($str1, $salt);

// 4. LE VERROU (Algo 3)
// On utilise Argon2id (standard mondial actuel)
// C'est ici que l'on rend le brute-force "impossible"
$options = [
'memory_cost' => 65536, // 64MB de RAM par essai
'time_cost' => 4, // 4 itérations
'threads' => 2, // Utilise 2 coeurs
];

return password_hash($str3, PASSWORD_ARGON2ID, $options);
}
 
WRInaute discret
function hash_code($str) {
// 1. On crée une empreinte de base
$str1 = hash('sha512', $str);

// 2. Votre Salt déduit (F1)
// On peut utiliser une partie du hash pour complexifier
$salt = hash('whirlpool', str_rot13($str1));

// 3. Votre Fusion personnalisée (F2)
$str3 = fusion($str1, $salt);

// 4. LE VERROU (Algo 3)
// On utilise Argon2id (standard mondial actuel)
// C'est ici que l'on rend le brute-force "impossible"
$options = [
'memory_cost' => 65536, // 64MB de RAM par essai
'time_cost' => 4, // 4 itérations
'threads' => 2, // Utilise 2 coeurs
];

return password_hash($str3, PASSWORD_ARGON2ID, $options);
}
 
WRInaute accro
Bonjour voyante

La fonction password_hash() avec PASSWORD_ARGON2ID, ne rend-t-elle pas une chaîne de caractère avec au début le type de cryptage ?

Je suggère d'utiliset cette fonction en premier, puis les deux autres algos après.

Merci beaucoup de ton aide.
 
WRInaute discret
function hash_code_ultime($str) {
// 1. La fondation (Argon2id)
// On crée un hash ultra-robuste mais "identifiable"
$base_hash = password_hash($str, PASSWORD_ARGON2ID);

// 2. Votre Salt dérivé (F1)
// On déduit un salt de la chaîne initiale pour varier la transformation
$internal_salt = hash('sha3-256', $str);

// 3. Votre Fusion personnalisée (F2)
// On mélange le hash Argon2 (qui contient les $...) avec le salt interne
$mixed = fusion($base_hash, $internal_salt);

// 4. Le Masquage final (Algo 3)
// On termine par un hash rapide mais complexe (ex: Keccak/SHA3)
// pour uniformiser le résultat et supprimer toute trace du $argon2id$
$final_code = hash('sha3-512', $mixed);

return $final_code;
}
 
WRInaute accro
Bonjour voyante

Peut-être le salt dérivé avec sha3-512 au lieu de sha3-256 ?

Il me semble que Argon2ID rend un hash de longueur variable ?

Et $base_hash est de longueur fixe.

Ma fonction fusion() mêle ses paramètres par groupes à la file.

Le paramètre le plus long dépasse.

Il est souhaitable que les deux paramètres soient de même taille.

Sinon il faudrait que je change l'implémentation de fusion() ?

Merci beaucoup de ton aide.
 
WRInaute accro
Plus généralement...

La CNIL décrit deux modes de cryptage : La pseudonymisation et l'anonymisation.

Le hashing est censé être seulement de la pseudonymisation, parce qu'en testant en brute force toutes les possibilités, on pourrait retrouver le token caché.

Celà sous-entend, que cette recherche est possible, donc que l'agorithme de hashing est connu.

Si on implémente un hashing à plusieurs étages, l'algo à chaque étage est d'autant plus inconnu, que le nombre d'algorithmes est grand ( nombre d'étages ).

On en revient donc à un algorithme global inconnu, donc à de l'anonymisation.

Maintenant, la CNIL ne pourrait pas recommander tel ou tel type de séquences d'algorithmes de hashing, sans du même coup dévoiler les algorithmes, donc rendre possible les recherches brute force.

Celà veut simplement dire, que les implémentations individuelles, ne peuvent quasiment pas être légiférées.

Merci beaucoup de vos suggestions.
 
WRInaute discret
function hash_code_ultime($str) {
// 1. Générer un Salt de 64 octets (512 bits)
$salt_derivé = hash('sha3-512', $str); // Sortie hexadécimale de 128 car.

// 2. Générer un hash de base de la même longueur exacte (128 car.)
// On utilise ici une fonction de dérivation (KDF) pour la lenteur
// hash_pbkdf2 permet de choisir la longueur de sortie
$base_hash = hash_pbkdf2("sha512", $str, $salt_derivé, 100000, 64);
// Le '64' ici génère 64 octets bruts, soit 128 caractères en hexa.

// Désormais : strlen($base_hash) == strlen($salt_derivé) == 128

// 3. Fusion parfaite (puisque les tailles sont identiques)
$mixed = fusion($base_hash, $salt_derivé);

// 4. Masquage final
return hash('sha3-512', $mixed);
}
 
WRInaute accro
Bonjour voyante

Avec ta fonction et le salt en 128 octets :


Code:
STR = ABRARACOURCIX

SALT = a89af00da71f508211ff5501557f86c4ae7589b99d58f996bccacecae83757d061dff3073e483e9529881a922c49e5427c77a92598932c8245ad961c3e49cd59

HASH = 845950026200ab117e2a308e44f1e14a033da8eadf9a4fa7840de4f48309cedc16bdefac7a46de03cc4e305c50cd4b40d96b49e766482872a0bbacfc22859f05

MIXED = 84595002a89a6200ab11f00d7e2a308ea71f44f1e14a5082033da8ea11ffdf9a4fa75501840de4f4557f8309cedc86c416bdefacae757a46de0389b9cc4e305c9d5850cd4b40f996d96b49e7bcca66482872cecaa0bbacfce83722859f0557d061dff3073e483e9529881a922c49

RESULTAT = 4911989d93d92b4db0d8e15183556e75df4057fe2dd240e78848d9db7ba78340f0347e0e811462761cb0a9d81201347271539c721358dce11dcb58ed1504c39f

STRLEN(STR) = 128
 
WRInaute discret
Si vous utilisez ce code en production, assurez-vous que vos fonctions algo1, algo2, algo3 et fusion sont bien dans un fichier protégé. Si un pirate accède au code source, il ne pourra toujours pas "inverser" le hash (car c'est impossible), mais il pourra commencer à faire tourner ses propres serveurs pour tester des milliards de mots de passe par seconde.


Pour contrer cela, n'oubliez pas d'ajouter un "Work Factor" (comme les itérations dans PBKDF2 ou Argon2) pour que chaque calcul de RESULTAT prenne au moins 100 ou 200 millisecondes sur votre serveur.
 
WRInaute accro
Bonjour voyante

J'ai amélioré la fonction fusion().

Le bug c'est que ma fonction de cryptage est destinée à crypter les noms de Jockeys sur mon site.

Cà fait quelques mois que j'ai enlevé les jockeys de la base de données de mon site de turf.

La CNIL prône une approche sécurisée mais vague par rapport au cryptage des données personnelles.

Cà a l'air d'être au "cas par cas".

Donc prudence.

Voilà.


Code:
STR = ABRARACOURCIX

SALT = a89af00da71f508211ff5501557f86c4ae7589b99d58f996bccacecae83757d061dff3073e483e9529881a922c49e5427c77a92598932c8245ad961c3e49cd59

HASH = d286993e12c65b70f6247e07fec4eec101bfee75036b63a27ad17225e9e6e2f28e04ecb74074ded5d3c0a3c6f211aa30e4f98152fe6e2f54364d780f362397b8

MIXED = d2869a89a93e1f00da2c65b71f570f608211247e0ff557fec015574eec1f86c01bf4ae75ee75089b936b69d58f3a27a996bd172ccace25e9ecae86e2f3757d28e04061decb7ff3074074d3e48ed5d3e9523c0a39881c6f2a922c11aa349e50e4f427c7981527a92fe6e598932f5432c8264d745ad980f3661c32397e49cdb859

STR_CIBLE = 873c1660d6405cd5cb5b3019b6c3bf5f502ba0d71c131abff445ab7280a26799

ELAPSED = 216.97998046875 milli-secondes
 
WRInaute discret
Une suggestion pour le "Cas par Cas" de la CNIL


Pour être totalement inattaquable juridiquement, vous pourriez ajouter une variable "Clé Secrète" (Pepper) dans votre fusion() qui n'est pas stockée en base de données, mais dans un fichier de configuration sur votre serveur.
 
WRInaute accro
Bonsoir voyante

Dans un fichier de configuration chmod 640 en dehors de l'arborescence du $DOCUMENT_ROOT ?

Celà suffirait ?

Avec en plus un audit de Maître Muriel CAHEN, avocate NTIC ?

Merci beaucoup beaucoup de votre réponse.


PHP:
$bytes = random_bytes(64);
var_dump(bin2hex($bytes));
 
Dernière édition:
WRInaute accro
Merci beaucoup voyante

Si la variable "Clé Secrète" est associée à chaque jockey crypté, pourrais-je mettre ces clés en troisième colonne dans la Table MySQL : JOCKEYS_HASHED ?

CREATE TABLE JOCKEYS_HASHED(NUMJO INTEGER PRIMARY KEY NOT NULL AUTO INCREMENT, NOMJO VARCHAR(130) UNIQUE KEY NOT NULL DEFAULT '', KEY VARCHAR(130) NOT NULL DEFAULT '');

Ou bien s'il y a une seule clé secrète, ce ne serait pas suffisant ?
 

➡️ Offre MyRankingMetrics ⬅️

pré-audit SEO gratuit avec RM Tech (+ avis d'expert)
coaching offert aux clients (avec Olivier Duffez ou Fabien Faceries)

Voir les détails ici

coaching SEO
Discussions similaires
Haut