それは、マーカス・アダムスの答えを拡張したものですが、私は、ここで言及見なかったことの一つは、あなたが可能性があるかどうかを確認し、ユーザを認証の両方に単一の情報を使用してはならないことであるタイミング攻撃は、そのことができます応答時間の違いを使用して、文字列の比較がどこまで進んだかを推測します。
「キー」を使用してユーザーまたは資格情報を検索するシステムを使用している場合、その情報は、何千ものリクエストを送信し、データベースが検出するのにかかる時間を調べることで、時間の経過とともに段階的に推測される可能性があります。検索)レコード。これは、「キー」がキーの一方向ハッシュではなくプレーンテキストで格納されている場合に特に当てはまります。ユーザーにキーを再度表示できるようにする必要がある場合は、ユーザーのキーをプレーンテキストまたは対称的に暗号化して保存することをお勧めします。
2番目の情報、つまり「シークレット」を用意することで、タイミング攻撃に対して脆弱である可能性のある「キー」を使用してユーザーまたは資格情報を最初に検索し、次にタイミングセーフ比較機能を使用しての値を確認できます。秘密"。
その関数のPythonの実装は次のとおりです。
https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727
そしてそれはhmac
lib(そしておそらく他のもの)で公開されています:
https://docs.python.org/3/library/hmac.html#hmac.compare_digest
ここで注意すべきことの1つは、入力文字列の文字が変更されるたびに比較される値がランダムに変更されるため、ルックアップの前にハッシュまたは暗号化された値に対してこの種の攻撃が機能するとは思わないことです。私はここでこれの良い説明を見つけました。
APIキーを保存するためのソリューションは次のようになります。
- 別のキーとシークレットを使用し、キーを使用してレコードを検索し、タイミングセーフな比較を使用してシークレットを確認します。これにより、ユーザーにキーとシークレットを再度表示できます。
- 個別の鍵と秘密を使用し、秘密に対称的で決定論的な暗号化を使用し、暗号化された秘密の通常の比較を行います。これにより、ユーザーにキーとシークレットを再度表示できるようになり、タイミングセーフな比較を実装する必要がなくなります。
- 別の鍵と秘密を使用し、秘密を表示し、ハッシュして保存してから、ハッシュされた秘密の通常の比較を行います。これにより、双方向暗号化を使用する必要がなくなり、システムが危険にさらされた場合に秘密を安全に保つという追加の利点があります。これには、ユーザーに秘密を再度表示できないという欠点があります。
- 単一のキーを使用し、それをユーザーに1回表示し、ハッシュしてから、ハッシュまたは暗号化されたキーの通常のルックアップを実行します。これは単一のキーを使用しますが、ユーザーに再度表示することはできません。システムが危険にさらされた場合にキーを安全に保つという利点があります。
- 単一のキーを使用し、それを1回ユーザーに表示して暗号化し、暗号化されたシークレットの通常のルックアップを実行します。再度ユーザーに表示できますが、システムが危険にさらされた場合、キーが脆弱になるという犠牲が伴います。
なかでも、セキュリティと利便性のバランスは3がベストだと思います。キーを発行するときに、これが多くのWebサイトに実装されているのを見てきました。
また、実際のセキュリティ専門家にこの回答を批評してもらいます。別の議論のポイントとして、これを公開したかっただけです。