🔑
TOTP認証をデスクトップ画面で簡単管理するアプリをGo言語で作ってみた
はじめに
本記事では、Go言語を使ってTOTP (Time-based One-Time Password) コードを生成し、システムトレイに表示するアプリケーションを紹介します。この記事で取り上げるアプリケーションは、簡単なユーザーインターフェースを持ち、トークンを更新し、ワンクリックでクリップボードにコピーできる機能を持っています。
このアプリを利用することで、2段階認証の際に毎回authenticatorアプリを開く手間を省くことができます。
前提条件
- Go 1.23+
-
github.com/pquerna/otp/totp
パッケージ -
github.com/atotto/clipboard
パッケージ -
github.com/getlantern/systray
パッケージ - アイコンファイル (例:
icon.ico
)
プログラム概要
このアプリケーションでは、環境変数に保存されたTOTPキーを使用して、システムトレイ上でTOTPコードを表示し、ユーザーがクリップボードにコピーできます。
主な機能は以下の通りです。
- TOTPキーの生成と表示
- トークンのクリップボードへのコピー
- 定期的なトークンの更新
- アプリケーションの終了機能
コードの説明
メイン処理
func main() {
systray.Run(onReady, onExit)
}
systray.Run()
を使用して、システムトレイのメニューを表示し、onReady()
関数で初期化を行います。onExit()
はアプリケーション終了時に実行される関数です。
TOTPコードの生成と更新
go func() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
code, err := totp.GenerateCode(secret, time.Now())
if err != nil {
fmt.Println("Error generating TOTP code: ", err)
continue
}
systray.SetTooltip(code)
}
}()
この部分は1秒ごとにTOTPコードを生成し、トレイアイコンのツールチップに表示します。TOTPコードは時刻に依存しているため、一定の時間間隔で更新されます。
クリップボードへのコピー
go func() {
for range copyMenuItem.ClickedCh {
otp, err := totp.GenerateCode(secret, time.Now())
if err != nil {
fmt.Println("Error generating TOTP code: ", err)
continue
}
err = clipboard.WriteAll(otp)
if err != nil {
fmt.Println("Error copying TOTP code to clipboard: ", err)
} else {
fmt.Println("Copied TOTP code to clipboard")
}
}
}()
ユーザーが「Copy」メニューをクリックすると、現在のTOTPコードが生成され、クリップボードにコピーされます。
アイコンの読み込み
func icoToByteArray(path string) []byte {
file, err := os.Open(path)
if err != nil {
return nil
}
defer file.Close()
byteArray, err := io.ReadAll(file)
if err != nil {
return nil
}
return byteArray
}
この関数では、指定されたファイルパスからアイコンファイルを読み込み、バイト配列として返します。これにより、システムトレイにカスタムアイコンを設定できます。
実行方法
- 必要な依存ライブラリをインストールします。
- TOTPキーとアイコンのパスを環境変数に設定します。
export TOTP_SECRET="YOUR_SECRET_TOTP_KEY" export TOTP_ICON_PATH="/path/to/icon.ico"
- アプリケーションを実行します。これで、システムトレイにTOTPアイコンが表示され、ツールチップとしてワンタイムパスワードが定期的に更新されます。Copyメニューをクリックすることで、パスワードをクリップボードにコピーできます。
go run main.go
詳細は下記リポジトリのREADMEを参照してください。
Discussion