2012-06-15 16 views
5

Ogni oggetto utente nel mio database ha un ID incrementale (1, 2, 3, ...). L'URL per visualizzare il profilo di un utente contiene l'ID dell'oggetto utente; per esempio. http://www.example.com/users/1. In questo modo tutti possono vedere quanti utenti ci sono sul sito web, quanto velocemente cresce la base di utenti ecc. Non voglio dare queste informazioni.Come calcolare un ID nascosto breve di lunghezza fissa simile a YouTube (ad esempio 2WNrx2jq184)

Mi piacerebbe convertire l'ID incrementale in una stringa di lunghezza fissa in formato Base58, quindi l'URL sarebbe simile a http://www.example.com/users/2WNrx2jq184 Inoltre, ho bisogno della funzione di inversione che converta la stringa all'ID originale. La funzione inversa non dovrebbe essere facile da decodificare.

Il miglior codice Python che ho trovato per questo scopo è https://github.com/JordanReiter/django-id-obfuscator. È molto buono, ma in alcuni casi aggiunge un carattere 0 e/o ., che porta a stringhe che non sono in Base58 e non hanno una lunghezza fissa. (Vedi utils.py linee 24 e 29.)

Come posso migliorare django-id-obfuscator di provocare base58 lunghezza fissa gli ID offuscato, o come posso creare tali ID offuscato in Python?

+1

presumo si vuole evitare di creare un numero casuale e memorizzare il suo riferimento all'ID reale da qualche parte in il database? – Groo

+0

https://github.com/JordanReiter/django-id-obfuscator/blob/master/id_obfuscator/base58.py - questo non sembra contenere '0' o' .'. – eumiro

+1

@eumiro https://github.com/JordanReiter/django-id-obfuscator/blob/master/id_obfuscator/utils.py - succede qui – Korneel

risposta

5

Se si desidera eseguire correttamente questa operazione, prendere l'ID utente, riempirlo con zeri iniziali, quindi crittografarlo con qualcosa come AES e codificare il risultato con base58. Per recuperare l'ID, decodifica, decodifica e int() il risultato.

Così, per la crittografia:

>>> from Crypto.Cipher import AES 
>>> import base64 
>>> obj = AES.new('yoursecretkeyABC') 
>>> x = base64.encodestring(obj.encrypt("%016d"%1)) 
>>> x 
'tXDxMg1YGb1i0V29yCCBWg==\n' 

e la decrittografia

>>> int(obj.decrypt(base64.decodestring(x))) 
1 

Se si può vivere con crypto deboli, si potrebbe anche semplicemente XOR l'ID imbottita con una chiave:

>>> key = [33, 53, 2, 42] 
>>> id = "%04d" % 1 
>>> x = ''.join([chr(a^ord(b)) for a, b in zip(key, id)]) 
>>> x 
'\x11\x052\x1b' 
>>> int(''.join([chr(a^ord(b)) for a, b in zip(key, x)])) 
1 

Ma questo è molto meno sicuro poiché non si dovrebbe mai usare lo stesso OTP per più messaggi. Assicurati anche che la chiave abbia la stessa lunghezza del tuo ID imbottito.

+0

https://en.bitcoin.it/wiki/Base58Check_encoding – StefanNch

+0

@StefanNch http://gitorious.org/bitcoin/python-base58/blobs/master/base58.py Penso che questo sia quello di cui ho bisogno per sostituire base64 con base58 – Korneel

+0

Pensi che il costo di questa operazione (decrypt di base58 + decrittografia AES) per convertire l'ID offuscato nell'ID originale sia giustificato solo per nascondere la sequenza ID? L'operazione di decrittografia potrebbe essere ottimizzata al costo dell'operazione di crittografia? – Korneel

0

Questa è una vecchia domanda su cui sono incappato. di recente ho trovato la Biblioteca hashids che risolve questo problema ed è disponibile per una vasta gamma di linguaggi di programmazione:

http://hashids.org

Problemi correlati