Quelle est la meilleure façon de créer un hachage court, similaire à ce que fait une Url minuscule?
j'utilise actuellement des hachures MD5 mais j'aimerais trouver quelque chose qui va créer un hachage plus court qui utilise juste [A-z][a-Z][0-9]. Il suffit d'environ 5-10 caractères.
y a-t-il quelque chose qui fait déjà ça?
mise à jour:
j'aime le hachage CRC32. Y a-t-il une façon propre de le calculer dans .NET?
Update2:
j'utilise la fonction CRC32 du lien fourni par Joe. Comment convertir l'uInt en caractères définis ci-dessus?
13 réponses
.net string object a une fonction GetHashCode (). Elle renvoie un entier. Convertissez-le en hexadécimal puis en chaîne de 8 caractères.
Comme suit:
string hashCode = String.Format("{0:X}", sourceString.GetHashCode());
pour en savoir plus: http://msdn.microsoft.com/en-us/library/system.string.gethashcode.aspx
mise à JOUR: , a Ajouté le remarques à partir du lien ci-dessus pour cette réponse:
le comportement de GetHashCode dépend de son implémentation, qui peut changer d'une version du langage courant runtime à l'autre. Une raison pouvant expliquer ce phénomène est d'améliorer la performance de GetHashCode.
si deux objets string sont égaux, la méthode GetHashCode retourne des valeurs identiques. Cependant, il n'y a pas de valeur unique de code de hachage pour chaque valeur de corde unique. différentes chaînes peuvent retourner le même hachage code.
Notes aux appelants
la valeur retournée par GetHashCode est dépendant de la plate-forme . Elle diffère sur les versions 32 et 64 bits du Framework .NET.
est-ce que votre but est de créer un raccourci D'URL ou de créer une fonction de hachage?
si votre but est de créer un raccourci D'URL, alors vous n'avez pas besoin d'une fonction de hachage. Dans ce cas, vous voulez juste prégénérer une séquence de nombres aléatoires cryptographiquement sûrs, puis assigner chaque url pour être encodé un numéro unique de la séquence.
vous pouvez faire cela en utilisant le 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);
}
utilisant le numéro cryptographique le générateur rendra très difficile pour les gens de prédire les chaînes que vous générez, ce qui est important pour vous.
vous pouvez alors convertir le nombre aléatoire de 8 octets en chaîne de caractères en utilisant les caractères de votre alphabet. Il s'agit essentiellement d'un changement du calcul de base (de la base 256 à la base 62).
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 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 jeter un oeil à ce lien: quelques fonctions de hachage Aussi, un peu offtopique, mais selon ce que vous travaillez sur ce pourrait être intéressant: Coding Horror article
il suffit de prendre une Base36 (insensible à la casse) ou une Base64 de L'ID de l'entrée.
alors, disons que je voulais utiliser Base36:
(ID-Base36)
1-1
2-2
3-3
10 - Un
11 - b
12-C
...
10000-7PS
22000 - GZ4
34000-Q8C
...
1000000-LFL
2345000-1E9EW
6000000-3KLMO
vous pouvez les garder encore plus courtes si vous allez avec base64 mais alors les URL seraient sensibles à la casse. Vous pouvez voir que vous obtenez toujours votre belle, soignée clé alphanumérique et avec une garantie qu'il n'y aura pas de collisions!
vous ne pouvez pas utiliser un raccourci hachage que vous avez besoin d'une correspondance un-à-un de la version courte à la valeur réelle. Pour un petit hash, les risques de collision seraient bien trop élevés. Les coups de fouet normaux et longs ne seraient pas très faciles à utiliser (et même si le risque d'une collision serait probablement assez faible à ce moment-là, il ne me semble pas "juste").
TinyURL.com semble utiliser un nombre incrémenté qui est converti en Base 36 (0-9, A-Z).
vous pouvez diminuer le nombre de caractères du hachage MD5 en les encodant sous forme alphanumérique. Chaque caractère MD5 est généralement représenté sous forme de hexadécimal hexadécimal, soit 16 valeurs possibles. [A-zA-Z0-9] inclut 62 valeurs possibles, donc vous pouvez encoder chaque valeur en prenant 4 valeurs MD5.
EDIT:
voici une fonction qui prend un nombre ( 4 chiffres hexadécimaux ) et retourne [0-9a-zA-Z]. Cela devrait vous donner une idée de la façon de la mettre en œuvre. Notez qu'il n'y 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';
}
D'abord je reçois une liste de nombres aléatoires distincts. Ensuite, je sélectionne chaque char
à partir de la chaîne de base, ajouter et retourner le résultat. Je sélectionne 5 caractères, ce qui représente 6471002 permutations de la base 62. La deuxième partie est de vérifier contre db pour voir si tout existe, si non enregistrer l'url courte.
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));
}
}
vous pouvez utiliser CRC32, il est de 8 octets de long et similaire à MD5. Les valeurs uniques seront supportées en ajoutant timestamp à la valeur réelle.
donc ça ressemblera à http://foo.bar / abcdefg12 .
si vous êtes à la recherche d'une bibliothèque qui génère de minuscules hachures uniques d'inters, je vous recommande vivement http://hashids.org/net / . Je l'utilise dans de nombreux projets et il fonctionne magnifiquement. Vous pouvez également spécifier votre propre jeu de caractères pour les hachures personnalisées.
si vous ne vous souciez pas de la force cryptographique, n'importe laquelle des fonctions du CRC le fera.
Wikipedia Liste un tas de différentes fonctions de hachage, y compris la longueur de la sortie. Convertir leur sortie en [A-z][a-Z][0-9] est trivial.
vous pouvez encoder votre code de hachage md5 avec base64 au lieu de hexadécimal, de cette façon vous obtenez une url plus courte en utilisant exactement les caractères [A-z][a-Z][0-9].
il y a un programme merveilleux mais ancien appelé btoa
qui convertit les binaires en ASCII en utilisant des lettres majuscules et minuscules, des chiffres, et deux caractères supplémentaires. Il y a aussi l'encodage MIME base64; la plupart des systèmes Linux ont probablement un programme appelé base64
ou base64encode
. L'un ou l'autre vous donnerait une chaîne courte et lisible à partir d'un CRC 32 bits.
vous pouvez prendre les premiers caractères alphanumériques 5-10 du hachage MD5.