Por que usar uma chave e um segredo de API?

92

Eu encontrei muitas APIs que fornecem ao usuário uma chave de API e um segredo . Mas minha pergunta é: qual a diferença entre os dois?

A meu ver, uma chave pode ser o suficiente. Digamos que eu tenha uma chave e apenas eu e o servidor a saibamos. Eu crio um hash HMAC com essa chave e faço uma chamada de API. No servidor, criamos o hash HMAC novamente e o comparamos com o hash enviado. Se for o mesmo, a chamada é autenticada.

Então, por que usar duas chaves?

Editar: ou essa chave de API é usada para pesquisar o segredo da API?

EsTeGe
fonte

Respostas:

45

A criptografia de chave secreta depende do uso da mesma chave para codificar e, posteriormente, decodificar uma mensagem. Assim, apenas quem conhece o "segredo" pode ler a mensagem.

A segurança RSA é baseada em 2 chaves correspondentes. Existe uma chave pública para cada usuário e todos podem (devem) conhecê-la. Também existe uma chave privada que apenas o usuário deve saber. Uma mensagem criptografada pela chave pública só pode ser descriptografada pela chave privada e vice-versa.

Assim, se eu quiser enviar a você uma mensagem que só você pode ler, eu pego (da rede) sua chave pública, criptografo a mensagem com essa chave e você é a única pessoa que pode descriptografá-la.

Ou, se eu quiser provar que enviei uma mensagem, posso criptografar a mensagem com minha chave privada, dizer a você (em texto aberto ou em outra mensagem) como ela foi criptografada. Então você pode descriptografar a mensagem com minha chave pública e, se ela se tornar legível, você saberá que veio de mim.

Essa forma de criptografia consome bastante o computador, então o que às vezes é feito é criptografar uma "chave secreta" única com tecnologia RSA, criptografar o restante da mensagem com a chave secreta e, em seguida, criptografar minha assinatura da segunda maneira. Em seguida, você reverte esse processo para que, se a mensagem e a assinatura puderem ser lidas, você e somente você poderá lê-la e ter a garantia de que enviei a mensagem.

OU

você pode visitar este link para uma explicação mais detalhada.

Como funcionam as chaves API e as chaves secretas?

SALMAN
fonte
9
Boa resposta, mas quando eu uso chaves e segredos de API com Facebook ou Gmail etc, em nenhum momento eu tenho que criptografar ou hash nada. Nesses casos, qual é o objetivo dos segredos e chaves da API?
Quintonn
2
Usando o Facebook como exemplo, existem dois cenários em que você usaria app_secret. O primeiro não requer hashing. É usado principalmente para evitar que seu URL de redirecionamento seja sequestrado. Depois que um usuário faz login e concede acesso ao seu aplicativo, se o Facebook enviar o token de acesso diretamente para a url de redirecionamento, você não terá como verificar se o token de acesso foi do Facebook. Eu poderia postar meu próprio token de acesso à sua url de redirecionamento e executar ações do Facebook que viriam de sua API. Em vez disso, o Facebook envia um código para o URL de redirecionamento. A api então troca o código pelo token de acesso real.
Ryan Thomas
2
Durante a última parte, trocando o código pelo token de acesso real, o Facebook espera que sua api verifique sua identidade com uma assinatura. Nesse cenário, eles não exigem criptografia de chave pública para assinar, eles simplesmente confiam em você para manter o segredo do seu aplicativo e usá-lo como sua assinatura. Sempre me pareceu bobo não ir em frente e usar uma função de mão única para gerar uma assinatura, mas suponho que haja razões, como desempenho, para se conformar com o uso direto do segredo do aplicativo.
Ryan Thomas
No segundo caso de uso, você usa hashing criptográfico. Depois de ter o access_token real para começar a interagir com o Facebook, você pode querer segurança extra para evitar que seu aplicativo seja falsificado. No console do aplicativo do Facebook, você pode ativar um recurso que exige que todas as solicitações de API do Facebook do seu aplicativo incluam sua assinatura, além do token de acesso. Estou apenas adivinhando seus motivos, mas acho que, neste momento, eles não querem que você envie app_secret repetidamente como a assinatura em cada solicitação. Quanto mais você enviar, maior será a chance de app_secret ser comprometido.
Ryan Thomas
1
Suponho que, já que você optou por esse recurso de segurança extra, você também decidiu permitir a sobrecarga de desempenho extra do Facebook ao verificar sua assinatura com uma chamada de hash criptográfica. De qualquer forma, neste cenário, você passa dois valores com suas solicitações de API do Facebook. O access_token e um valor denominado appsecret_proof que serve como sua assinatura. A prova de segredo do aplicativo é gerada por hashing criptográfico do access_token usando app_secret como a chave.
Ryan Thomas
55

