web-dev-qa-db-ja.com

秘密鍵を保存せずにAPIメッセージを検証しますか?

WebサービスにパブリックAPIを実装しているところです。お金が関わるため、セキュリティは重要な関心事です。

APIリクエストでユーザーを「認証」する現在の一般的な方法は、メッセージの信頼性を確認し、リクエストごとにユーザーにパラメーターのHMAC(一意のナンスを含む)を送信させることです。

これは問題ありませんが、共有シークレットを使用しています。HMACを生成するには、サーバーとクライアントの両方が秘密鍵を保存する必要があります。

私はこれが好きではありません。暗号化されていない共有シークレットをデータベースに格納し始める場合、パスワードをソルト/ハッシュするすべてのフープラに行く意味は何ですか?

もっと良い方法はありますか?私はGPGを使用することを考えていました。ユーザーに自分のGPG公開キーを提供して保存してもらいました。その後、秘密鍵を使用してメッセージに署名できます。しかし、これはWindowsユーザーが操作するのが少し面倒なことかもしれません。

一般的に、公開/秘密鍵署名はこれを行うためのはるかに良い方法ではありませんか?誰もが共有秘密のHMACを選択している理由がいくつかあるに違いありません...何が欠けていますか?

もちろん、APIを介して顧客とのやり取りに制限を設定し、通知を提供し、システムからお金を取り除くことを制限しますが、共有秘密が漏洩した場合でも、多大な損害が発生する可能性があります。

11
Jhong

公開鍵暗号化は低速であり、小さい共有秘密と同じ暗号強度を取得するには、より多くのリソースが必要です。

参照: https://stackoverflow.com/questions/4299795/why-public-key-algorithms-are-slow

少量のシステムを構築している場合、これはおそらく問題にはなりませんが、大規模なシステムになったら、組織と顧客/クライアントに追加のコストを正当化する必要があるかもしれません。

対称シークレットの保存が心配な場合は、おそらくそれを暗号化する必要があります。

2
user26802

私は昨日同じ質問をしましたが、その間に私は私たちの両方の質問に答えると信じているものを見つけました:SRP。 この質問 は、これまでに見つけた最良の答えです。 これはSRPへの参照です 。 SRPの主な問題は、アプリケーションレベルで使用できる最新の実装がないことです。

編集して私の研究からさらに情報を追加します。

データベースを使用するセッションストアを使用することを決定したので、ステートレスの定義を満たしています。これには、SSLが通信のための唯一のプロトコルである必要があり、これによりMITMおよびリプレイ攻撃が排除されます。

  • Bcryptを使用してパスワードをDBに保存する
  • authyやGoogle Authenticatorなどの2要素認証を使用します。これは、外部依存関係がないという要件を満たしていませんが、私の場合は問題ありません。これにより、ユーザーが自分のパスワードを漏洩するのを防ぎます-攻撃者は依然としてユーザーのTFAデバイスを必要とします。
  • 各ユーザーレコードにセッションIDとセッションの長さ(秒)フィールドがある
  • 認証が成功すると(通常の認証、ユーザーはユーザーIDとパスワードを送信し、bcryptを使用して、dbから格納されているハッシュされたパスワードを使用してパスワードをハッシュします)、ハッシュを比較します)
  • パスワードが成功したら、暗号的に健全なGUIDを生成し、セッションを存続させたい期間とともにデータベースに保存します。
  • このセッションIDを認証への応答として送信する
  • 真のステートレス性が必要な場合は、このIDを持つすべてのリクエストをHMACハッシュするようクライアントに要求します-彼はIDを保持できるので、IDをあなたに送信する必要はありません
  • 保存されたsidでリクエストをハッシュしてリクエストを確認し、彼があなたに送信したハッシュと比較します
  • リクエストごとに、expire-timeが経過していないことを確認します。有効期限を確認するプロセスは必要ありません。クライアントがAPI呼び出しを試みるたびに確認するだけです。

私は妥協し、クライアント側Cookieを使用するExpress-jsの安全なセッションストレージを使用しましたが、Cookieはすべてのアプリケーションサーバーが知っている共有シークレットで署名されているため、Cookieは一意ではないというステートレスの定義を満たしていますCookieがまだアプリサーバーのドメインにあるため、クライアントが接続しているサーバーに

3
regretoverflow

user26802は正解です。答えは速度です。 Amazon SQSのようなAPIで、クライアントが大量の小さなメッセージを高速でドロップおよびピックアップし、クライアントでの暗号化とサーバーでの復号化が遅いと、そのサービスの速度が大幅に低下します。

クライアントが秘密鍵署名で認証された呼び出しを行い、短期対称鍵を確立する混合アプローチを想像できます。キーが危険にさらされた場合、キーの有効期限が切れるまでの脆弱性はわずかです。これで、攻撃者がシステムに永続的にアクセスできるようになったとしても、それ以上のことはできません。

覚えておかなければならないもう1つのことは、攻撃者がキーストアを危険にさらし、すべての署名キーを盗むことができる場合、それらは公開キーを置き換えるための位置にあり、別のユーザーとしてリクエストを作成できる可能性があります。

1
u2702