Generazione di un token non percettibile per e-mail di conferma

12

Sto generando un token da utilizzare quando si fa clic sul collegamento in un'e-mail di verifica. Ho intenzione di utilizzare uniqid () ma l'output sarà prevedibile permettendo a un utente malintenzionato di aggirare l'e-mail di conferma mail. La mia soluzione è di cancellarlo. Ma non è ancora abbastanza, perché se viene scoperto l'hash che sto usando, sarà comunque prevedibile. La soluzione è salarla. Che non sono sicuro di come fare perché se uso una funzione per dare sale variabile (ad esempio in pseudocode hash(uniqid()+time()) ), allora l'unicità dell'hash non è più garantita? Dovrei usare un hash costante e sarebbe abbastanza buono (ad esempio hash(uniqid()+asd741) )

Penso che tutte le risposte perdano un punto importante. Deve essere unico. Cosa succede se openssl_random_pseudo_bytes() procura lo stesso numero due volte? Quindi un utente non sarebbe in grado di attivare il suo account. La contro tesi della gente è improbabile che produca lo stesso numero due volte? Ecco perché stavo considerando uniqid() perché l'output è unico.

Credo che potrei usarli entrambi e aggiungerli insieme.

    
posta Celeritas 08.08.2013 - 22:53
fonte

4 risposte

25

Vuoi una casualità inconcepibile. Quindi, usa casualità non percettibile. Usa openssl_random_pseudo_bytes() che si inserirà nel PRNG strong crittograficamente . Non utilizzare rand() o mt_rand() , poiché questi sono prevedibili ( mt_rand() è statisticamente buono ma non regge contro attaccanti senzienti). Non scendere a compromessi, usa un buon PRNG. Non cerca di creare qualcosa tu stesso lanciando la funzione di hash e simili; solo il dolore si trova alla fine di questo percorso.

Genera 16 byte, quindi li codifica in una stringa se hai bisogno di una stringa. bin2hex() codifica in esadecimale; 16 byte diventano 32 caratteri. base64_encode() codifica in Base64; 16 byte diventano 24 caratteri (gli ultimi due dei quali sono segni '=').

16 byte è 128 bit, questo è il "valore sicuro" che rende le collisioni così assolutamente improbabili da non doverti preoccupare di esse. Non andare al di sotto di questo se non hai una buona ragione (e, anche in questo caso, non andare comunque al di sotto dei 16).

    
risposta data 08.08.2013 - 23:11
fonte
16

Assicurati di avere supporto OpenSSL , e non fallirai mai con questo one-liner

$token = bin2hex(openssl_random_pseudo_bytes(16));
    
risposta data 08.08.2013 - 23:05
fonte
1

In PHP 7, puoi semplicemente usare random_bytes :

Generates an arbitrary length string of cryptographic random bytes that are suitable for cryptographic use, such as when generating salts, keys or initialization vectors.

Quindi per generare un token esadecimale a 16 byte si dovrebbe fare:

$token = bin2hex(random_bytes(16));

Formalmente, non vi è alcuna garanzia che tutti i numeri siano unici. Ma è improbabile che una collisione possa accadere che starai meglio a preoccuparti di essere colpito da un metroorite.

    
risposta data 14.11.2018 - 16:39
fonte
-1

Questa è la funzione che uso per generare un token casuale in PHP:

<?php
function generateToken($length = 24) {
        if(function_exists('openssl_random_pseudo_bytes')) {
            $token = base64_encode(openssl_random_pseudo_bytes($length, $strong));
            if($strong == TRUE)
                return strtr(substr($token, 0, $length), '+/=', '-_,'); //base64 is about 33% longer, so we need to truncate the result
        }

        //fallback to mt_rand if php < 5.3 or no openssl available
        $characters = '0123456789';
        $characters .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+'; 
        $charactersLength = strlen($characters)-1;
        $token = '';

        //select some random characters
        for ($i = 0; $i < $length; $i++) {
            $token .= $characters[mt_rand(0, $charactersLength)];
        }        

        return $token;
}
?>
    
risposta data 08.08.2013 - 23:02
fonte

Leggi altre domande sui tag