Você precisa de duas chaves separadas, uma que diga quem você é e outra que prove que você é quem diz ser .

A "chave" é o seu ID de usuário e o "segredo" é a sua senha. Eles apenas usam os termos "chave" e "secreto" porque foi assim que os implementaram.

Marcus Adams
fonte
1
E se você estiver se comunicando por https? Qual é o objetivo de criptografar sua mensagem com alguma chave secreta, então?
Kamuniaft
6
A questão é sempre reduzir o risco. Se a comunicação https estiver comprometida, um invasor que possa ler sua solicitação não conseguirá forjar novas. Se sua API está prestes a classificar imagens de gatos, não é grande coisa, se é uma API de pagamento é melhor você ter várias camadas de segurança :)
Yall
Suponho que o objetivo são duas chaves separadas porque diferentes usuários de um único aplicativo cliente podem ter segredos diferentes, caso contrário, se todos tivessem o mesmo segredo, ter uma chave não seria útil. Certo?
Honey
Por que essas APIs não usam Bearer:autenticação para isso? Você teria um ID e um pwd lá.
Stefan Haberl
7

Resposta simples, se entendi bem ...

Se você usar sua chave de API para criptografia, como o serviço saberá quem está entrando em contato com eles? Como eles vão descriptografar essa mensagem?

Você usa a chave API para indicar quem você é; isso é o que você está enviando em texto simples. A chave SECRETA que você não envia a ninguém. Você simplesmente o usa para criptografia. Então você envia a mensagem criptografada. Você não envia a chave que foi usada para criptografia, pois isso anularia o propósito.

ancajico
fonte
Você faz. Você envia a chave API para o servidor. Portanto, isso significa que você está dando esse valor a qualquer pessoa que possa estar interceptando sua comunicação com o servidor.
ancajic
Quase todas as APIs que vi enviam a chave e o segredo para o servidor. A conexão com o servidor é criptografada teoricamente com o mesmo nível de segurança. Mas nunca dou a ninguém além do servidor.
sudo
Nunca vi envio de secrettexto simples. Você pode me dar um link? O que vi está usando secretpara criptografar alguns dados. E junto com os dados criptografados, enviar apiKeypara que o servidor saiba como descriptografar os dados.
ancajic
twilio.com/docs/sms/tutorials/… e nexmo.github.io/Quickstarts/sms/send são os exemplos que vi que me levaram a pesquisar no StackOverflow.
sudo
Twilio não está exatamente usando esses termos. Mas Nexmo com certeza é ... Mas, após uma rápida olhada, parece que eles estão apenas chamando os dados secrete apiKeye o que eles realmente estão fazendo é usernamee password. O que é uma coisa completamente diferente ...
ancajic
3

Existem respostas que explicam o que é a chave secreta e (pública). É um par de chaves pública-privada ao qual eles dão nomes confusos. Mas ninguém diz por que as APIs exigem ambos, e muitas APIs fornecem apenas um segredo! Eu também nunca vi nenhum documento de API explicando porque eles têm duas chaves, então o melhor que posso fazer é especular ...

É melhor colocar apenas sua chave pública em sua solicitação e assiná-la localmente com sua chave privada; o envio de mais nada não deve ser necessário. Mas alguns escapam apenas tendo o segredo do pedido. Ok, qualquer boa API usará alguma segurança de transporte como TLS (geralmente sobre HTTPS). Mas você ainda está expondo sua chave privada para o servidor dessa forma, aumentando o risco de eles, de alguma forma, a manipularem de maneira incorreta (consulte: bug do GitHub e do registro de senha do Twitter descoberto recentemente). E o HTTPS é teoricamente tão seguro, mas sempre há falhas de implementação por aí.

