Perché utilizzare una chiave e un segreto API?


93

Mi sono imbattuto in molte API che forniscono all'utente sia una chiave API che un segreto . Ma la mia domanda è: qual è la differenza tra i due?

Ai miei occhi, una chiave può essere sufficiente. Diciamo che ho una chiave e che solo io e il server lo sappiamo. Creo un hash HMAC con questa chiave ed eseguo una chiamata API. Sul server, creiamo nuovamente l'hash HMAC e lo confrontiamo con l'hash inviato. Se è lo stesso, la chiamata viene autenticata.

Allora perché usare due chiavi?

Modifica: o quella chiave API è utilizzata per cercare il segreto API?


Risposte:


46

La crittografia con chiave segreta si basa sull'utilizzo della stessa chiave per codificare e successivamente decodificare un messaggio. Quindi, solo chi conosce il "segreto" può leggere il messaggio.

La sicurezza RSA si basa su 2 chiavi corrispondenti. C'è una chiave pubblica per ogni utente e tutti possono (dovrebbero) conoscerla. C'è anche una chiave privata che solo l'utente dovrebbe conoscere. Un messaggio crittografato dalla chiave pubblica può essere decrittografato solo dalla chiave privata e viceversa.

Quindi, se voglio inviarti un messaggio che solo tu puoi leggere, ottengo (dalla rete) la tua chiave pubblica, cripto il messaggio con quella chiave e tu sei l'unica persona che può decriptarlo.

Oppure, se voglio dimostrarti che ho inviato un messaggio, posso crittografare il messaggio con la mia chiave privata, dirti (in testo aperto o in un altro messaggio) come è stato crittografato. Quindi potresti decriptare il messaggio con la mia chiave pubblica e, se diventa leggibile, sai che è venuto da me.

Questa forma di crittografia è piuttosto intensiva per il computer, quindi ciò che a volte viene fatto è crittografare una "chiave segreta" una tantum con la tecnologia RSA, quindi crittografare il resto del messaggio con la chiave segreta, quindi crittografare la mia firma nel secondo modo. Quindi inverti questo processo, quindi se il messaggio e la firma sono leggibili, tu e solo tu puoi leggerlo e sei sicuro che ho inviato il messaggio.

O

puoi visitare questo link per una spiegazione più dettagliata.

Come funzionano le chiavi API e le chiavi segrete?


9
Buona risposta, ma quando uso segreti e chiavi API con Facebook o Gmail, ecc., Non devo in nessun momento crittografare o hash. In questi casi, qual è lo scopo dei segreti e delle chiavi API?
Quintonn

2
Usando Facebook come esempio ci sono due scenari che useresti app_secret. Il primo non richiede hashing. Viene utilizzato principalmente per impedire il dirottamento dell'URL di reindirizzamento. Dopo che un utente ha effettuato l'accesso e ha concesso alla tua app l'accesso se Facebook avesse inviato il token di accesso direttamente all'URL di reindirizzamento, non avresti modo di verificare se il token di accesso provenisse da Facebook. Potrei inviare il mio token di accesso al tuo URL di reindirizzamento ed eseguire azioni di Facebook che verrebbero dalla tua API. Invece Facebook invia un codice all'URL di reindirizzamento. L'API quindi scambia il codice con il token di accesso effettivo.
Ryan Thomas,

2
Durante l'ultima parte, scambiando il codice con il token di accesso effettivo, Facebook si aspetta che la tua API verifichi la sua identità con una firma. In questo scenario non richiedono crittografia a chiave pubblica per la firma, si fidano semplicemente di te per mantenere la tua app segreta veramente segreta e per usarla come firma. Mi è sempre sembrato sciocco non andare avanti e utilizzare una funzione unidirezionale per generare una firma, ma suppongo che abbiano ragioni come le prestazioni per accontentarsi dell'uso diretto del segreto dell'app.
Ryan Thomas,

Nel secondo caso d'uso utilizzi l'hashing crittografico. Dopo aver ottenuto l'effettivo access_token per iniziare a interagire con Facebook, potresti volere una maggiore sicurezza per impedire che la tua app venga impersonata. Nella console dell'app Facebook puoi attivare una funzionalità che richiede che ogni richiesta API di Facebook dalla tua app includa la tua firma oltre al token di accesso. Sto solo indovinando le loro motivazioni, ma penso che a questo punto non vogliano che tu invii ripetutamente app_secret come firma con ogni richiesta. Più lo invii, maggiori sono le possibilità che app_secret venga compromessa.
Ryan Thomas,

