Posso usare la stessa password sia per SRP che per la crittografia lato client?

13

Supponiamo che un server meno affidabile sia utilizzato per archiviare i dati riservati degli utenti (crittografati sul lato client) e che entrambe le attività - autenticazione e crittografia / decrittografia - debbano essere eseguite con una singola password. Basterebbe a:

  1. Rafforza la password con una funzione di derivazione a chiave lenta e un banale sale [1] , che produce k ;
  2. Utilizza k come "password" SRP, autenticandosi con il server e ricevendo il testo cifrato;
  3. Decifra il testo cifrato per ottenere le chiavi effettive da utilizzare per la firma, la crittografia, ecc.

Un server dannoso (a basso rischio) dovrebbe eseguire un attacco di dizionario offline - sul verificatore o su il testo cifrato - per recuperare k , mentre un aggressore esterno (rischio maggiore) sarebbe solo in grado di fare attacchi online (poiché non ha accesso né al verificatore né al testo cifrato), a meno che non ottenga una copia del database - che sarebbe basta metterlo in una situazione simile del server [2] .

Questo ragionamento è corretto? Qualche difetto che non avevo previsto? Alcune note:

  1. Dico che il sale è "banale" perché è: a) vuoto; b) derivato dal nome utente; c) casuale, ma il server lo darà a chiunque lo richieda. Normalmente sarebbe una preoccupazione , ma qui la chiave non lascia mai la macchina client, quindi non importa se due utenti hanno la stessa chiave.
  2. Una delle mie preoccupazioni è che un utente malintenzionato potrebbe creare una tabella arcobaleno indirizzata a un particolare utente, quindi ottenere il database e quasi immediatamente accedere come tale utente, poiché la forzatura bruta del verificatore o del testo cifrato è più veloce se si dispone di elenco delle chiavi candidate piuttosto che un elenco di password candidate (che devono ancora essere allungate prima di diventare chiavi).

    Ovviamente, se un hacker ha quella potenza di calcolo (se la password è debole) qualsiasi testo cifrato trapelato sarà eventualmente incrinato, ma il danno futuro potrebbe essere evitato se il server fosse più strong contro questo scenario (prima di apprendere su SRP che ho progettato un protocollo più contorto che ne tenesse conto, ma era più dispendioso e aveva domande aperte).

  3. [Per il mio caso particolare] Tutti questi sono fuori dallo scopo della domanda (supponiamo già capito): tutte le comunicazioni saranno su TLS, l'opzione per usare le chiavi appropriate e l'autenticazione a 2 fattori sarà data (ma non mandata) , il codice client non proviene dal server meno affidabile, verranno utilizzati i MAC, ecc.
posta mgibsonbr 14.06.2013 - 11:08
fonte

3 risposte

6

Come esercizio di sana prudenza, consiglierei quanto segue:

  • Quando si ricava la chiave k dalla password dell'utente, allungarla e dividerla in due. Usa la prima metà per SRP, la seconda metà per la crittografia. Un modo semplice per ottenerlo è di hash k con SHA-256, che fornisce 256 bit che possono quindi essere suddivisi in due chiavi a 128 bit. In alternativa, utilizza una funzione di derivazione della chiave con dimensioni di output regolabili, come PBKDF2 .

    Il punto qui è che vogliamo evitare qualsiasi "interazione" indesiderata, per quanto non plausibile, tra la crittografia simmetrica e i calcoli eseguiti in SRP. Intercalare uno strato di unidireità tra le due sottochiavi dovrebbe prevenire tali problemi (supponendo che SHA-256 si comportino più o meno come un oracolo casuale ).

  • Si cripta per un motivo: si deve quindi presumere che un utente malintenzionato possa osservare, ad un certo punto, il blob dei dati crittografato simmetricamente. Altrimenti, quale sarebbe il punto di crittografia? Ma se tale intercettazione è possibile, allora il sale deve essere corretto. Un sale vuoto non lo avrebbe tagliato, perché tutti gli utenti avrebbero usato lo stesso sale, consentendo ottimizzazioni degli attacchi (vale a dire tavoli arcobaleno).

    Ora c'è un punto interessante, che è che SRP stesso include un po 'di elaborazione del sale. Dai un'occhiata a RFC 5054 , che descrive come integrare SRP in un handshake TLS. Nel passaggio iniziale, il client (nel suo ClientHello ) invia l'identità dell'utente ( I ). Il server risponde con alcuni messaggi, incluso il ServerKeyExchange che contiene (tra gli altri valori) il sale s . Quindi hai, proprio qui, il tuo "server che invia il sale a tutti quelli che lo chiedono".

L'elaborazione della password effettiva, in SRP, è il calcolo di x = SHA1(s | SHA1(I | ":" | P)) . Questa è una funzione di hashing della password salata, ma insufficientemente iterata. Questo è un difetto noto in SRP come è attualmente definito. Tuttavia, sarebbe banale sostituire questa operazione con una funzione di hashing delle password complesse , purché il client e il server siano d'accordo.

