サービスの他の「不正な」クライアントを防止するために、サーバーAPIが自分のアプリからのリクエストのみを受け入れるようにしたいのですが。
私が理解しているように、これを行う方法は、アプリが送信する「クライアント証明書」を使用し、Webサーバーが検証するように構成されていることです。
ただし、私はHerokuでアプリをホストしており、それを実行することは不可能であると考えているので、これを実現するために可能な限り良いものを探しています。
クライアントが秘密鍵を使用して特定の合意済みトークンに署名し(さらに、ランダムなソルトがあり、暗号化された文字列が常に異なるようにする)、サーバーが公開鍵を使用して、トークンを確認します(再生を防ぐために重複するソルトを拒否します)。または、クライアントがリクエスト全体に秘密鍵などで署名する場合もあります。
誰かがSSLのピン留め(iOSのkillスイッチのようなものを使用している可能性があります)を回避してトラフィックを検査し、APIがどのように機能するかを把握したとしても、バイナリをリバースエンジニアリングしない限り、呼び出しはできないという考えになります。その証明書/秘密鍵を抽出します。私はそれを行うことが可能であることを理解しています。私はできるだけ多くの障壁を設けようとしているだけです。
これを行う良い方法は何ですか?
このタイプの問題は、 Cargo-Cult Security type "solutions"に役立ちます。
現実の世界では、悪意のあるクライアントがサービスに接続するのを防ぐメカニズムはありません。 VPNは、信頼できるクライアントが信頼できるネットワークにアクセスできる、実績のあるセキュリティシステムですが、インターネットは本質的に信頼できません。攻撃者はアプリに埋め込まれている、またはアプリのメモリに保存されているシークレットにアクセスできます。TLSクライアント証明書はシークレットに依存しています。
Webサービスを設計するときは、「クライアントは攻撃者であり、決して信頼することはできません。」この間違いを犯した場合は、製図板に戻ります。
注
この回答は、指定された前提の下でのみ適用されます。私はそれらを質問の明示的な表現に基づいて作成しました。これにより、既知の攻撃ベクトルが緩和されないことが明示的に許可されます。
セキュリティは、資産が侵害された場合の損失の価値と、そのような侵害を達成するために敵が実行しようとする努力(コストなど)との間の相対的なバランスです。彼らが利害関係者に関する全体像を持っているので、そのようなバランスを決定することは著者の特権です。
前提条件
あなたが緩和しようとしている脅威は、自分の通信を読み取り/改ざんし、クライアントになりすますことができる敵の1人ですが、リバースエンジニアではありませんバイナリの内容(技術的な不足のため)能力、または意欲の欠如)。
TL; DR
HMAC(message | nonce, key)
とともにクライアントメッセージ/ nonce "in the clear"(TLS経由、ただしそれ以上の暗号化なし)。
詳細な回答
あなたの質問はauthenticationの1つですが、あなたはencryptionでそれを解決しようとしているようです(はい、特定の状況ではいくつかのクロスオーバーがありますが、2つを分離すると答えがわかりますより簡単に)。
秘密鍵(非対称秘密鍵ではなく、十分に大きく、暗号で保護された乱数)がバイナリーに保管されている場合(公開鍵/秘密鍵のペアで提案していたように)、それは、 [〜#〜] hmac [〜#〜] /プレーンテキストのペア。
サーバーはキーについても理解しており、受信したメッセージのHMACを計算し、無効なクライアント通信を破棄します。 nonceは、メッセージを送信する前にサーバーからクライアントに提供され、一意です。傍受されたメッセージのリプレイから保護するように機能します。
警告
前述のように、他の回答/コメントでも、バイナリからキーを取得できます。興味のある人のために、バイナリのすべての領域のエントロピーを計算し、線形位置を ヒルベルト曲線 にマッピングする本当にクールなテクニックがあります。マシンコード領域は、「キー」領域よりもエントロピーが比較的低くなります。 Chris Domasは彼のビデオの1つでこれを実証しています。たぶん彼の TEDトーク 覚えていませんが(TEDビデオをどちらかの方法で見てください)。