1
Suppongo che da quando hai attivato questa funzione di sicurezza aggiuntiva, hai anche preso una decisione per consentire il sovraccarico di prestazioni extra di Facebook che verifica la tua firma con una chiamata hash crittografica alla fine. Comunque in questo scenario passi due valori con le tue richieste API di Facebook. Access_token e un valore denominato appsecret_proof che funge da firma. La prova del segreto dell'app viene generata dall'hash crittografico di access_token utilizzando app_secret come chiave.
Ryan Thomas,

55

Hai bisogno di due chiavi separate, una che dica loro chi sei e l'altra che dimostri che sei chi dici di essere .

La "chiave" è il tuo ID utente e il "segreto" è la tua password. Usano semplicemente i termini "chiave" e "segreto" perché è così che l'hanno implementato.


1
E se comunichi tramite https? Qual è il punto di crittografare il tuo messaggio con una chiave segreta, allora?
kamuniaft

6
Il punto è sempre quello di ridurre il rischio. Se la comunicazione https è compromessa, un utente malintenzionato in grado di leggere la tua richiesta non sarà in grado di crearne di nuove. Se la tua API sta per classificare le immagini dei gatti, non è un grosso problema, se è un'API di pagamento è meglio che tu abbia più livelli di sicurezza :)
Yall

Suppongo che lo scopo siano due chiavi separate, perché utenti diversi di una singola app client possono avere segreti diversi, altrimenti se avessero tutti lo stesso segreto, avere una chiave non sarebbe utile. Destra?
Honey

Perché queste API non utilizzano l' Bearer:autenticazione per questo? Avresti un ID e un PWD lì.
Stefan Haberl

7

Risposta semplice, se ho capito bene ...

Se utilizzi la tua chiave API per la crittografia, come farà il servizio a sapere chi li sta contattando? Come decifreranno quel messaggio?

Usi la chiave API per dichiarare chi sei, questo è ciò che stai inviando in testo normale. Il SEGRETO ti chiave non la mandi a nessuno. Lo usi semplicemente per la crittografia. Quindi si invia il messaggio crittografato. Non si invia la chiave utilizzata per la crittografia, che vanificherebbe lo scopo.


Tu fai. Si invia la chiave API al server. Quindi, questo significa che stai dando quel valore a chiunque possa intercettare la tua comunicazione con il server.
ancajic

Quasi tutte le API che ho visto ti hanno inviato sia la chiave che il segreto al server. La connessione al server è crittografata teoricamente con lo stesso livello di sicurezza. Ma non lo do mai a nessun altro oltre al server.
sudo

Non ho mai visto l'invio secretin testo normale. Puoi darmi un link? Quello che ho visto sta usando secretper crittografare alcuni dati. E insieme ai dati crittografati, inviare in apiKeymodo che il server sappia come decrittografare i dati.
ancajic

twilio.com/docs/sms/tutorials/… e nexmo.github.io/Quickstarts/sms/send sono gli esempi che ho visto che mi hanno spinto a cercare su StackOverflow.
sudo

Twilio non sta usando esattamente questi termini. Ma Nexmo certo è ... Ma, dopo una rapida occhiata, sembra che essi sono solo chiamando i dati secreted apiKeye quello che effettivamente facendo è usernamee password. Che è una cosa completamente diversa ...
ancajic

3

Ci sono risposte che spiegano qual è la chiave segreta e (pubblica). È una coppia di chiavi pubblica-privata a cui danno nomi confusi. Ma nessuno dice perché le API richiedono entrambi e molte API ti danno solo un segreto! Inoltre, non ho mai visto nessun documento API che spieghi perché hanno due chiavi, quindi il meglio che posso fare è speculare ...

È meglio inserire solo la tua chiave pubblica nella tua richiesta e firmare la richiesta localmente con la tua chiave privata; non dovrebbe essere necessario inviare altro. Ma alcuni se la cavano solo avendo il segreto nella richiesta. Ok, qualsiasi buona API utilizzerà una sicurezza di trasporto come TLS (di solito su HTTPS). Ma stai ancora esponendo la tua chiave privata al server in questo modo, aumentando il rischio che in qualche modo la gestiscano male (vedi: GitHub e il bug di registrazione della password di Twitter scoperto di recente). E HTTPS è teoricamente altrettanto sicuro, ma ci sono sempre difetti di implementazione là fuori.

