Come generare una stringa imprevedibile ma breve? [chiuso]

1

Voglio creare alcuni URL brevi per caricare file e collegamenti sul mio server. Abbastanza semplice, carico i file e il mio script mi restituisce un link. All'accesso, il collegamento viene tradotto nel file e il download inizia. Perché è moderno, voglio i miei collegamenti brevi e non così UUID4-like, perché sono molto lunghi.

Non voglio che qualcuno provi alcuni URL per trovare un link valido. Forse dovrei inviare solo 404 se un IP ha già 10 URL errati chiamati?

Per creare stringhe casuali corte ho pensato a quanto segue:

  1. Precarica una tabella SQL (key, target) dove key è case sensitive con tutti i possibili valori in un intervallo definito come [a-zA-Z0-9_-~=]{12} . Quindi seleziona con WHERE target IS NULL ORDER BY RANDOM() una chiave vuota e usala. Ciò garantirà che non genererò mai la stessa chiave due volte ma che richiede molto spazio di archiviazione e potrebbe essere troppo.
  2. Genero una stringa UUID4 e lancio un algoritmo hash come SHA3 su di esso e utilizzo i primi 12 caratteri del risultato. Quindi provo a inserirlo nel mio tavolo. Se fallisce, ho bisogno di generare un nuovo UUID4 e così via ...

Naturalmente, questi sono pensieri molto teorici, perché penso che starò bene con 1000 chiavi all'anno. Ma come accorciare i servizi di url farlo? O non si preoccupano di "imprevedibilità"?

    
posta tjati 10.07.2014 - 11:25
fonte

2 risposte

4

Se vuoi imprevedibile allora hai bisogno di imprevedibile . Se inizi con un UUID e poi giochi con le funzioni hash, non ottieni valori imprevedibili; ottieni solo valori che "sembrano casuali".

Quindi, usa solo un PRNG protetto da crittografia . Questo significa /dev/urandom (o qualcosa di simile, ad esempio java.security.SecureRandom se ti stai sviluppando in Java).

Questo semplice comando (funziona su qualsiasi sistema Linux) genera valori di 12 caratteri casuali e imprevedibili:

dd if=/dev/urandom bs=9 count=1 2>/dev/null | base64 | tr '+/' '_-'

I caratteri usati sono lettere (maiuscole e minuscole), cifre, '_' e '-'. Pertanto, dovrebbero adattarsi bene all'URL (raw Base64 produce i segni "+" e "/", che possono essere problematici, ma lo aggiusto con la chiamata tr ). L'entropia è 72 bit, il che significa che le stringhe fanno parte di uno spazio di dimensioni 2 72 . Se generi 1000 stringhe, la probabilità di colpire una delle stringhe è 1000/2 72 , cioè circa 1 su 4.7 miliardi di miliardi (quindi l'attaccante dovrebbe essere super-fortunato).

La traduzione in qualsiasi particolare quadro di programmazione viene lasciata come esercizio. Il punto davvero importante è usare un PRNG strong, non cose che sono semplicemente intese come "statisticamente casuali" come il RANDOM() di SQL o l'UUID di SQL. Questa è sicurezza: vogliamo la casualità crittografica , non statistica , perché dobbiamo sconfiggere un aggressore intelligente .

    
risposta data 10.07.2014 - 16:19
fonte
2

Vado per un certo controvalore e aggiungo un po 'di casualità ad esso e non memorizzo tutti i singoli risultati. Memorizzare tutti i risultati sembra complicato. Se si utilizza un contatore a 4 byte e lo si combina con un valore generato casualmente a 4 byte, base32 codifica il risultato. Con un contatore da 4 byte è possibile generare collegamenti 4294967296 e il 4 byte di casualità dovrebbe essere sufficiente per impedire a qualcuno una facile intuizione. Se hai bisogno di generare più link, usa più byte, se hai bisogno di più casualità usa più byte casuali. Utilizzando un contatore, è sufficiente memorizzare solo un valore. Invece di usare un contatore puoi anche usare l'ora corrente in millisecondi. Questo è ancora più semplice e la possibilità di generare lo stesso URL quando si genera un numero di URL in un breve periodo di tempo è molto piccola poiché si ha sempre il valore casuale.

    
risposta data 10.07.2014 - 13:00
fonte

Leggi altre domande sui tag