diff --git a/gauth/gauth.go b/gauth/gauth.go index 619328d..3b2af0a 100644 --- a/gauth/gauth.go +++ b/gauth/gauth.go @@ -17,15 +17,27 @@ import ( "github.com/creachadair/otp/otpauth" ) -// IndexNow returns the current 30-second time slice index, and the number of -// seconds remaining until it ends. -func IndexNow() (int64, int) { +// IndexNow returns the current 30-second time step, and the number of seconds +// remaining until it ends. +func IndexNow() (uint64, int) { time := time.Now().Unix() - return time / 30, int(time % 30) + return uint64(time / 30), int(time % 30) } // Codes returns the previous, current, and next codes from u. func Codes(u *otpauth.URL) (prev, curr, next string, _ error) { + var ts uint64 + if u.Period > 0 { + ts = otp.TimeWindow(u.Period)() + } else { + ts, _ = IndexNow() + } + return CodesAtTimeStep(u, ts) +} + +// CodesAtTimeStep returns the previous, current, and next codes from u at the +// given time step value. +func CodesAtTimeStep(u *otpauth.URL, timeStep uint64) (prev, curr, next string, _ error) { if u.Type != "totp" { return "", "", "", fmt.Errorf("unsupported type: %q", u.Type) } else if u.Algorithm != "" && u.Algorithm != "SHA1" { @@ -33,18 +45,12 @@ func Codes(u *otpauth.URL) (prev, curr, next string, _ error) { } cfg := otp.Config{Digits: u.Digits} - var ts uint64 - if u.Period > 0 { - ts = otp.TimeWindow(u.Period)() - } else { - ts = otp.TimeWindow(30)() - } if err := cfg.ParseKey(u.RawSecret); err != nil { return "", "", "", fmt.Errorf("invalid secret: %v", err) } - prev = cfg.HOTP(ts - 1) - curr = cfg.HOTP(ts) - next = cfg.HOTP(ts + 1) + prev = cfg.HOTP(timeStep - 1) + curr = cfg.HOTP(timeStep) + next = cfg.HOTP(timeStep + 1) return } diff --git a/gauth/gauth_test.go b/gauth/gauth_test.go index de1ad90..9244f1e 100644 --- a/gauth/gauth_test.go +++ b/gauth/gauth_test.go @@ -4,14 +4,14 @@ import ( "bytes" "testing" + "github.com/creachadair/otp/otpauth" "github.com/pcarrier/gauth/gauth" ) -/* TODO: Update this test. func TestCodes(t *testing.T) { tests := []struct { secret string - index int64 + index uint64 want string fail bool }{ @@ -22,14 +22,15 @@ func TestCodes(t *testing.T) { {"blargh!", 123, "", true}, } for _, test := range tests { - _, got, _, err := gauth.Codes(test.secret, test.index) + u := &otpauth.URL{Type: "totp", RawSecret: test.secret} + _, got, _, err := gauth.CodesAtTimeStep(u, test.index) if err != nil && !test.fail { - t.Errorf("Code(%q, %d): unexpected error: %v", test.secret, test.index, err) + t.Errorf("Codes(%q) at %d: unexpected error: %v", u, test.index, err) } else if got != test.want { - t.Errorf("Code(%q, %d): got %q, want %q", test.secret, test.index, got, test.want) + t.Errorf("Codes(%q) at %d: got %q, want %q", u, test.index, got, test.want) } } -} */ +} //go:generate openssl enc -aes-128-cbc -md sha256 -pass pass:x -in testdata/plaintext.csv -out testdata/encrypted.csv