Ma molte API - in realtà la maggior parte sembra - ti hanno inviato entrambe le chiavi nelle richieste poiché è più facile che costringere le persone a fare le proprie firme; altrimenti non possono avere esempi di cURL puri! In tal caso, è inutile averli separati. Immagino che le chiavi separate siano solo nel caso in cui cambino l'API in un secondo momento per trarne vantaggio. Oppure alcuni hanno una libreria client che potrebbe farlo nel modo più sicuro.


1

Una cosa che non ho visto menzionata qui, sebbene sia un'estensione della risposta di Marcus Adams, è che non dovresti usare una singola informazione sia per identificare che per autenticare un utente se c'è la possibilità di attacchi temporizzati , il che può usa le differenze nei tempi di risposta per indovinare quanto è arrivato un confronto di stringhe.

Se stai utilizzando un sistema che utilizza una "chiave" per cercare l'utente o la credenziale, quella parte di informazione potrebbe essere indovinata in modo incrementale nel tempo inviando migliaia di richieste ed esaminando il tempo impiegato dal tuo database per trovare (o meno trova) un record. Ciò è particolarmente vero se la "chiave" è archiviata in testo normale invece di un hash unidirezionale della chiave. Ti consigliamo di archiviare le chiavi degli utenti in un testo normale o crittografate simmetricamente se devi essere in grado di visualizzare nuovamente la chiave per l'utente.

Avendo una seconda informazione, o "segreto", puoi prima cercare l'utente o la credenziale utilizzando la "chiave", che potrebbe essere vulnerabile a un attacco di temporizzazione, quindi utilizzare una funzione di confronto a tempo per controllare il valore di il segreto".

Ecco l'implementazione di quella funzione da parte di Python:

https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727

Ed è esposto nella hmaclibreria (e probabilmente in altri):

https://docs.python.org/3/library/hmac.html#hmac.compare_digest


Una cosa da notare qui è che non penso che questo tipo di attacco funzionerà su valori che sono sottoposti ad hashing o crittografati prima della ricerca, perché i valori che vengono confrontati cambiano casualmente ogni volta che un carattere nella stringa di input cambia. Ho trovato una buona spiegazione di questo qui .

Le soluzioni per l'archiviazione delle chiavi API sarebbero quindi:

  1. Usa una chiave e un segreto separati, usa la chiave per cercare il record e usa un confronto a tempo per controllare il segreto. Ciò consente di mostrare nuovamente all'utente la chiave e il segreto.
  2. Utilizzare una chiave e un segreto separati, utilizzare la crittografia simmetrica e deterministica sul segreto ed eseguire un normale confronto dei segreti crittografati. Ciò consente di mostrare di nuovo all'utente la chiave e il segreto e potrebbe evitarti di dover implementare un confronto temporizzato.
  3. Usa una chiave e un segreto separati, visualizza il segreto, hash e memorizzalo, quindi fai un normale confronto del segreto con hash. Ciò elimina la necessità di utilizzare la crittografia a due vie e ha l'ulteriore vantaggio di mantenere il tuo segreto al sicuro se il sistema è compromesso. Ha il rovescio della medaglia che non puoi mostrare di nuovo il segreto all'utente.
  4. Utilizzare una singola chiave , mostrarla una volta all'utente, eseguirne l'hashing, quindi eseguire una normale ricerca della chiave crittografata o hash. Questo utilizza una singola chiave, ma non può essere mostrato di nuovo all'utente. Ha il vantaggio di mantenere le chiavi al sicuro se il sistema è compromesso.
  5. Utilizzare una singola chiave , mostrarla una volta all'utente, crittografarla ed eseguire una normale ricerca del segreto crittografato. Può essere mostrato di nuovo all'utente, ma a costo di avere chiavi vulnerabili se il loro sistema è compromesso.

Di questi, penso che 3 sia il miglior equilibrio tra sicurezza e convenienza. L'ho visto implementato su molti siti Web quando si ottengono le chiavi emesse.

Inoltre, invito tutti i veri esperti di sicurezza a criticare questa risposta. Volevo solo che questo fosse un altro punto di discussione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.