Questi metodi crittografici sono sulla traccia giusta?

2

So che non dovremmo mai "lanciare la nostra crittografia", ma voglio capire il funzionamento interno. Ho scritto le seguenti due funzioni di crittografia / decrittografia in PHP:

function encrypt($message) {

    $key = hash("sha256", base64_decode($secretpw64));    // get key from secret password
    $iv = random_bytes(16);                               // create an iv
    $output = openssl_encrypt($message, "AES-256-CBC", $key, 0, $iv);    // encrypt using openssl

    return implode(".", array(base64_encode($iv), $output));             // join iv.output
}

function decrypt($message) {

    $key = hash("sha256", base64_decode($secretpw64));    // get key from secret password
    $segs = explode(".", $message);    // separate the message
    $iv = base64_decode($segs[0]);     // get the iv
    $emsg = $segs[1];                  // get the encrypted message

    return openssl_decrypt($emsg, "AES-256-CBC", $key, 0, $iv);    // decrypt and return
}

Suppongo (che so che non dovrei) che random_bytes produce un insieme casuale di byte casuali e sicuri, che secondo i documenti lo fa. Io uso anche un vettore di inizializzazione ( iv ) che fa sì che la crittografia sia diversa ogni volta in base allo stesso input.

Questo codice è fondamentalmente difettoso dal punto di vista della sicurezza in alcun modo? E, supponendo che non lo sia, è hash-then-encrypt (o simile) il prossimo" level up "?

    
posta Antinous 26.04.2018 - 14:15
fonte

1 risposta

2

Ci sono alcuni problemi con il tuo codice.

$key = hash("sha256", base64_decode($secretpw64));

SHA-256 è molto veloce e non c'è sale qui. Un utente malintenzionato può creare un dizionario di (secretpw64, chiave) e ottenere la chiave attraverso un attacco al dizionario veloce e sporco. Come altri hanno già detto, considera l'utilizzo di un PBKDF. Anche l'iterazione dello SHA per, diciamo, 1000 volte può essere OK. Per ulteriori informazioni su come ottenere una chiave crittografica da una password, vedere questa risposta su Crypto.SE .

 $iv = random_bytes(16); 

Si presume che random_bytes sia un PRNG crittograficamente sicuro, ma questo non è qualcosa che si può maneggiare. Stai attento!

Inoltre, dai un'occhiata a come vengono generati gli IV.

Se l'applicazione si blocca, o si spegne il sistema operativo e si ricomincia, il primo IV è sempre lo stesso? Potrebbe succedere.

Se lo fa, un utente malintenzionato può bloccare l'applicazione e ottenere due messaggi con la stessa chiave e IV ogni volta che lo desidera . Non c'è bisogno di aspettare per 2 ^ 64 messaggi!

La riservatezza non è tutto in sicurezza. L'integrità e l'autenticazione dei messaggi sono importanti anche nella maggior parte delle applicazioni.

Come risulta, CBC è anche vulnerabile agli attacchi di "bit flipping" (aka byte flipping).

Fondamentalmente, puoi capovolgere un byte nel testo cifrato in modo da capovolgere un byte corrispondente nel testo in chiaro. Questo normalmente confonde il blocco precedente, ma diventa un attacco pratico quando si desidera modificare il primo blocco ed è possibile modificare l'IV o, in alcuni casi, bypassando la convalida dell'input. Per ulteriori dettagli, vedi questo write-up di Defcamp .

Infine, dovresti considerare anche altri attacchi non crittografici, a seconda del modello di minaccia, tra cui:

  • furto / divulgazione di chiavi di crittografia (ad esempio dalla RAM);
  • modifiche dannose o dirottamenti del RNG. Se, per esempio, un attaccante può sostituire il tuo RNG con un PRNG debole, tutto si rompe.
risposta data 26.04.2018 - 20:34
fonte

Leggi altre domande sui tag