2010-04-08 5 views
10

Ich arbeite in Python auf appengine.Erzeuge Fixed-Length-Hash in Python für URL-Parameter

Ich versuche zu schaffen, was mit dem „v“ Wert in der URL des YouTube entspricht (http://www.youtube.com/watch?v=XhMN0wlITLk) für bestimmte Einheiten abruft. Der Datenspeicher generiert automatisch einen Schlüssel, der jedoch viel zu lang ist (34 Ziffern). Ich habe mit hashlib experimentiert, um mein eigenes zu bauen, aber wieder bekomme ich eine lange Schnur. Ich möchte es unter 11 Ziffern behalten (ich habe es nicht mit einer großen Anzahl von Entitäten zu tun) und Buchstaben und Zahlen sind akzeptabel.

Es scheint, als sollte es eine schöne Standardlösung geben. Ich vermisse es wahrscheinlich nur.

Antwort

8

Sie können die automatisch generierte integer id des Schlüssels verwenden, um den Hash zu generieren. Eine einfache Möglichkeit, den Hash zu generieren, wäre, die Integer-ID in base62 (alphanumerisch) zu konvertieren. Um das Objekt abzurufen, konvertieren Sie einfach von Base62 in Dezimal zurück und verwenden Sie get_by_id, um das Objekt abzurufen.

Hier ist eine einfache base62-Konvertierungsfunktion, die ich in einer meiner Apps verwendet habe.

import string 
alphabet = string.letters + string.digits 
max = 11 

def int_to_base62(num): 
    if num == 0: 
     return alphabet[0] 

    arr = [] 
    radix = len(alphabet) 
    while num: 
     arr.append(alphabet[num%radix]) 
     num /= radix 
    arr.reverse() 
    return (alphabet[0] * (max - len(arr))) + ''.join(arr) 

def base62_to_int(str): 
    radix = len(alphabet) 
    power = len(str) - 1 
    num = 0 
    for char in str: 
     num += alphabet.index(char) * (radix ** power) 
     power -= 1 
    return num 
+0

Diese beiden Links waren sehr hilfreich. Das Problem besteht nun darin, den idealen Weg zum Codieren und Decodieren in base62 zu finden. Ich habe etwas gelesen, gibt es eine Methode, die Sie vorschlagen? – LeRoy

+1

können Sie grundlegende Anzahl Base-Konvertierungstechniken verwenden. Um die feste Hash-Länge zu erhalten, fügen Sie der Base62-Nummer einfach einen Null-Padding hinzu. – z33m

5

Wenn Sie einen Wert haben, der für jede Entität eindeutig ist, können Sie eine kürzere Version durch Hashing und Abschneiden erhalten. Hashes wie md5 oder sha1 sind gut gemischt, was bedeutet, dass jedes Bit in der Ausgabe eine 50% ige Chance hat zu spiegeln, wenn Sie ein Bit in der Eingabe ändern. Wenn Sie den Hash-Wert kürzen, erhöhen Sie einfach die Wahrscheinlichkeit einer Kollision, aber Sie können den Kompromiss zwischen Länge und Kollisionsquoten festlegen.

Url-safe base64-Codierung ist eine gute Option, um den Hash in Text umzuwandeln.

orig_id = 'weiowoeiwoeciw0eijw0eij029j20d232weifw0jiw0e20d2' # the original id 
shorter_id = base64.urlsafe_b64encode(hashlib.md5(orig_id).digest())[:11] 

Mit Base64, haben Sie 6 Bits pro Zeichen, 11 Zeichen 66 Bits von Einzigartigkeit gibt, oder eine 1 in 2 ** 66 Chance einer Kollision.

+0

Gibt es einen Grund, warum Sie die base64-Konvertierung gegenüber base62 wie oben vorgeschlagen wählen würden? – LeRoy

+0

Base64 scheint immer ein "=" zu enthalten, das nicht wirklich sicher ist. – LeRoy

+0

Ich benutze Base64 über Base62, nur weil es vertrauter ist. Das = ist Auffüllen. Du stutzst trotzdem, oder? –