2009-09-14 10 views
14

In meiner Benutzerdatenbanktabelle nehme ich den MD5-Hash der E-Mail-Adresse eines Benutzers als ID.MD5-Hash als Ganzzahl darstellen

Beispiel: email([email protected]) = id(d41d8cd98f00b204e9800998ecf8427e)

Leider habe ich jetzt die IDs als ganzzahlige Werte darzustellen - um in der Lage sein, eine API zu verwenden, wo die ID nur eine ganze Zahl sein kann.

Jetzt bin ich auf der Suche nach einer Möglichkeit, die ID in eine ganze Zahl zu kodieren, um sie beim Empfang erneut zu entschlüsseln. Wie könnte ich das tun?

Meine Ideen so weit:

  1. convert_uuencode() und convert_uudecode() für den MD5-Hash
  2. jedes Zeichen des MD5-Hash von seinem ord() Wert

ersetzen Welcher Ansatz ist besser? Weißt du noch bessere Möglichkeiten, dies zu tun?

Ich hoffe, Sie können mir helfen. Vielen Dank im Voraus!

+1

Haben Sie keinen anderen, möglicherweise intern, Wert um Ihre Nutzer zu identifizieren? Nun, Sie sollten mindestens eine PK für Ihre Benutzertabelle haben. – Malax

+0

@Malax: Ja, der Primärschlüssel ist das ID-Feld, das den MD5-Hash enthält. Ist das eine schlechte Lösung? – caw

+3

Die Verwendung eines MD5-Hashs als Primärschlüssel Ihrer Benutzertabelle ist im Allgemeinen keine gute Idee. Eine Auto-Inkrement/Serien-Integer-ID ist 4-8 Bytes. Ein MD5-Hash ist 32 Bytes. Vergleiche mit ganzzahligen Werten (z.Jedes Mal, wenn Sie an dieser Tabelle JOIN oder SELECT eine Zeile von ihm) wird viel schneller als der Vergleich von 32 Byte Strings sein, und Integer-Werte benötigen weniger Speicherplatz. Und wirklich ... wenn Sie einen String-Wert verwenden möchten, warum nicht die E-Mail-Adresse selbst verwenden? Es wird die meiste Zeit 32 Bytes oder weniger sein. –

Antwort

16

Seien Sie vorsichtig. Das Konvertieren der MD5s in eine Ganzzahl erfordert Unterstützung für große Ganzzahlen (128 Bit). Die von Ihnen verwendete API wird wahrscheinlich nur 32-Bit-Ganzzahlen unterstützen - oder, schlimmer noch, sie könnte mit der Zahl in Fließkommazahlen umgehen. In jedem Fall wird Ihre ID verloren. Wenn dies der Fall ist, ist das einfache Zuweisen einer zweiten ID ein viel besserer Weg, um mit Dingen umzugehen, als zu versuchen, das MD5 in eine Ganzzahl umzuwandeln.

Wenn Sie jedoch sind sicher, dass die API mit beliebig großen Ganzzahlen ohne Probleme umgehen kann, können Sie nur die MD5 von hexadezimal in eine ganze Zahl konvertieren. PHP unterstützt diese eingebaute Funktion jedoch höchstwahrscheinlich nicht, da sie versuchen wird, sie entweder als 32-Bit-Ganzzahl oder als Fließkomma darzustellen; Sie müssen wahrscheinlich die PHP GMP library dafür verwenden.

+3

+1 für Hinweise, dass der resultierende Wert für die API zu groß sein kann, selbst wenn die leeren Bytes als Ganzzahl verwendet werden. Sie sollten eine andere Lösung für Ihr "email address to integer" -Problem finden. – Malax

+0

Vielen Dank! Wäre das die Lösung besser als meine beiden Ideen? $ id_integer = base_convert ($ id_string, 16, 10); – caw

+0

Lesen Sie die Warnung in base_converts Dokumentation (http://www.php.net/manual/en/function.base-convert.php) - es ist NICHT für große Zahlen geeignet. Und MD5s sind sehr große Zahlen. Sie müssen eine Bigint-Bibliothek verwenden, und die API, auf die Sie zugreifen, muss dies ebenfalls tun - aber ich bezweifle, dass dies der Fall ist. Fügen Sie einfach eine weitere Spalte hinzu und weisen Sie jedem Benutzer beliebige IDs zu. Das wird viel einfacher. – bdonlan

1

Sie könnten hexdec verwenden, um die hexadezimale Zeichenfolge zu analysieren und die Nummer in der Datenbank zu speichern.

+1

Behandelt das 160-Bit-Ganzzahlen, ohne sie zu verschachteln? – bdonlan

+2

Antwort: Nein, es konvertiert zu float, nach der Dokumentation. Dadurch verlieren Sie ungefähr 120 Datenbits und können das ursprüngliche MD5 später nicht wiederherstellen. – bdonlan

+2

Sie haben Recht, die MD5-Summe ist zu groß, um sie als 32-Bit-Integer zu speichern. Ignoriere meine Antwort. ;-) – Malax

1

Konnten Sie nicht einfach ein weiteres Feld hinzufügen, das ein Auto-Inkrement-Int-Feld war?

1

