TOTPキーボードをつくろう その1
ワンタイムパスワードをワンタッチで入力できる装置を作ってみる
はじめに
いろんなサービスで MFA を設定していることは多いと思うのですが、 いわゆる TOTP を使ったサービスの場合、 毎回 Authenticator を起動して認証コードを確認して、 手でコードを入力しないといけないので、手間が増えてしまいます。
せっかく、そこにコード表示されいるんだから自動で入力しろよということで、 ここをなんとか自動化できないものかと思いました。
仕様の検討
最低限の仕様として次のものを考えました。
- RTC を使って時刻を保持する
- 何らかの方法で、時刻を同期する
- キースイッチを使って、コードを選択できるようにする
- PC からは USB キーボードとして見えるようにする
- 選択したコードをワンタッチで入力できるようにする
- 簡易的なパスワード機能をつける
以下、それぞれについて考察します。
時刻の管理
TOTP は一般的に 30秒ごとの時刻情報をキーとして、OTP を発生します。 したがって、正確な時刻情報が必要になります。
一般的なマイコンには RTC がついているので、それを使うのが簡単なのですが、 時刻の精度はクロックの精度によって決まってしまいます。
水晶発振器の精度は ppm のオーダーなので、月に数秒の誤差が発生する可能性があります。
一方 NTP などを使えば時刻同期は簡単なのですが、WiFi 機能付きのマイコンが必要になりますが、 安価に入手できる ESP32 シリーズでは RTC の精度が高くないために、 外付けの RTC チップと併用する必要が出てきます。 (持ち運びしないなら常に NTP で同期しても良いのですが)
今回は RTC 付きのマイコンを使って、時刻の修正はキーを使って行うこととします。 また STM32 互換マイコンには、ppm オーダーの RTC の微調整機能があるので、それを使えばもっと精度が上げられるかもしれません。
CH32V203 の RTC は秒単位のカウンタでカウントするタイプなので、2038年問題を気にしなければ、単純に Unix time で保持するのが楽そうです。
キースイッチ
一台で複数の TOTP キーに対応するために、簡単な UI を付けます。 何らかのキーストロークをトリガにして、ロックが解除されるような簡易パスワード機能をつけます。 UIがあるので、時刻調整もできるようにします。
- 普段はロック状態(ディスプレイは消灯か時刻表示)
- 特定のキー入力で、キー選択状態になる
- キー選択状態で、選択キーを押すと TOTP コードが入力される
- キー選択状態で、「時刻調整」を選ぶと時刻調整ができる
- 一定時間キー入力がなければ、ロック状態に戻る
- ロック解除に失敗すると、次の解除入力が可能になるまで待たされる
- 複数回失敗すると、入力可能になるまでの時間が伸びる
USB
USB キーボードとして振舞うこととします。 時刻の初期設定のために USB CDC を使っても良かったのですが、 複合デバイスにするといろいろと問題が起きる可能性があるので、 そちらは素直に USART 経由とします。 また、TOTP のキーをどのように設定するかという問題もあるのですが、 こちらはコード上に埋め込んでしまうこととしました。 対タンパー性が必要であれば、フラッシュの書き込み時に ReadOnly にしてしまえばよいという開き直りです。
# まとめ
ということで大体以下の仕様で作成することとしました
- マイコンは RTC と USB がついている CH32V203 を使う
- RTC は外部クロックで駆動して、バッテリバックアップする
- USB で給電して、給電中はマイコンはオンにする
- コード選択&パスワード入力のためにキースイッチを3~4個つける
- ディスプレイをつける
- RTC の初期設定は USART を経由する
- TOTP の設定はコードに埋め込む
- 時刻の微調整(30秒以内)はキースイッチからできるようにする