なぜAPIキーとシークレットを使用するのですか?


93

ユーザーにAPIキーシークレットの両方を提供する多くのAPIに出くわしました。しかし、私の質問は、両方の違いは何ですか?

私の目には、1つのキーで十分です。私が鍵を持っていて、私とサーバーだけがそれを知っているとしましょう。このキーを使用してHMACハッシュを作成し、API呼び出しを行います。サーバー上で、HMACハッシュを再度作成し、送信されたハッシュと比較します。同じ場合、通話は認証されます。

では、なぜ2つのキーを使用するのでしょうか。

編集:またはそのAPIキーはAPIシークレットを検索するために使用されますか?


回答:


46

秘密鍵暗号化は、同じ鍵を使用してメッセージをエンコードし、後でデコードすることに依存しています。したがって、「秘密」を知っている人だけがメッセージを読むことができます。

RSAセキュリティは、2つの一致するキーに基づいています。ユーザーごとに公開鍵があり、誰もがそれを知ることができます(すべきです)。ユーザーだけが知っておくべき秘密鍵もあります。公開鍵で暗号化されたメッセージは、秘密鍵でのみ復号化できます。その逆も同様です。

したがって、あなただけが読むことができるメッセージを送信したい場合は、(ネットワークから)公開鍵を取得し、その鍵でメッセージを暗号化します。これを復号化できるのはあなただけです。

または、メッセージを送信したことを証明したい場合は、秘密鍵を使用してメッセージを暗号化し、暗号化の方法を(オープンテキストまたは別のメッセージで)伝えます。次に、私の公開鍵を使用してメッセージを復号化できます。メッセージが読み取り可能になった場合は、それが私からのものであることがわかります。

この形式の暗号化はかなりコンピュータを集中的に使用するため、RSAテクノロジを使用して1回限りの「秘密鍵」を暗号化し、残りのメッセージを秘密鍵で暗号化してから、2番目の方法で署名を暗号化することがあります。次に、このプロセスを逆にして、メッセージと署名が読み取り可能である場合、あなたとあなただけがそれを読み取ることができ、私がメッセージを送信したことを確認します。

または

詳細な説明については、このリンクにアクセスしてください。

APIキーとシークレットキーはどのように機能しますか?


9
良い答えですが、FacebookやGmailなどでAPIシークレットとキーを使用する場合、暗号化やハッシュを行う必要はありません。そのような場合、APIシークレットとキーのポイントは何ですか?
クイントン2016

2
Facebookを例として使用すると、app_secretを使用する2つのシナリオがあります。最初のものはハッシュを必要としません。これは主に、リダイレクトURLが乗っ取られるのを防ぐために使用されます。ユーザーがログインしてアプリへのアクセスを許可した後、FacebookがアクセストークンをリダイレクトURLに直接送信した場合、アクセストークンがFacebookからのものであるかどうかを確認する方法はありません。私はあなたのリダイレクトURLに私自身のアクセストークンを投稿し、あなたのAPIから来るFacebookアクションを実行することができます。代わりに、FacebookはリダイレクトURLにコードを送信します。次に、APIはコードを実際のアクセストークンと交換します。
ライアントーマス

2
後半では、コードを実際のアクセストークンと交換する際に、FacebookはAPIが署名を使用してIDを確認することを期待しています。このシナリオでは、署名に公開鍵暗号化を必要とせず、アプリの秘密を真に秘密に保ち、署名として使用することを信頼しているだけです。これは、先に進まず、一方向性関数を使用して署名を生成することは常にばかげているように見えましたが、アプリシークレットの直接使用に落ち着くためのパフォーマンスなどの理由があると思います。
ライアントーマス

2番目のユースケースでは、暗号化ハッシュを使用します。Facebookとの対話を開始するための実際のaccess_tokenを取得した後、アプリが偽装されるのを防ぐために追加のセキュリティが必要になる場合があります。Facebookアプリコンソールでは、アプリからのすべてのFacebook APIリクエストに、アクセストークンに加えて署名を含める必要がある機能をオンにできます。私は彼らの動機を推測しているだけですが、現時点では、リクエストごとに署名としてapp_secretを繰り返し送信することを望んでいないと思います。送信すればするほど、app_secretが危険にさらされる可能性が高くなります。
ライアントーマス