Warum ord()? md5 erzeugt einen normalen 16-Byte-Wert, der Ihnen zur besseren Lesbarkeit in Hex angezeigt wird. Sie können also 16-Byte-Werte nicht ohne Verlust in 4 oder 8 Byte-Ganzzahlen konvertieren. Sie müssen einen Teil Ihrer Algorithmen ändern, um dies als ID zu verwenden.

+0

MD5 erzeugt einen 20-Byte-Wert. – bdonlan

+2

Hmmm ... kann ich ganz dumm bin, aber ... fred @ fred-desktop: ~ $ md5sum citycode.sql 734e4d6f039a81c8a196db588e1cb002 citycode.sql 73 4e 4d 6F 03 9a 81 c8 a1 96 db 58 8e 1c b0 02 hier ein marco92w (Frage owner) Wert d4 1d 8c d9 8f 00 b2 04 e9 80 09 98 ec f8 42 7e was falsch ist mit mir? Wo sind zusätzlich vier Bytes? –

+0

@bdonlan: Nein, 128 Bits sind gleich 16 Bytes, oder? – caw

10

Es gibt gute Gründe, von anderen gesagt zu haben, es anders zu machen.

Aber wenn das, was Sie tun möchten, ist ein MD5-Hash in eine String der Dezimalstellen umwandeln (das ist, was ich glaube, Sie wirklich von „durch eine ganze Zahl darstellen“ bedeuten, da ein md5 schon eine ganze Zahl in String-Form), und es wieder in die gleiche md5 String verwandeln:

function md5_hex_to_dec($hex_str) 
{ 
    $arr = str_split($hex_str, 4); 
    foreach ($arr as $grp) { 
     $dec[] = str_pad(hexdec($grp), 5, '0', STR_PAD_LEFT); 
    } 
    return implode('', $dec); 
} 

function md5_dec_to_hex($dec_str) 
{ 
    $arr = str_split($dec_str, 5); 
    foreach ($arr as $grp) { 
     $hex[] = str_pad(dechex($grp), 4, '0', STR_PAD_LEFT); 
    } 
    return implode('', $hex); 
} 

Demo:

$md5 = md5('[email protected]'); 
echo $md5 . '<br />'; // 23463b99b62a72f26ed677cc556c44e8 
$dec = md5_hex_to_dec($md5); 
echo $dec . '<br />'; // 0903015257466342942628374306682186817640 
$hex = md5_dec_to_hex($dec); 
echo $hex;    // 23463b99b62a72f26ed677cc556c44e8 

natürlich würden Sie caref sein müssen ul entweder String, wie dafür, dass sie als String-Typ nur verwenden, führende Nullen nicht zu verlieren, um sicherzustellen, die Saiten sind die richtigen Längen usw.

+0

Vielen Dank. So würde es funktionieren. Aber jetzt kann ich sehen, was alle anderen sagen wollten: Die neue Ganzzahl ist sehr lang. Und die führende Null ist auch ein Problem. – caw

+0

Froh, zu helfen.Beachten Sie, dass die dezimale Ziffernfolge und die hexadezimale Ziffernfolge (die md5-Zeichenfolge) mathematisch nicht gleich sind; sie sind lediglich "Übersetzungen" voneinander, die durch diese Begleiterfunktionen erzeugt werden, in ihre jeweiligen Ziffernsymbolsätze. – GZipp

1

was:

$ float = hexdec (md5 (‘ String '));

oder

$ = int (integer) (substr (hexdec (md5 ('string')), 0,9) * 100000000);

Definitly größere Chancen für Kollision aber immer noch gut enaugh anstelle von Hash in DB verwenden?

prost,

/Marcin

+0

dieser ist noch besser: sprintf ("% u", crc32 (md5 ('string'))); – Marcin

+0

gut lemme berechnen 32 * 16 bit ... Sie werden 64bytes benötigt. keine Float oder doppelt so lang;) Ihre Nummer wird durch Abschneiden oder Rundung Genauigkeit verlieren –

0

Verwenden Sie die E-Mail-Adresse als Dateiname einer leeren, temporären Datei in einem freigegebenen Ordner, wie /var/myprocess/[email protected]

Rufen Sie dann ftok über den Dateinamen auf. ftok gibt eine eindeutige Ganzzahl-ID zurück.

Es wird nicht garantiert, dass es einzigartig ist, aber es wird wahrscheinlich für Ihre API ausreichen.

6

Für eine 32-Bit-Kondensation kann eine einfache Lösung gefunden werden, indem 4 Hexadezimalpaare (8 Zeichen) des MD5-Hashs ausgewählt werden, wobei jedes Paar ein Byte darstellt und dann mit konvertiert wird.

Für ein nicht signierten 32-Bit-Int:

$inthash = intval(substr(md5($str), 0, 8), 16); 

Für den positiven Wert nur ein 32-Bit-Int:

$inthash = intval(substr(md5($str), 0, 8), 16) >> 1; 

Dies wird wahrscheinlich nur für Werte arbeitet bis zu 64- Bit (8 Bytes oder 16 Zeichen) für die meisten modernen Systeme, wie in den Dokumenten erwähnt.

Auf einem System, das 64-Bit-Ints, eine Aufspaltung Strategie, die der gesamte 128-Bit MD5-Hash als 2 Ints könnte so aussehen verbraucht aufnehmen kann:

$hash = md5($str); 
$inthash1 = intval(substr($hash, 0, 16), 16); 
$inthash2 = intval(substr($hash, 16, 16), 16); 
Verwandte Themen