Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

アカウントセキュリティを強化:二要素認証(2FA)の導入とTOTPの仕組みを徹底解説

高額なインターネット料金にうんざりして、「隣人のセキュリティがザルなWi-Fiを勝手に使ってしまいたい」と思ったことはありませんか?それをためらわせていたのが、Honeybadgerの一要素認証フローだったという方に、朗報です。

ついに登場:二要素認証(2FA)

冗談はさておき、私たちはセキュリティを非常に真剣に考えています。ユーザーの皆様とそのデータをより安全に守るための重要なツールをご提供できることを、大変嬉しく思います。

単純に2FAの有効化手順だけを説明してもいいのですが、それでは面白くありません。そこで今回は、暗号技術の世界を軽やかに覗きながら、2FAがどのように動作するのかを一緒に見ていきましょう。

理論は苦手という方は、遠慮なく「有効化の手順」までスキップしてください。傷つきませんので。

⚠️ 注意:ここから少し理論の話

多くの2FA実装は、Time-Based One-Time Password(TOTP:時間ベースのワンタイムパスワード)と呼ばれるアルゴリズムを基盤としています。名前からして長ったらしいですね。

「ワンタイム」って何?

この方式の美しいところは、ログインのたびに同じ「パスワード」を送信する必要がない点です。認証アプリを使うと、一度限りの「パスワード」が生成され、短時間(通常30秒)のみ有効になります。これにより、中間者攻撃(man-in-the-middle attack)の効果は大きく損なわれます。

細部には複雑な部分もありますが、全体的な仕組みは比較的シンプルです。

共有秘密鍵(The Secret)

TOTPについて理解すべきとなるポイントは、サーバー(検証者/verifier)と認証アプリ(証明者/prover)が共有秘密鍵を持っている必要があるということです。これこそが本当の「パスワード」ですが、送信されるのは一度きりです(だからこれも「ワンタイム」と言えるかもしれませんね!)。

秘密鍵を受け取る推奨方法はQRコード経由です。スマートフォンでQRコードを読み取ると、秘密鍵は次のような標準URIにエンコードされています:

otpauth://totp/Honeybadger.io:inigo@honeybadger.io?secret=base32-secret-key

平文の秘密鍵を直接表示する代わりにQRコードを使うメリットはいくつかあります:

  1. 32文字のコードを手打ちする時間なんて誰が持っているでしょうか?
  2. 認証アプリがワンタイムパスワードに便利なラベルを付けてくれます(URI内のメールアドレスと発行者を参照)。複数のサービスで2FAを使っている場合に特に役立ちます。
  3. ようやくQRコードを使う良い理由が見つかりました!

otpauthスキームには他にもいくつかのパラメータがあります(ほとんど無視されます)が、詳細は公式ドキュメントで確認できます。

MAC(Message Authentication Code)とは

秘密鍵の共有が完了したら🤝、どこかの時点でワンタイムパスワードの入力を求められます。ここからが本番です

TOTPは、HMAC-Based One-Time Password(HOTP)という別のアルゴリズムの上に構築されており、HOTP自体はHash-based Message Authentication Code(HMAC)に基づいています。まるで暗号版マトリョーシカのような入れ子構造です。

TOTPHOTPは、基本的に「どのメッセージをハッシュ化するか」のバリエーション違いです。そしてHMACこそが魔法の正体です。HMACはダイジェストを生成します。これはある値をハッシュアルゴリズムに通した出力結果です。Rubyコードで実際に見てみましょう:

OpenSSL::HMAC.digest("SHA1", "my-secret-key", "the-earth-is-flat")
=> "R\xABp\xCB\xEC\xFEJ\r#\x02\xC8\xAB\x96\xB68\v\xDA0\xD7z"

おっと、このバイナリ文字列を見てください!これがMessage Authentication Code(MAC:メッセージ認証コード)です。

ハッシュ関数にはSHA1を選択しました(TOTPの実装でも同様です)。選択肢は他にもたくさんあり、それぞれセキュリティやパフォーマンス特性が異なります。ハッシュアルゴリズムの素晴らしいところは、どんな入力に対しても、毎回同じ出力が得られることです!さらに、入力がわずかに変わるだけで、まったく異なる固有の出力が生成されます(ハッシュ関数によりますが、衝突についてはあまり心配しなくて大丈夫です)。

さて、これがメッセージ認証コードと呼ばれるのは、受信したメッセージが本物であることを証明できるからです。あなたと私が同じ秘密(my-secret-key)を知っていれば、私はメッセージthe-earth-is-flatMACを一緒に送ることができます。受け取った側は、同じ入力でまったく同じダイジェスト関数を実行し、MACが一致すれば、そのメッセージは認証されたことになります!改ざんされておらず、私から来たものであることが分かるのです!

😎

タイムコード(Timecode)

では、話をTOTPに戻しましょう。そろそろ時間の話をします。TOTPでは、the-earth-is-flatのようなふざけたメッセージの代わりに、時間ステップ数(文字列に変換されたもの)を入力として使います。認証アプリを開いて、コードが切り替わるタイミングを観察すると、あるパターンに気づくかもしれません。そう、一緒に言ってみましょう:「30秒ごとに切り替わる」。その通りです。