1
この追加のセキュリティ機能を選択したので、Facebookの追加のパフォーマンスオーバーヘッドが暗号化ハッシュ呼び出しで署名を検証できるようにするための決定も行ったと思います。とにかく、このシナリオでは、FacebookAPIリクエストで2つの値を渡します。access_tokenと、署名として機能するappsecret_proofという名前の値。アプリシークレットプルーフは、app_secretをキーとして使用するaccess_tokenの暗号化ハッシュによって生成されます。
ライアントーマス

55

2つの別々のキーが必要です。1つはあなたが誰であるかを示すもので、もう1つはあなたがあなたが誰であるかを証明するものです

「キー」はユーザーID、「シークレット」はパスワードです。彼らは「キー」と「シークレット」という用語を使用しているだけです。それが彼らがそれを実装した方法だからです。


1
そして、もしあなたがhttps経由で通信しているとしたら?では、秘密鍵を使用してメッセージを暗号化する意味は何ですか?
kamuniaft 2018年

6
重要なのは常にリスクを減らすことです。https通信が危険にさらされた場合、リクエストを読み取ることができる攻撃者は新しいリクエストを偽造できなくなります。APIが猫の写真をランク付けしようとしている場合、大したことではありません。支払いAPIの場合は、複数のセキュリティレイヤーを使用することをお勧めします:)
Yall

2つの別々のキーの目的は、単一のクライアントアプリの異なるユーザーが異なるシークレットを持つ可能性があるためだと思います。そうでない場合、すべてのユーザーが同じシークレットを持っているとしたら、キーを持つことは役に立ちません。正しい?
ハニー

なぜこれらのAPIBearer:はそのために認証を使用しないのですか?そこにIDとpwdがあります。
Stefan Haberl

7

簡単な答え、私がそれを正しく理解していれば...

暗号化にAPIキーを使用する場合、サービスは誰がそれらに連絡しているかをどのように知るのでしょうか?彼らはそのメッセージをどのように解読しますか?

APIキーを使用して、自分が誰であるかを示します。これは、プレーンテキストで送信するものです。誰にも送信しない秘密鍵。暗号化に使用するだけです。次に、暗号化されたメッセージを送信します。暗号化に使用されたキーを送信しないと、目的が損なわれます。


あなたがやる。APIキーをサーバーに送信します。つまり、これは、サーバーとの通信を傍受している可能性のあるすべての人にその価値を提供していることを意味します。
ancajic 2018年

私が見たほとんどすべてのAPIでは、キーとシークレットの両方をサーバーに送信しています。サーバーへの接続は、理論的には同じレベルのセキュリティで暗号化されます。しかし、私はサーバー以外の誰にも決して与えません。
sudo 2018年

secretプレーンテキストで送信するのを見たことがありません。リンクを教えていただけますか?私が見たのは、secretいくつかのデータを暗号化するために使用しています。そして、暗号化されたデータとともにapiKey、サーバーがデータを復号化する方法を知っているように送信します。
ancajic 2018年

twilio.com/docs/sms/tutorials/…nexmo.github.io/Quickstarts/sms/sendは、StackOverflowで検索するように促した例です。
sudo 2018年

Twilioはこれらの用語を正確に使用していません。しかし、Nexmoは確かに...しかし、一見したところ、彼らは単にデータsecretを呼び出しているようでありapiKey、実際に行っていることはusernamepasswordです。これは完全に異なるものがある...
ancajic

3

秘密鍵と(公開)鍵が何であるかを説明する答えがあります。これは、彼らが紛らわしい名前を付ける公開鍵と秘密鍵のペアです。しかし、APIが両方を必要とする理由は誰も言いません。多くのAPIは、1つの秘密しか提供しません。また、APIのドキュメントで2つのキーがある理由を説明しているのを見たことがないので、私ができる最善のことは推測することです...

