こんにちは洸です!今回は、Go言語でワンタイムパスワードを発行し、メールで送信したいと思います。
通常、ログイン画面でユーザIDとパスワードの認証だけでは、ブルーフォースアタック(総攻撃)などによって容易に不正アクセスされてしまいます。そこで、SMSやメールアドレスでワンタイムパスワードを通知し、2つの要素で認証を行います。(2要素認証)
こちらの記事のように、直接計算式を記述してもよいですが、今回は便利なpquerna/otpパッケージを使います。
インストール
まずは、go getコマンドでpquerna/otpパッケージのインストールを行います。
1 2 3 |
go get github.com/pquerna/otp |
ワンタイムパスワード生成
インストールが完了したら、exampleを参考にワンタイムパスワードの発行処理を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
func IssueTotp() (string, error) { key, err := totp.Generate(totp.GenerateOpts{ Issuer: "myfuns", // 任意の値を指定してください AccountName: "myfuns@example.com", // 任意の値を指定してください }) if err != nil { return "", err } secretKey := key.Secret() passcode, err := totp.GenerateCodeCustom(secretKey, time.Now(), totp.ValidateOpts{ Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA1, }) if err != nil { return "", err } // メール送信 err = SendMail(passcode) if err != nil { return "", err } return secretKey, nil } |
IssuerとAccountNameに任意の値を代入し、シークレットキーをランダム生成します。次に、作成されたシークレットキーから、SHA-1アルゴリズムでワンタイムパスワードを生成します。
生成したパスワードはメールで送信し、ユーザの入力を待ちます。 シークレットキーは検証で使用するので、戻り値で保持しておきます。
メール送信
パスワードを通知するための、メール送信を行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// メール送信 func SendMail(passcode string) error { auth := smtp.PlainAuth( "", "myfuns@example.com", // ユーザ名 "****", // パスワード "smtp.gmail.com") // ホスト名 to := []string{"to@example.com"} // 宛先アドレス msg := []byte("Subject: パスワードを入力してください" + "\r\n" + "\r\n" + "パスワードは" + passcode + "です。") // メール送信 err := smtp.SendMail( "smtp.gmail.com:587", // サーバ情報 auth, // 認証情報 "myfuns@example.com", // 送信元アドレス to, // 宛先アドレス msg, // 本文 ) if err != nil { return err } return nil } |
検証
次に、ワンタイムパスワードの検証です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
func Validate(passcode string, secret string) bool { rv, _ := totp.ValidateCustom( passcode, secret, time.Now(), totp.ValidateOpts{ Period: 30, // 有効時間 Skew: 1, // 誤差 Digits: otp.DigitsSix, // パスワード桁数 Algorithm: otp.AlgorithmSHA1, // アルゴリズム }, ) return rv } |
ユーザの入力値とシークレットキーで検証を行います。検証に用いるアルゴリズムは、パスワード生成したものと同じSHA-1を用います。
メイン処理
最後に全体の処理を記述して完了です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
func main() { // ワンタイムパスワード発行 secret, err := IssueTotp() if err != nil { fmt.Println(err) panic(err) } fmt.Println("パスワードを入力してください: ") var input string // 入力 fmt.Scan(&input) // 検証 if Validate(input, secret) { fmt.Println("認証成功です。") } else { fmt.Println("認証失敗です。") } } |
やってみよう
go run で実行します。
1 2 3 |
go run main.go |
IssueTotp()が成功すると、メールでワンタイムパスワードが送られ、入力を促されます。
1 2 3 4 5 |
% go run main.go パスワードを入力してください: |
メールにあるパスワードを入力します。
1 2 3 4 5 6 7 |
% go run main.go パスワードを入力してください: 158447 認証成功です。 |
無事認証成功です。お疲れ様でした!
おすすめのメールの記事はこちら!
-
-
参考【知っとくとお得◎】メール設定で今後困らない知識を5分で理解する
OutlookやiPhoneでメールアカウントを追加したい時、SMTP、POP3、IMAP、SSLなどの言葉が出てきます。数年間意味が分からないまま、無心で設定を行っていました(笑)が、いざ勉強してみると簡単じゃん!!ということで、忘備録もかねて、メールの設定項目と仕組み・流れを簡単に説明していきたいと思います。
続きを見る