web-dev-qa-db-fra.com

Quelle est la meilleure façon de créer un hachage court, similaire à ce que fait une petite URL?

J'utilise actuellement des hachages MD5, mais j'aimerais trouver quelque chose qui créera un hachage plus court utilisant uniquement [a-z] [A-Z] [0-9]. Il ne doit contenir que 5 à 10 caractères. 

Y a-t-il quelque chose qui fait déjà cela? 

Mettre à jour:

J'aime le hash CRC32. Existe-t-il un moyen propre de le calculer dans .NET?

Update2:  

J'utilise la fonction CRC32 à partir du lien fourni par Joe. Comment puis-je convertir l'uInt dans les caractères définis ci-dessus? 

39
Arron S

L'objet chaîne .NET a une fonction GetHashCode (). Il retourne un entier . Convertissez-le en hexadécimal, puis en une chaîne de 8 caractères.

Ainsi: 

string hashCode = String.Format("{0:X}", sourceString.GetHashCode());

Plus à ce sujet: http://msdn.Microsoft.com/en-us/library/system.string.gethashcode.aspx

UPDATE: Ajouté les remarques du lien ci-dessus à cette réponse:

Le comportement de GetHashCode dépend de son implémentation, qui peut changer d'une version du Common Language Runtime à un autre. Une des raisons pour lesquelles cela pourrait arriver est d’améliorer les performances de GetHashCode.

Si deux objets de chaîne sont égaux, la méthode GetHashCode renvoie valeurs identiques. Cependant, il n'y a pas une valeur de code de hachage unique pour chaque valeur de chaîne unique. Différentes chaînes peuvent retourner le même hachage code.

Notes aux appelants

La valeur renvoyée par GetHashCode est dépendant de la plate-forme. Il diffère sur les versions 32 bits et 64 bits du .NET Framework.

45
Vlad

Votre objectif est-il de créer un raccourcisseur d'URL ou de créer une fonction de hachage?

Si votre objectif est de créer un raccourcisseur d'URL, vous n'avez pas besoin d'une fonction de hachage. Dans ce cas, vous souhaitez simplement générer au préalable une séquence de nombres aléatoires sécurisés de manière cryptographique, puis affecter à chaque URL un code unique à partir de la séquence.

Vous pouvez le faire en utilisant un code comme:

using System.Security.Cryptography;

const int numberOfNumbersNeeded = 100;
const int numberOfBytesNeeded = 8;
var randomGen = RandomNumberGenerator.Create();
for (int i = 0; i < numberOfNumbersNeeded; ++i)
{
     var bytes = new Byte[numberOfBytesNeeded];
     randomGen.GetBytes(bytes);
}

En utilisant le générateur de numéros cryptographiques, il sera très difficile pour les gens de prédire les chaînes que vous générez, ce qui est important pour moi, je suppose.

Vous pouvez ensuite convertir le nombre aléatoire de 8 octets en une chaîne à l'aide des caractères de votre alphabet. Il s’agit essentiellement d’un changement de calcul de base (de la base 256 à la base 62). 

34
Scott Wisniewski

Je ne pense pas que les services de raccourcissement d'URL utilisent des hachages, je pense qu'ils ont juste une chaîne alphanumérique en cours qui est augmentée avec chaque nouvelle URL et stockée dans une base de données . Si vous avez vraiment besoin d'utiliser une fonction de hachage, regardez ce lien: Quelques fonctions de hachage Aussi, un peu offtopic mais en fonction de ce que vous travaillez sur cela pourrait être intéressant: Article Coding Horror

16
jörg

Prenez simplement une Base36 (insensible à la casse) ou Base64 de l’ID de l’entrée.

Alors, disons que je voulais utiliser Base36:

(ID - Base36)
1 - 1
2 - 2
3 - 3
10 - A
11 - B
12 - C
...
10000 - 7PS
22000 - GZ4
34000 - Q8C
...
1000000 - LFLS
2345000 - 1E9EW
6000000 - 3KLMO 