リクエストには公開鍵のみを入れ、秘密鍵を使用してローカルでリクエストに署名することをお勧めします。これ以上送信する必要はありません。しかし、一部の人は、リクエストに秘密を持っているだけで逃げます。わかりました。優れたAPIは、TLS(通常はHTTPS経由)などのトランスポートセキュリティを使用します。ただし、その方法で秘密鍵をサーバーに公開しているため、秘密鍵が何らかの形で誤って処理されるリスクが高まります(最近発見されたGitHubとTwitterのパスワードロギングのバグを参照)。また、HTTPSは理論的には同じくらい安全ですが、実装上の欠陥は常に存在します。

しかし、多くの(実際にはほとんどのように思われる)APIでは、ユーザーに独自の署名を行わせるよりも簡単なので、リクエストで両方のキーを送信する必要があります。そうでなければ、純粋なcURLの例を持つことはできません!その場合、それらを分離することは無意味です。個別のキーは、後でそれらを利用するためにAPIを変更する場合に備えていると思います。または、より安全な方法で実行できるクライアントライブラリを持っている人もいます。


1

それは、マーカス・アダムスの答えを拡張したものですが、私は、ここで言及見なかったことの一つは、あなたが可能性があるかどうかを確認し、ユーザを認証の両方に単一の情報を使用してはならないことであるタイミング攻撃は、そのことができます応答時間の違いを使用して、文字列の比較がどこまで進んだかを推測します。

「キー」を使用してユーザーまたは資格情報を検索するシステムを使用している場合、その情報は、何千ものリクエストを送信し、データベースが検出するのにかかる時間を調べることで、時間の経過とともに段階的に推測される可能性があります。検索)レコード。これは、「キー」がキーの一方向ハッシュではなくプレーンテキストで格納されている場合に特に当てはまります。ユーザーにキーを再度表示できるようにする必要がある場合は、ユーザーのキーをプレーンテキストまたは対称的に暗号化して保存することをお勧めします。

2番目の情報、つまり「シークレット」を用意することで、タイミング攻撃に対して脆弱である可能性のある「キー」を使用してユーザーまたは資格情報を最初に検索し、次にタイミングセーフ比較機能を使用しての値を確認できます。秘密"。

その関数のPythonの実装は次のとおりです。

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

そしてそれはhmaclib(そしておそらく他のもの)で公開されています:

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


ここで注意すべきことの1つは、入力文字列の文字が変更されるたびに比較される値がランダムに変更されるため、ルックアップの前にハッシュまたは暗号化された値に対してこの種の攻撃が機能するとは思わないことです。私はここでこれの良い説明を見つけました。

APIキーを保存するためのソリューションは次のようになります。

  1. 別のキーとシークレットを使用し、キーを使用してレコードを検索し、タイミングセーフな比較を使用してシークレットを確認します。これにより、ユーザーにキーとシークレットを再度表示できます。
  2. 個別の鍵と秘密を使用し、秘密に対称的で決定論的な暗号化を使用し、暗号化された秘密の通常の比較を行います。これにより、ユーザーにキーとシークレットを再度表示できるようになり、タイミングセーフな比較を実装する必要がなくなります。
  3. 別の鍵と秘密を使用し、秘密を表示し、ハッシュして保存してから、ハッシュされた秘密の通常の比較を行います。これにより、双方向暗号化を使用する必要がなくなり、システムが危険にさらされた場合に秘密を安全に保つという追加の利点があります。これには、ユーザーに秘密を再度表示できないという欠点があります。
  4. 単一のキーを使用し、それをユーザーに1回表示し、ハッシュしてから、ハッシュまたは暗号化されたキーの通常のルックアップを実行します。これは単一のキーを使用しますが、ユーザーに再度表示することはできません。システムが危険にさらされた場合にキーを安全に保つという利点があります。
  5. 単一のキーを使用し、それを1回ユーザーに表示して暗号化し、暗号化されたシークレットの通常のルックアップを実行します。再度ユーザーに表示できますが、システムが危険にさらされた場合、キーが脆弱になるという犠牲が伴います。

なかでも、セキュリティと利便性のバランスは3がベストだと思います。キーを発行するときに、これが多くのWebサイトに実装されているのを見てきました。

また、実際のセキュリティ専門家にこの回答を批評してもらいます。別の議論のポイントとして、これを公開したかっただけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.