Verifica dei messaggi API senza memorizzare la chiave privata?

10

Sono in procinto di implementare un'API pubblica per il mio servizio web. La sicurezza è una preoccupazione fondamentale poiché il denaro è coinvolto.

Sembra che l'attuale pratica comune per "autenticare" gli utenti nelle richieste API sia confermando l'autenticità del messaggio, facendo in modo che l'utente invii un HMAC dei parametri (incluso un nonce univoco) per ogni richiesta.

Questo va bene, ma utilizza un segreto condiviso: sia il server che il client devono memorizzare la chiave privata per generare l'HMAC.

Non mi piace. Qual è il punto di andare a tutto il trambusto con le password saling / hashing, se poi sto andando a memorizzare segreti condivisi non crittografati nel database?

C'è un modo migliore? Stavo pensando di utilizzare GPG e di fornire all'utente la propria chiave pubblica GPG da memorizzare; potrebbero quindi firmare i messaggi usando la loro chiave privata. Tuttavia, temo che questo potrebbe essere un po 'un problema per gli utenti di Windows con cui giocare.

In generale, la chiave pubblica / privata non firma un modo migliore per farlo? Ci deve essere qualche ragione per cui tutti scelgono HMAC con un segreto condiviso ... cosa mi manca?

Ovviamente imporrò limiti alle interazioni con i clienti tramite API, fornirò notifiche e limiterei la rimozione di denaro dal sistema, ma si potrebbero ancora fare molti danni se i segreti condivisi fossero trapelati.

    
posta Jhong 06.06.2013 - 04:45
fonte

3 risposte

1

La crittografia a chiave pubblica è più lenta e richiede più risorse per ottenere la stessa forza crittografica di un segreto condiviso più piccolo.

Vedi: link

Questo probabilmente non costituirà un problema se si costruisce un sistema a basso volume, ma una volta arrivati a sistemi su larga scala, potrebbe essere necessario giustificare i costi aggiuntivi per l'organizzazione e i clienti / clienti.

Se sei preoccupato di memorizzare i segreti simmetrici, dovresti probabilmente crittografarli comunque.

    
risposta data 06.06.2013 - 18:53
fonte
3

Ho fatto la stessa domanda ieri, ma nel frattempo ho trovato quello che credo risponderà a entrambe le nostre domande: SRP. Questa domanda ha la migliore risposta che ho trovato finora. Ecco un riferimento a SRP . Il problema principale con SRP è che non esistono implementazioni moderne che possono essere utilizzate a livello di applicazione.

Modifica per aggiungere ulteriori informazioni dalla mia ricerca:

Ho deciso di utilizzare un archivio di sessione di backup del database, quindi soddisfa ancora la definizione di apolidi. Ciò richiede che SSL sia l'unico protocollo per la comunicazione, che elimina gli attacchi MITM e replay.

  • Utilizza bcrypt per memorizzare le password in DB
  • usa l'autenticazione a due fattori, come Authy o Google Authenticator - questo non soddisfa i tuoi requisiti di nessuna dipendenza esterna, ma nel mio caso sono d'accordo. Impedisce la perdita della password da parte dell'utente - gli attcker hanno ancora bisogno del dispositivo TFA dell'utente.
  • Avere un campo ID sessione e lunghezza sessione (in secondi) in ogni record utente
  • In caso di autenticazione riuscita (autenticazione tipica, l'utente invia userid e password, usa bcrypt to hash password usando hash memorizzato pw da db), confronta hash, ecc)
  • Dopo aver eseguito correttamente la password, genera guide crittografiche valide per il suono e archivia in db, insieme al tempo in cui desideri mantenere viva la sessione
  • invia questo ID di sessione come risposta all'autent
  • se vuoi l'apolide vera, richiedi al cliente l'hash HMAC ogni richiesta con questo ID - può conservare l'ID, non deve inviarlo a te
  • verifica la richiesta di hashing con sid memorizzato, confronta con hash che ti ha inviato
  • su ogni richiesta, verificare che non sia scaduto il tempo di scadenza - non è necessario un processo che verifica la scadenza, basta controllare ogni volta che il client tenta una chiamata API.

Ho compromesso e utilizzato la memorizzazione sicura della sessione di express-js, che utilizza un cookie lato client, ma il cookie è firmato con un segreto condiviso che tutti i miei server delle applicazioni conoscono, quindi soddisfa la definizione stateless in quanto il cookie non è univoco per il server al quale è connesso il client, poiché il cookie è ancora nel dominio del mio server delle app

    
risposta data 06.06.2013 - 18:06
fonte
1

user26802 è corretto, la risposta è velocità. Immagina un'API come Amazon SQS, in cui i clienti stanno scendendo e raccolgono un sacco di piccoli messaggi a tariffe elevate, con una crittografia lenta sul client e una decrittazione lenta sul server che rallenterebbe notevolmente il servizio.

Si potrebbe immaginare un approccio blended in cui i client hanno effettuato una chiamata autenticata con la firma di una chiave privata per stabilire una chiave simmetrica a breve termine. Se le tue chiavi fossero state compromesse, avresti solo una breve finestra di vulnerabilità prima della scadenza delle chiavi. Ora se l'attaccante ha un accesso persistente al tuo sistema, non stai meglio.

Un'altra cosa da tenere a mente, se un utente malintenzionato ha compromesso il tuo keystore e può rubare tutte le chiavi di firma, potrebbe anche essere in grado di sostituire una chiave pubblica ed essere comunque in grado di creare richieste come un altro utente.

    
risposta data 18.06.2013 - 18:41
fonte

Leggi altre domande sui tag