Generazione di keypair RSA (sicurezza / prestazioni) nel servizio REST

0

Esiste un servizio API REST. Un endpoint è responsabile della creazione di account utente. Ogni utente dovrebbe avere una coppia di chiavi RSA generata e memorizzata su un server. Per proteggere le chiavi private da essere lette da un possibile avversario, le chiavi private sono codificate in PEM. Il formato PEM è crittografato con AES-256-CBC utilizzando una passphrase. La passphrase è uguale a quella utilizzata da un utente per accedere.

Finora ho generato una coppia di chiavi all'interno di un gestore di richieste. Ma in alcuni casi occorrono 10 secondi, il che è indesiderabile.

Quale sarebbe una soluzione sicura e orientata al rendimento per questo problema? Voglio evitare di memorizzare una passphrase in testo semplice per una successiva crittografia.

    
posta antagon 20.06.2017 - 13:49
fonte

2 risposte

2

Se ho capito bene, stai generando chiavi RSA su un server, mantenendo la chiave pubblica sul server e inviando le chiavi private agli utenti. Raccomanderei invece di generare le chiavi sul lato client e inviare la chiave pubblica al server. Ecco come dovrebbe essere usata la crittografia asimmetrica.

Il tempo necessario per generare le chiavi RSA è inerente all'algoritmo RSA, non c'è molto che tu possa fare al riguardo.

Se devi generare le chiavi sul server, ti suggerisco di passare da RSA a ECC . Il processo di generazione delle chiavi è molto più veloce. Esistono molte librerie per usare ECC. L'algoritmo Curve25519 è una buona scelta, ma ci sono alternative .

Inoltre, se hai solo bisogno di proteggere le comunicazioni tra il client e il server, utilizzare TLS 1.2 (o 1.3) con i certificati client è una soluzione migliore rispetto al rollare la tua crittografia.

    
risposta data 21.06.2017 - 14:38
fonte
1

La tua descrizione del servizio, anche nei commenti, non è completamente chiara, quindi descriverò alcune linee guida generali per ciò che devi fare per un sistema di questo tipo, insieme al perché e al modo.

  1. Non generare chiavi asimmetriche sul server. Cioè, quando possibile, il lavoro del cliente. Non solo evita di legare le risorse del server e aprirti agli attacchi di negazione del servizio, ma evita il server, anche se per un breve periodo, di accedere alla chiave privata del client.
  2. Cripta la chiave privata sul client, prima di inviarla al server. Un sistema in cui il server può mai vedere la chiave privata del client e potrebbe teoricamente memorizzarlo o decrittografarlo non ci si può fidare.
  3. Hash la password dell'utente tramite una funzione di hashing della password sicura (o funzione di derivazione della chiave) sul client, prima di inviarla al server. Quando usi uno schema come questo, dove gli utenti hanno le chiavi private che vengono crittografate usando il loro password, non è possibile consentire al server di conoscere la password dell'utente anche durante la creazione dell'account o il login.
  4. Utilizza diversi sali nella funzione di derivazione della chiave per la crittografia lato client della chiave e l'hashing sul lato client della password per l'autenticazione. Va bene usare lo stesso algoritmo e anche lo stesso fattore di lavoro per entrambi chiave di crittografia derivata da password e hashing della password sul lato client, ma dovrebbero avere diversi sali in modo che, dato un hash (che il client esegue quando invia l'hash della password al server), la chiave di crittografia non possa essere determinata da alcuna operazione .
  5. Hash di nuovo l'hash della password fornito dal client prima di archiviare / confrontare sul server. Anche se è effettivamente derivato dalla password inserita dall'utente anziché essere la stessa password, devi ancora re-hash la password hash prima di archiviarlo, altrimenti un attore malintenzionato che si impossessa della tabella delle password potrebbe autenticarsi come qualsiasi utente (anche se non avrebbero abbastanza informazioni per decrittografare le chiavi private). Questo round finale di hashing non deve essere particolarmente lento, in quanto l'input è già l'output di forza bruta di una funzione di hashing della password / di derivazione della chiave.

Alcune note:

  • Approvo il suggerimento di A. Hersean di usare ECC invece di RSA, se puoi. RSA è un algoritmo asimmetrico più vecchio e più ampiamente implementato, ma è anche più lento generare e utilizzare le chiavi e le chiavi stesse sono più lunghe, rendendo necessaria una maggiore memorizzazione.
  • Si cita (in un commento) usando la crittografia per proteggere dall'iniezione SQL. Questa è una soluzione non ingegnerizzata a un problema già risolto. È come cercare di usare una grattugia per tagliare il pane, quando hai un coltello da pane proprio lì: è un grande sforzo per qualcosa che probabilmente non funzionerà nemmeno nel modo giusto. Usa lo strumento giusto per il lavoro; la soluzione per SQLi consiste nell'utilizzare query parametrizzate / stored procedure per l'accesso al database e non concatenare mai le stringhe fornite dall'utente nelle query (e, se ciò non riesce, perché per qualche motivo è necessario per consentire a un utente fornito stringa da utilizzare per una parte della query che non può essere parametrizzata, utilizzare una funzione di sanitizzazione dell'input ben implementata e attendibile piuttosto che crittografare la stringa o provare qualsiasi altro modo per renderla sicura da soli).
  • Ci sono molti, molti più rischi per le app Web e i servizi Web rispetto a SQLi. Dal momento che il tuo sistema sembra coinvolgere il passaggio dei messaggi, alcuni di quelli ovvi da considerare sono XSS e CSRF, anche se i servizi REST dovrebbero essere al sicuro da quelli. Altri sono attacchi ricorsivi o esterni di entità XML (se si utilizza XML), attacchi di deserializzazione (se si utilizza qualsiasi tipo di oggetti serializzati) e, naturalmente, le innumerevoli forme di attacchi denial-of-service (di cui ti sei già esposto a uno, consentendo ai client di dire al server di eseguire un'operazione costosa).
  • Crypto è davvero, davvero difficile da ottenere. Dovresti avere qualcuno che sa davvero cosa stanno facendo e guarda il tuo design completo (non solo il riassunto parziale che ci hai fornito qui), e quindi dare un'altra occhiata al tuo codice, perché la crittografia può essere incredibilmente fragile e se ottieni una piccola cosa sbagliata, può diventare inutile.
risposta data 28.09.2018 - 10:18
fonte

Leggi altre domande sui tag