これによりメッセージの計算が少し簡単になります。この場合、UNIX時間(いわゆるエポック秒)からの経過時間を30秒(タイムステップ)で割って切り捨てた値を使います。再びRubyで書くと:

Time.now.to_i / 30
=> 51772900

なるほど!これがメッセージです。

そこで認証アプリでは、頼れるダイジェスト関数を使って新しいHMACを取得します:

hmac = OpenSSL::HMAC.digest("SHA1", "avwe8aw71j2boib23jkbjk32", "51772900")
=> "H\x7F\xC1\xACL\xDA\xDB\xE7DQ\x91kE\x1C\xE3,c\nH\xA0"
get_otp_code(hmac)
=> "332204"

最後のステップは、このバイナリ文字列から数字コードを取り出すことです。ビット操作が必要になるため、今のところ匿名のget_otp_code関数の陰に隠れておきます。興味があれば、HOTP仕様でその動作について詳しく読むことができます。

コードをサーバーに送信すると、サーバーはまったく同じダイジェスト操作を実行してコードを比較します。一致すれば、ログイン成功です!時間を扱っているため、レイテンシ(通信遅延)も考慮要素になります。遅延への対策戦略はいくつかあります。その理解については、よろしければ宿題としておきます。

以上がTime-Based One-Time Passwordの仕組みの概要です!!🎉 この知識を活かして次のディナーパーティーの人気者になれたら、ぜひ感謝のメールをお送りください!

実装について

こうした仕組みを理解することは大切だと思いますが、暗号関連のものを自作することは強く非推奨です。Ruby/Railsエコシステムの素晴らしい点のひとつは、問題を解決してくれるgem(時には複数)を見つけられることが多いことです。

Honeybadgerではdeviseを使用しており、two_factor_authenticationという優れたdeviseプラグインがあります。2FAの実装はいくつかありますが、これを選んだ理由は以下の通りです:

  • セットアップがシンプル(マイグレーション1つと、設定・イニシャライザを少々追加するだけ)
  • ワンタイムコードを専用ページで入力できる(ユーザー名/パスワードの認証後)
  • デフォルト設定が妥当でありながら、オーバーライドも簡単
  • 最大ログイン試行回数チェック機能があり、これは仕様でも推奨されている

有効化の手順

設定は簡単です:「ユーザー設定 > 認証」ページに移動し、「Set Up Two Factor Authentication(二要素認証を設定)」を選択して、AuthyまたはGoogle Authenticator(またはその他の任意のTOTP対応アプリ)を使って秘密鍵を同期する手順に従ってください。

アカウントセキュリティを強化:二要素認証(2FA)の導入とTOTPの仕組みを徹底解説

これだけです!次回ログイン時に、認証アプリのコード入力を求められます。コードを入力すれば、完全な安心感とともにお使いいただけます。🧘

アカウントセキュリティを強化:二要素認証(2FA)の導入とTOTPの仕組みを徹底解説

セキュリティとシンプルさの両立?これ以上何を望みましょうか?

最後にもうひとつ:Pwned Passwordチェック

弱いパスワード派の皆さんに、ちょっとしたお知らせです。私たちはdevise-pwned_password gemとも統合しました。今後、パスワードが必要な操作を行う際に、入力されたパスワードが既知のデータ漏洩事件で流出していないかをチェックします。新しいパスワードを設定する際にチェックに失敗した場合は、そのパスワードは使用できません。

まだの方は、パスワードマネージャーの使用を強くお勧めします(えへん、1Passwordとか)。

Pwned Passwordの興味深い点のひとつは、サードパーティサービスのデータベースと照合している間も、パスワードの安全性が保たれる仕組みです。これはk-Anonymity(k-匿名性)と呼ばれる手法で、概要はこちらで確認できます。

今回は以上です。また次回お会いしましょう!👋

  1. Wi-Fiのネットワークセキュリティキーとは?確認方法と忘れたときの対処法を解説

    Wi-Fiのネットワークセキュリティキーとは?ネットワークセキュリティキーとは、Wi-Fiなどのローカルエリアネットワーク(LAN)に接続する際に求められるパスワードや暗証番号のことです。自宅のWi-Fiに接続するときに入力するパスワードがまさにこれに該当し、許可されたユーザーだけが安全にネットワークへアクセスできるようにするための重要な仕組みとなっています。Windowsでセキュリティキーを確認する方法すでに接続したことのあるWi-Fiのセキュリティキーを忘れてしまった場合は、Windowsの設定から簡単に確認できます。スタートメニューを開き、「ネットワーク接続」の画面を表示します。「ネット

  2. ネットワークセキュリティキーとは?確認方法と基本知識をわかりやすく解説

    ネットワークセキュリティキーの確認方法(Windowsの場合)Windowsパソコンでネットワークセキュリティキーを確認するには、以下の手順に従ってください。まず、スタートメニューをクリックして起動します。次に「ネットワーク接続」の画面を開き、「ネットワークと共有センター」を選択します。画面上にワイヤレスネットワークのアイコンが表示されるので、それをクリックしてください。続いて、左側のメニューから「ワイヤレスプロパティ」を選び、「セキュリティ」タブを開きます。最後に「文字を表示する」にチェックを入れると、ネットワークセキュリティキーが画面に表示されます。Wi-Fi接続におけるネットワークセキュ