web-dev-qa-db-ja.com

同じOTPシークレットを使用するデバイスの防止

モバイルデバイスのOTPアプリケーションが同じシークレットを共有しないという要件があります(モバイルデバイスが同じユーザーによって所有されている場合でも)。 1つのシークレットが1つのデバイスに存在する必要があります。

OTPを実装するオープンソースアプリケーション(Google AuthenticatorやFreeOTPなど)は私の要件を満たしていません。秘密はデバイス固有ではありません。これは、複数のデバイスでQRコードをスキャンでき、バックエンドがそれを知らないためです。これはアプリケーション自体に関連するものではなく、この要件を指定していないRFC 4226に関連していると思います。

そこで、複数のデバイスでOTPシークレットを使用するユーザーのリスクを軽減するプロセスについて考えました(インターネット接続が必要です-オフラインである必要はありません)。手順:

  1. アプリは最初の実行時に一意の秘密保護キーを生成します
  2. アプリが秘密の保護キーをサーバーに送信する
  3. サーバーはアプリの一意のシークレットを生成します
  4. サーバーはアプリのシークレット保護キーを使用してシークレットを暗号化し、アプリにblobを返します
  5. アプリは生成されたキーを使用して情報を復号化し、OTPの生成を開始します
  6. 暗号化された秘密と秘密保護キーの両方がアプリに保存されます

このアプローチは改ざん防止されておらず、シークレットはストレージから復元できますが、より困難になることは知っています。

ここで説明するすべてについて、私の質問は次のとおりです。

  • たとえそれがTLSで保護されているとしても、ウェブを介してOTPの秘密を交換する良いアプローチでしょうか?
  • 独自の秘密保護はプロセスにセキュリティまたは欠陥を追加していますか?
  • オフライン同期で同様の結果を達成することは可能でしょうか?
  • 秘密鍵をよりよく保護するためのオープンソースフレームワークはありますか(つまり、ユーザーに直接公開しない、QRコードのように)?
1
rcorreia

Google Authenticators KeyURIでQRコードをスキャンすると、認証所持の「コピー」が作成されるため、私はあなたのニーズを完全に理解しています。

興味深いことに、このためのRFCがあります。 https://www.rfc-editor.org/rfc/rfc6063.txt しかし、これは少しやり過ぎかもしれないという疑いがあります。

私は独自の authentication server に取り組んでいます。他の多くの認証デバイスとは別に、「プレーンテキスト」でOTPシークレットをスキャンするGoogle認証システムなどのスマートフォンアプリもサポートしています。既に述べたように、私は本当にこれが好きではないため、ロールアウトプロセスの改善についても検討を始めました。これらはこれまでのところ私たちの考えです: https://github.com/privacyidea/privacyidea/wiki/concept%3A-SmartphoneApp

基本的に、インターネットに接続していなくてもスマートフォンを登録できるようにしたいと考えています。スマートフォンが接続されていない場合や、トークンが登録されている認証サーバーにスマートフォンからアクセスできず、デスクトップクライアントからのみアクセスできる場合があります。そこで、私たちはまだQRコードに依存することを考えました。

ただし、QRコード内で秘密鍵を転送するだけでなく、トークンを多くのスマートフォンにコピーできるようにする代わりに、スマートフォンによって生成される2番目のコンポーネントが必要です。最も簡単な方法はこれです:

  1. 認証サーバーは、QRコードで秘密鍵の最初のコンポーネントを提供します
  2. ユーザーは新しいQRアプリでこのQRコードをスキャンします
  3. アプリは2番目のコンポーネントを生成し、これをユーザーに単に表示します。
  4. ユーザーは、この2番目のコンポーネントを認証サーバーの登録ページに入力します。
  5. サーバーとスマートフォンアプリの両方が、サーバーによって生成されたコンポーネントとスマートフォンアプリによって生成されたコンポーネントに基づいて最終的な秘密鍵を計算します。

Plus:ワークフローはかなり簡単で、エラーが発生しにくい

マイナス:悪意のあるユーザーは、サーバーの最初のコンポーネントとスマートフォンによって生成された2番目のコンポーネントを書き留め、「手動で」秘密鍵を計算し、いくつかのスマートフォンアプリでこの秘密鍵を使用します。しかし、これはまだ厄介なプロセスです。主な目的は、同僚に「ちょっとトークンもスキャンして」と尋ねるだけの、怠惰で邪悪なユーザーから保護することでした。

私はあなたがこれについてどう思うか、興味があります。これが気に入った場合は、githubでフォローするか、貢献してください。

2
cornelinux

独自の認証アプリを設計している場合; OTPトークンをスキャンする代わりに、サーバーからOTPを取得するために使用される認証トークンをスキャンします。その後、サーバーは、トークンを1回だけ解放するようにセットアップできます。アプリケーションに証明書のピン留めをバンドルすれば、あなたもそうすることができます。

フローは次のようになります。

  • ユーザーがウェブサイトからOTPトークンをリクエストする
  • ユーザーがアプリを開き、1回限りのAPIキーを含むQRコードをスキャンします
  • 次に、アプリはサーバーに接続し、固定された証明書で証明書を検証します
  • アプリは1回限りの使用のAPIキーを送信し、サーバーはOTPトークンを返し、APIキーを無効としてマークします。
4
zzarzzur

RFC 4226 で説明されているように、デバイスIDを使用してデバイスごとに一意の確定的なシークレットを実装できます。シークレットの送信は強制されません(ただし、ランダム生成を使用することをお勧めします)。

 We distinguish two different cases:

      - A single master key MK is used to derive the shared secrets;
        each HOTP device has a different secret, K_i = SHA-1 (MK,i)
        where i stands for a public piece of information that identifies
        uniquely the HOTP device such as a serial number, a token ID,
        etc.  Obviously, this is in the context of an application or
        service -- different application or service providers will have
        different secrets and settings.

最初の実行時に生成されたランダムキーのシナリオの代わりに、アプリは1と2で暗号化キーとしてデバイスuuidを使用する場合があり、別のデバイスでの再現が難しくなります。

2
Tensibai