Vous pourriez les garder encore plus rapidement si vous utilisiez base64, mais l'URL serait sensible à la casse. Vous pouvez voir que vous obtenez toujours votre belle clé alphanumérique bien ordonnée et avec la garantie qu'il n'y aura pas de collision!

11
KingNestor

Vous ne pouvez pas utiliser un hash short car vous avez besoin d'un mappage un-à-un de la version courte à la valeur réelle. Pour un hasch court, le risque de collision serait beaucoup trop élevé. Des hachages normaux et longs ne seraient pas très faciles à utiliser (et même si le risque de collision serait probablement assez faible, cela ne me semblerait toujours pas "correct").

TinyURL.com semble utiliser un nombre incrémenté converti en Base 36 (0-9, A à Z).

7
Arjan

J'obtiens d'abord une liste de nombres distincts aléatoires. Ensuite, je sélectionne chaque char dans la chaîne de base, ajoute et renvoie le résultat. Je sélectionne 5 caractères, ce qui équivaut à 6471002 permutations sur la base 62. La deuxième partie consiste à vérifier contre db pour voir s'il en existe, sinon enregistrer l'URL abrégée.

 const string BaseUrlChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

 private static string ShortUrl
 {
     get
     {
         const int numberOfCharsToSelect = 5;
         int maxNumber = BaseUrlChars.Length;

         var rnd = new Random();
         var numList = new List<int>();

         for (int i = 0; i < numberOfCharsToSelect; i++)
             numList.Add(rnd.Next(maxNumber));

         return numList.Aggregate(string.Empty, (current, num) => current + BaseUrlChars.Substring(num, 1));
      } 
  }
3
Filix Mogilevsky

Vous pouvez réduire le nombre de caractères du hachage MD5 en les encodant sous forme alphanumériques. Chaque caractère MD5 est généralement représenté par un hex, ce qui fait 16 valeurs possibles. [a-zA-Z0-9] comprend 62 valeurs possibles. Vous pouvez donc coder chaque valeur en prenant 4 valeurs MD5.

MODIFIER:

voici une fonction qui prend un nombre (4 chiffres hexadécimaux) et renvoie [0-9a-zA-Z]. Cela devrait vous donner une idée de la façon de le mettre en œuvre. Notez qu'il peut y avoir des problèmes avec les types; Je n'ai pas testé ce code.

char num2char( unsigned int x ){
    if( x < 26 ) return (char)('a' + (int)x);
    if( x < 52 ) return (char)('A' + (int)x - 26);
    if( x < 62 ) return (char)('0' + (int)x - 52);
    if( x == 62 ) return '0';
    if( x == 63 ) return '1';
}
3
Colin

Vous pouvez utiliser CRC32, il est long de 8 octets et similaire à MD5. Les valeurs uniques seront prises en charge en ajoutant un horodatage à la valeur réelle. 

Donc, cela ressemblera à http://foo.bar/abcdefg12 .

2
Joe

Si vous recherchez une bibliothèque générant de minuscules hachages uniques d’inters, je peux fortement recommander http://hashids.org/net/ Je l'utilise dans de nombreux projets et cela fonctionne à merveille. Vous pouvez également spécifier votre propre jeu de caractères pour les hachages personnalisés.

2
herostwist

Vous pouvez encoder votre code de hachage md5 avec base64 au lieu de hexadécimal, ainsi vous obtiendrez une URL plus courte en utilisant exactement les caractères [a-z] [A-Z] [0-9].

0
codymanix

Il existe un programme ancien mais merveilleux appelé btoa qui convertit le binaire en ASCII à l'aide de lettres majuscules et minuscules, de chiffres et de deux caractères supplémentaires. Il y a aussi le codage MIME en base64; la plupart des systèmes Linux ont probablement un programme appelé base64 ou base64encode. L'une ou l'autre vous donnerait une courte chaîne lisible à partir d'un CRC 32 bits.

0
Norman Ramsey

Si vous ne vous souciez pas de la force cryptographique, aucune des fonctions du CRC ne le fera.

Wikipedia répertorie un tas de différentes fonctions de hachage, y compris la longueur de la sortie. La conversion de leur sortie en [a-z] [A-Z] [0-9] est triviale.

0
Kevin Montrose