2013-10-25 19 views
12

Quello che mi serve è hash una stringa. Non deve essere sicuro perché sarà solo una frase nascosta nel file di testo (semplicemente non deve essere riconoscibile per un occhio umano).Stringhe di hashing (nascondimento) in Python

Non deve essere solo una stringa casuale perché quando gli utenti digitano la stringa, desidero compilarla e confrontarla con una stringa già hash (dal file di testo).

Quale sarebbe il migliore per questo scopo? Può essere fatto con le classi built-in?

+1

Qual è il tuo ** problema ** reale? Ci sono molti algoritmi di hash, l'approccio bset dipende da come userete la stringa hash. –

risposta

32

Prima di tutto, lasciami dire che non puoi garantire risultati unici. Se si desidera ottenere risultati univoci per tutte le stringhe nell'universo, è meglio memorizzare la stringa stessa (o una versione compressa).

Maggiori informazioni su questo in un secondo. Prendiamo prima alcuni hash.

modo hashlib

È possibile utilizzare uno dei principali hash crittografici per hash di una stringa con pochi passaggi:

>>> import hashlib 
>>> sha = hashlib.sha1("I am a cat") 
>>> sha.hexdigest() 
'576f38148ae68c924070538b45a8ef0f73ed8710' 

Avete una scelta tra SHA1, SHA224, SHA256, SHA384, SHA512, e MD5 per quanto riguarda i built-in.

Qual è la differenza tra questi algoritmi di hash?

Una funzione di hash funziona prendendo i dati di lunghezza variabile e trasformandoli in dati di lunghezza fissa.

La lunghezza fissa, nel caso di ciascuno degli algoritmi SHA incorporati in hashlib, è il numero di bit specificato nel nome (con l'eccezione di sha1 che è 160 bit). Se si desidera una maggiore certezza che due stringhe non finiscano nello stesso bucket (stesso valore hash), selezionare un hash con un digest più grande (la lunghezza fissa).

in modo ordinato, questi sono i digest dimensioni si deve lavorare con:

Algorithm Digest Size (in bits) 
md5  128 
sha1  160 
sha224  224 
sha256  256 
sha384  384 
sha512  512 

Più grande è il digerire meno è probabile che avrete una collisione, a condizione la funzione hash è degno.

Aspetta, che dire di hash()?

La funzione integrata hash() restituisce numeri interi, che potrebbero anche essere di facile utilizzo per lo scopo delineato. Ci sono problemi però.

>>> hash('moo') 
6387157653034356308 
  1. Se il programma sta per essere eseguito su sistemi diversi, non si può essere sicuri che hash tornerà la stessa cosa. In effetti, sto lavorando su una scatola a 64 bit usando Python a 64 bit. Questi valori saranno molto diversi da quelli di Python a 32 bit.

  2. Per Python 3.3+, come @gnibbler sottolineato, hash() è randomizzato tra le esecuzioni. Funzionerà per una sola esecuzione, ma quasi sicuramente non funzionerà su tutte le esecuzioni del tuo programma (tirando fuori dal file di testo che hai menzionato).

Perché lo standard hash() deve essere costruito in questo modo? Bene, l'hash incorporato è lì per una ragione specifica. Hash tabelle/dizionari/cercare tabelle in memoria. Non per uso crittografico ma per ricerche a basso costo in fase di esecuzione.

Non utilizzare hash(), utilizzare hashlib.

+4

'hash()' è randomizzato tra le esecuzioni dal Python3.3 ie. si può solo contare su di esso restituendo lo stesso valore all'interno di una singola esecuzione di un programma –

+0

Grande. Grazie per quello @gnibbler, non sapevo che non fosse stabile tra le corse. –

+2

Questo post è fantastico. Contiene tutte le informazioni di cui avevo bisogno. Alla gente piaci, grazie amico. – Lucas

0

usare Basta la funzione built-in hash(), ad esempio:

s = 'a string' 
hash(s) 
=> -8411828025894108412 
+0

Genererà numeri univoci per ogni stringa? Può essere decodificato (solo curioso)? – Lucas

+2

@Lucas, impossibile per una funzione hash di dimensioni fisse restituire un valore diverso per tutte le stringhe possibili. Ad esempio, se una funzione di hash restituisce 2 bit, ha solo 4 valori possibili. –

+0

@Tim Peters Può essere decodificato (solo curioso)? – Lucas

5

Si può semplicemente utilizzare il modulo base64 per raggiungere il tuo obiettivo:

>>> import base64 
>>> a = 'helloworld' 
>>> encoded_str = base64.encodestring(a) 
>>> encoded_str 
'aGVsbG93b3JsZA==' 
>>> base64.decodestring(encoded_str) 
'helloworld' 
>>> 

naturalmente si può anche utilizzare il il modulo hashlib, è più sicuro, perché la stringa hash non può (o molto molto difficile) essere decodificata, ma per la tua domanda base64 è sufficiente - "Non deve essere sicuro"

+0

'base64' viene fornito con Python2.3 (sì, so che è strano) per impostazione predefinita? – Lucas

+0

Sì! È OK per eseguire il codice sopra in Python 2.3 [Ulteriori informazioni da qui] (http://docs.python.org/release/2.3/lib/module-base64.html) – tinylambda

4

Si noti che l'hash di stringa di Python non è "definito", ma può variare e varia tra versioni e implementazioni. Quindi memorizzare un hash di stringa Python creerà delle difficoltà. L'hash delle stringhe di CPython non fa alcun tentativo di essere "oscuro".

Un approccio standard consiste nell'utilizzare una funzione hash progettata per il tipo. In questo modo:

>>> import hashlib 
>>> encoded = hashlib.sha1("abcdef") # "abcdef" is the password 
>>> encoded.hexdigest() 
'1f8ac10f23c5b5bc1167bda84b833e5c057a77d2' 

Questa lunga stringa di cifre esadecimali è "l'hash". SHA-1 è una funzione di hash "forte". Puoi diventare famoso se trovi due stringhe che hanno lo stesso hash ;-) E dato lo stesso input, restituirà lo stesso "esadecimale" su tutte le piattaforme attraverso tutte le versioni e implementazioni di Python.

+1

Specialmente dal momento che Python3.3 'hash (somestring)' è diverso tra le esecuzioni –