Mas muitas - na verdade, a maioria, ao que parece - APIs enviam ambas as chaves em solicitações, já que isso é mais fácil do que fazer as pessoas fazerem suas próprias assinaturas; não pode ter exemplos puros de cURL de outra forma! Nesse caso, é inútil separá-los. Eu acho que as chaves separadas são apenas para o caso de eles mudarem a API mais tarde para tirar proveito delas. Ou alguns têm uma biblioteca cliente que pode fazer isso da maneira mais segura.

sudo
fonte
0

Uma coisa que eu não vi mencionado aqui, embora seja uma extensão da resposta de Marcus Adams, é que você não deve usar uma única informação para identificar e autenticar um usuário se houver a possibilidade de ataques temporais , que podem use as diferenças nos tempos de resposta para adivinhar o quão longe uma comparação de strings foi.

Se você estiver usando um sistema que usa uma "chave" para procurar o usuário ou credencial, essa informação pode ser adivinhada de forma incremental ao longo do tempo, enviando milhares de solicitações e examinando o tempo que leva para seu banco de dados encontrar (ou não encontrar) um registro. Isso é especialmente verdadeiro se a "chave" for armazenada em texto simples, em vez de um hash unilateral da chave. Você gostaria de armazenar as chaves dos usuários em um texto simples ou criptografado simetricamente para o caso de precisar ser capaz de exibir a chave para o usuário novamente.

Ao ter uma segunda informação, ou "segredo", você pode primeiro procurar o usuário ou credencial usando a "chave", que pode ser vulnerável a um ataque de temporização e, em seguida, usar uma função de comparação segura de temporização para verificar o valor de o segredo".

Aqui está a implementação dessa função em Python:

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

E é exposto na hmacbiblioteca (e provavelmente em outras):

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


Uma coisa a ser observada aqui é que não acho que esse tipo de ataque funcionará em valores que são hash ou criptografados antes da pesquisa, porque os valores que estão sendo comparados mudam aleatoriamente cada vez que um caractere na string de entrada muda. Eu encontrei uma boa explicação disso aqui .

As soluções para armazenar chaves de API seriam:

  1. Use uma chave e um segredo separados, use a chave para pesquisar o registro e use uma comparação segura de tempo para verificar o segredo. Isso permite que você mostre ao usuário a chave e o segredo novamente.
  2. Use uma chave e um segredo separados, use criptografia simétrica e determinística no segredo e faça uma comparação normal de segredos criptografados. Isso permite que você mostre ao usuário a chave e o segredo novamente, e pode evitar que você tenha que implementar uma comparação segura de tempo.
  3. Use uma chave e um segredo separados, exiba o segredo, faça um hash e armazene-o e, em seguida, faça uma comparação normal do segredo com hash. Isso elimina a necessidade de usar criptografia bidirecional e tem o benefício adicional de manter seu segredo seguro se o sistema for comprometido. A desvantagem é que você não pode mostrar o segredo ao usuário novamente.
  4. Use uma única chave , mostre-a ao usuário uma vez, faça um hash e faça uma pesquisa normal da chave criptografada ou com hash. Ele usa uma única chave, mas não pode ser mostrado ao usuário novamente. Tem a vantagem de manter as chaves seguras se o sistema for comprometido.
  5. Use uma única chave , mostre-a ao usuário uma vez, criptografe-a e faça uma pesquisa normal do segredo criptografado. Pode ser mostrado ao usuário novamente, mas ao custo de ter chaves vulneráveis ​​se o sistema for comprometido.

Destes, acho que 3 é o melhor equilíbrio entre segurança e conveniência. Eu vi isso implementado em muitos sites ao obter as chaves emitidas.

Além disso, convido qualquer especialista em segurança real para criticar essa resposta. Eu só queria divulgar isso como outro ponto de discussão.

kbuilds
fonte