Questo produce lo schema seguente:

  • Al momento della registrazione, l'utente sceglie la sua password P e viene generata una percentuale saltuale dis (ad esempio, 128 bit da un PRNG crittograficamente strong).
  • Da P e s , viene applicata una strong funzione di hashing della password (come bcrypt ), che produce qualche valore intermedio z , che abbiamo poi hash con SHA-512, ottenendo 512 bit. Questi 512 bit sono suddivisi in due metà a 256 bit; la prima metà sarà il valore x per SRP, mentre la seconda parte (chiamiamola y ) verrà utilizzata per la crittografia simmetrica.
  • Al momento dell'accesso, il client invia prima il nome utente ( I ) al server e ottiene il sale s . Lo stesso calcolo di x e y viene eseguito di nuovo. La parte x viene utilizzata per SRP, la parte y per decrittografare il blob memorizzato sul server.

Questo schema combina tutti i punti discussi sopra. La derivazione da password a chiave utilizza una funzione appropriata con un buon sale casuale; c'è uno strato di isolamento di SHA-512 tra i due usi della password; non è necessario alcun ulteriore scambio di messaggi rispetto all'SRP di base. In effetti, ciò che suggerisco qui è un rafforzamento dell'hash per le password fatto in SRP, con un ulteriore rilascio di una chiave derivata da password per la tua esigenza di crittografia simmetrica.

Si noti che mentre è possibile stabilire un tunnel SSL / TLS e quindi eseguire SRP in esso, è anche possibile seguire la strada RFC 5054 e utilizzare SRP per l'handshake TLS. Ciò richiederebbe il controllo sia del codice client che del server, inclusa l'implementazione SRP, poiché sto suggerendo qui di modificare il processo di derivazione da password a chiave (vale a dire di rafforzarlo). Corrispondentemente, il cliente deve già avere il codice necessario. In un contesto Web-Javascript, è necessario prima un SSL / TLS "normale", anche se a quel punto i vantaggi di SRP diventano piuttosto ridotti.

Lasciando che il server invii il valore salt a chi chiede, come inerente a SRP, non è un problema serio. I sali non hanno bisogno di segretezza. Mantenere segreto i valori del sale non significa danno , ma questo è solo un obiettivo secondario. Il punto saliente di sali è unicità . Non lasciare che un prurito ingiustificato per la segretezza si imbatti nel percorso dell'unicità.

    
risposta data 01.07.2013 - 23:40
fonte
5

Suppongo che intendi che i dati sono crittografati utilizzando la chiave k (lo stesso valore utilizzato come password SRP). Non hai specificato questo, quindi se questo non è quello che avevi in mente, modifica la tua domanda.

Sì, questo è uno schema ragionevole.

Suggerirei di utilizzare il nome utente dell'utente più l'identificatore del server (ad esempio, il nome di dominio) come sale per la funzione di derivazione a chiave lenta, se possibile. Potresti anche renderlo un valore casuale che è pubblico e diverso per ogni utente.

Tabelle arcobaleno: Le tabelle arcobaleno non aiutano molto l'aggressore, dal momento che il costo di creare le tabelle arcobaleno è tanto quanto provare un gruppo di password candidate. Le tabelle Rainbow aiutano solo quando si attacca più volte (ad esempio, attaccando più utenti) e si desidera ammortizzare il costo. Se ritieni che un nome utente sia molto comune (ad esempio alice ), è sarebbe possibile creare una tabella arcobaleno specifica per alice (un calcolo una tantum) e quindi usarlo per attaccare più server, nella speranza che esista un account denominato alice su tutti quei server. Questo tuttavia ti dà una certa velocità solo se trovi più utenti con lo stesso nome utente (presumibilmente, su più server diversi). Non penso che sia una grande minaccia nella pratica. Se sei preoccupato, può essere evitato utilizzando come sale un valore casuale diverso per ogni utente o utilizzando la combinazione del nome utente dell'utente e dell'identificatore del server come salt.

Altro: Il più grande punto debole è probabilmente il punto in cui il client riceverà il codice per decifrare il testo cifrato. Se si tratta di un'applicazione client dedicata, è possibile crearla nel codice del programma client. Ma se il client accede a un sito Web tramite un browser Web e il codice di decrittografia viene fornito dal server come Javascript (per esempio), allora non hai acquisito tutta la sicurezza che pensi di avere, dal momento che un malware / compromesso / spoof server può inviare Javascript dannoso che ruba la password dell'utente.

    
risposta data 30.06.2013 - 04:09
fonte
2

C'è un altro approccio che potresti voler prendere in considerazione. Prendi la password utente p, applica un salt e passalo attraverso la derivazione della chiave per generare una chiave più lunga k. Quindi dividi k in due parti aeb. La prima parte, a, viene utilizzata per crittografare i dati e la seconda parte, b, viene utilizzata per autenticare il server.

Questo soddisfa la tua facilità d'uso e i requisiti di sicurezza?

    
risposta data 01.07.2013 - 19:12
fonte