LoginSignup
3
4

More than 3 years have passed since last update.

Go言語でOTP

Last updated at Posted at 2020-04-02

二段階認証で必要になったのでGolangでOTPクライアントを実装してみました。
以下をかなり非常に参考させてもらいました。

package otp

import (
    "crypto/hmac"
    "crypto/sha1"
    "encoding/base32"
    "encoding/binary"
    "time"
)

func TRUNCATE(hs []byte) int {
    offset := int(hs[len(hs)-1] & 0x0F)
    p := hs[offset : offset+4]
    return (int(binary.BigEndian.Uint32(p)) & 0x7FFFFFFF) % 1000000
}

func HMACSHA1(k []byte, c uint64) []byte {
    cb := make([]byte, 8)
    binary.BigEndian.PutUint64(cb, c)

    mac := hmac.New(sha1.New, k)
    mac.Write(cb)

    return mac.Sum(nil)
}

func TOTP(k string, x uint64) int {
    key, err := base32.StdEncoding.DecodeString(k)
    if err != nil {
        return 0
    }

    return HOTP(key, T(0, x))
}

func HOTP(k []byte, c uint64) int {
    return TRUNCATE(HMACSHA1(k, c))
}

func T(t0, x uint64) uint64 {
    return (uint64(time.Now().Unix()) - t0) / x
}

// func main() {
//  fmt.Println(TOTP("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF", 30)) // 30秒
// }

雰囲気で関数が全部大文字なってるけど HOTP/TOTP だけでよかった感。

本記事とは関係ないですが、Golang素晴らしいですね。
Javaで作っていたいくつかのAppEngineアプリを2nd Genにアップグレードしたら、Spring Bootで環境変数の一覧返すだけのWeb APIをF1インスタンス(メモリ256MB)にデプロイしたら、2回に1回メモリが溢れて落ちてしまい、全く使い物にならなかった...Google公式サイトにもJavaはオーバーヘッドが大きいとの記載があってJavaをやめる決断をしました。
勉強時間と教科書代と移行時間は結構かかってしまいましたが、代わりに全部Goに書き換えたら、メモリの使用量は1/10、実行速度はゴルーチンのおかげで3倍になり、Javaより非常に安く運用できそうです。
I/O待ちを軽量スレッド(goroutine)の仕組みを簡単に用いて潰せるのは非常にスケールさせやすいですね。GOMAXPROCSが1のGAE環境でも他サービスとの連携、DB/Storage/Datasotre/Firestore等への読み書き等を行っている間に処理を進めることでJavaよりかなり高速に実装し直せたのでとても驚きました。
とりあえず、Javaを今後使うことはないでしょう...さらばJava...

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4