From ec2b46e7780a73026d822aef18bbf66525ae3c43 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Mon, 29 Jan 2024 23:49:25 +0700 Subject: lib/totp: add method GenerateWithTime and GenerateNWithTime The GenerateWithTime and GenerateNWithTime accept parameter [time.Time] as the relative time for generated password. --- lib/totp/totp.go | 22 +++++++++++-- lib/totp/totp_example_test.go | 73 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/lib/totp/totp.go b/lib/totp/totp.go index 953fb843..77e90a00 100644 --- a/lib/totp/totp.go +++ b/lib/totp/totp.go @@ -99,13 +99,31 @@ func (p *Protocol) Generate(secret []byte) (otp string, err error) { return p.generateWithTimestamp(mac, now) } -// GenerateN generate n number of passwords from (current time - N*timeStep) -// until the curent time. +// GenerateWithTime generate one time password using ts as time and secret. +func (p *Protocol) GenerateWithTime(ts time.Time, secret []byte) (otp string, err error) { + var mac = hmac.New(p.fnHash, secret) + return p.generateWithTimestamp(mac, ts.Unix()) +} + +// GenerateN generate n number of passwords from (ts - 0*timeStep) +// until (ts - N*timeStep). func (p *Protocol) GenerateN(secret []byte, n int) (listOTP []string, err error) { var ( mac = hmac.New(p.fnHash, secret) ts = time.Now().Unix() + ) + return p.generateN(mac, ts, n) +} +// GenerateNWithTime generate n number of passwords from (ts - 0*timeStep) +// until (ts - N*timeStep). +func (p *Protocol) GenerateNWithTime(ts time.Time, secret []byte, n int) (listOTP []string, err error) { + var mac = hmac.New(p.fnHash, secret) + return p.generateN(mac, ts.Unix(), n) +} + +func (p *Protocol) generateN(mac hash.Hash, ts int64, n int) (listOTP []string, err error) { + var ( otp string t int64 x int diff --git a/lib/totp/totp_example_test.go b/lib/totp/totp_example_test.go index 7958e6d0..2d8e12e3 100644 --- a/lib/totp/totp_example_test.go +++ b/lib/totp/totp_example_test.go @@ -2,20 +2,81 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package totp +package totp_test import ( "encoding/hex" "fmt" "log" + "time" + + "github.com/shuLhan/share/lib/totp" ) +func ExampleProtocol_GenerateNWithTime() { + var ( + secretHex = `3132333435363738393031323334353637383930` + + secret []byte + err error + ) + + secret, err = hex.DecodeString(secretHex) + if err != nil { + log.Fatal(err) + } + + var ( + proto = totp.New(totp.CryptoHashSHA1, totp.DefCodeDigits, totp.DefTimeStep) + ts = time.Date(2024, time.January, 29, 23, 37, 0, 0, time.UTC) + + listOTP []string + ) + + listOTP, err = proto.GenerateNWithTime(ts, secret, 3) + if err != nil { + log.Fatal(err) + } + + fmt.Println(listOTP) + // Output: + // [933840 870583 802638] +} + +func ExampleProtocol_GenerateWithTime() { + var ( + secretHex = `3132333435363738393031323334353637383930` + + secret []byte + err error + ) + + secret, err = hex.DecodeString(secretHex) + if err != nil { + log.Fatal(err) + } + + var ( + proto = totp.New(totp.CryptoHashSHA1, totp.DefCodeDigits, totp.DefTimeStep) + ts = time.Date(2024, time.January, 29, 23, 37, 0, 0, time.UTC) + + otp string + ) + + otp, err = proto.GenerateWithTime(ts, secret) + if err != nil { + log.Fatal(err) + } + + fmt.Println(otp) + // Output: + // 933840 +} + func ExampleProtocol_Verify() { var ( secretHex = `3132333435363738393031323334353637383930` - proto = New(CryptoHashSHA1, DefCodeDigits, DefTimeStep) - otp string err error secret []byte ) @@ -25,6 +86,12 @@ func ExampleProtocol_Verify() { log.Fatal(err) } + var ( + proto = totp.New(totp.CryptoHashSHA1, totp.DefCodeDigits, totp.DefTimeStep) + + otp string + ) + otp, _ = proto.Generate(secret) if proto.Verify(secret, otp, 1) { -- cgit v1.3