Ingénierie inverse Ssortingng.GetHashCode

Le comportement de Ssortingng.GetHashCode dépend de l’architecture du programme. Donc, il retournera une valeur sur x86 et une valeur sur x64. J’ai une application de test qui doit fonctionner en x86 et qui doit prédire la sortie du code de hachage à partir d’une application devant s’exécuter en x64.

Vous trouverez ci-dessous le désassemblage de l’implémentation Ssortingng.GetHashCode de mscorwks.

public override unsafe int GetHashCode() { fixed (char* text1 = ((char*) this)) { char* chPtr1 = text1; int num1 = 0x15051505; int num2 = num1; int* numPtr1 = (int*) chPtr1; for (int num3 = this.Length; num3 > 0; num3 -= 4) { num1 = (((num1 <≫ 0x1b)) ^ numPtr1[0]; if (num3 <= 2) { break; } num2 = (((num2 <> 0x1b)) ^ numPtr1[1]; numPtr1 += 2; } return (num1 + (num2 * 0x5d588b65)); } } 

Quelqu’un peut-il porter cette fonction sur une implémentation sécurisée?

Les codes de hachage ne sont pas conçus pour être reproductibles sur toutes les plates-formes, ni même pour plusieurs exécutions du même programme sur le même système. Vous allez dans le mauvais sens. Si vous ne changez pas de cap, votre chemin sera difficile et un jour, il se terminera peut-être en larmes.

Quel est le vrai problème que vous voulez résoudre? Serait-il possible d’écrire votre propre fonction de hachage, en tant que méthode d’extension ou en tant GetHashCode d’une classe d’encapsuleur et de l’utiliser à la place?

Tout d’abord, Jon a raison. c’est une course de fou. Les versions internes de débogage du cadre utilisé pour “manger notre propre nourriture pour chien” changent chaque jour l’ algorithme de hachage afin d’empêcher les utilisateurs de créer des systèmes, même des systèmes de test, reposant sur des détails d’implémentation non fiables documentés comme pouvant être modifiés. à tout moment.

Plutôt que d’enchâsser une émulation d’un système documenté comme étant impropre à l’émulation, ma recommandation serait de prendre du recul et de vous demander pourquoi vous essayez de faire quelque chose d’aussi dangereux . Est-ce vraiment une exigence?

Deuxièmement, StackOverflow est un site de questions techniques et de réponses, et non un site “fais mon travail pour moi gratuitement”. Si vous êtes vraiment déterminé à faire cette chose dangereuse et que vous avez besoin de quelqu’un qui puisse réécrire du code non sécurisé en code équivalent, alors je vous recommande d’ engager quelqu’un qui puisse le faire pour vous .

Bien que tous les avertissements donnés ici soient valables, ils ne répondent pas à la question. J’ai eu une situation dans laquelle GetHashCode () était malheureusement déjà utilisé pour une valeur persistante en production, et je n’avais d’autre choix que de réimplémenter l’aide de l’algorithme par défaut .NET 2.0 32 bits x86 (little-endian). J’ai re-codé sans danger, comme indiqué ci-dessous, et cela semble fonctionner. J’espère que ça aide quelqu’un.

 // The GetSsortingngHashCode() extension method is equivalent to the Microsoft .NET Framework 2.0 // Ssortingng.GetHashCode() method executed on 32 bit systems. public static int GetSsortingngHashCode(this ssortingng value) { int hash1 = (5381 << 16) + 5381; int hash2 = hash1; int len = value.Length; int intval; int c0, c1; int i = 0; while (len > 0) { c0 = (int)value[i]; c1 = (int)value[i + 1]; intval = c0 | (c1 << 16); hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ intval; if (len <= 2) { break; } i += 2; c0 = (int)value[i]; c1 = len > 3 ? (int)value[i + 1] : 0; intval = c0 | (c1 << 16); hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ intval; len -= 4; i += 2; } return hash1 + (hash2 * 1566083941); } 

Ce qui suit reproduit exactement les codes de hachage de Ssortingng par défaut sur .NET 4.7 (et probablement plus tôt). C’est le code de hachage donné par:

  • Par défaut sur une instance de Ssortingng : "abc".GetHashCode()
  • SsortingngComparer.Ordinal.GetHashCode("abc")
  • Diverses méthodes Ssortingng qui prennent l’énumération SsortingngComparison.Ordinal .
  • System.Globalization.CompareInfo.GetSsortingngComparer(CompareOptions.Ordinal)

Lors des tests sur les versions libérées avec une optimisation complète de JIT, ces versions surpassent modestement le code .NET intégré et ont également été lourdement testées pour une équivalence exacte avec le comportement .NET . Notez qu’il existe des versions distinctes pour x86 et x64 . Votre programme devrait généralement inclure les deux; sous les listes de codes respectives se trouve un harnais d’appel qui sélectionne la version appropriée au moment de l’exécution.

x86 – (.NET s’exécutant en mode 32 bits)

 static unsafe int GetHashCode_x86_NET(int* p, int c) { int h1, h2 = h1 = 0x15051505; while (c > 2) { h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++; h2 = ((h2 << 5) + h2 + (h2 >> 27)) ^ *p++; c -= 4; } if (c > 0) h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++; return h1 + (h2 * 0x5d588b65); } 

x64 – (.NET s’exécutant en mode 64 bits)

 static unsafe int GetHashCode_x64_NET(Char* p) { int h1, h2 = h1 = 5381; while (*p != 0) { h1 = ((h1 << 5) + h1) ^ *p++; if (*p == 0) break; h2 = ((h2 << 5) + h2) ^ *p++; } return h1 + (h2 * 0x5d588b65); } 

Appel de la méthode de harnais / extension pour l'une ou l'autre des plateformes (x86 / x64)

 readonly static int _hash_sz = IntPtr.Size == 4 ? 0x2d2816fe : 0x162a16fe; public static unsafe int GetSsortingngHashCode(this Ssortingng s) { /// Note: x64 ssortingng hash ignores remainder after embedded '\0'char (unlike x86) if (s.Length == 0 || (IntPtr.Size == 8 && s[0] == '\0')) return _hash_sz; fixed (char* p = s) return IntPtr.Size == 4 ? GetHashCode_x86_NET((int*)p, s.Length) : GetHashCode_x64_NET(p); }