From 498ecd9a505021f2b92d4a966317dde9c555cd3b Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Fri, 22 Mar 2024 20:53:08 -0400 Subject: [PATCH] Implement Steam TOTP support using github.com/fortis/go-steam-totp --- go.mod | 1 + go.sum | 2 ++ src/offline/copy.go | 29 +++++++++++++++++++++++++---- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 484eeb2..2a4db99 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/rwinkhart/MUTN go 1.22.0 require ( + github.com/fortis/go-steam-totp v0.0.0-20171114202746-18e928674727 github.com/pquerna/otp v1.4.1-0.20231130234153-3357de7c0481 golang.org/x/crypto v0.20.0 gopkg.in/ini.v1 v1.67.0 diff --git a/go.sum b/go.sum index 5b46588..0881027 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fortis/go-steam-totp v0.0.0-20171114202746-18e928674727 h1:1RkPJqfzrncAuh9xgoslr9OplZskm+VRA9lkucHPQZ4= +github.com/fortis/go-steam-totp v0.0.0-20171114202746-18e928674727/go.mod h1:wRAWHbTlpt0C4kwnKoa42L2Phrv6uIq+c50P2uKpb7I= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/otp v1.4.1-0.20231130234153-3357de7c0481 h1:FkxbO331O7mS5EJkP+MCi0o2gswh/Aezs+//NmefrR8= diff --git a/src/offline/copy.go b/src/offline/copy.go index 0c804fd..6bf65b9 100644 --- a/src/offline/copy.go +++ b/src/offline/copy.go @@ -3,8 +3,10 @@ package offline import ( "bufio" "fmt" + steamtotp "github.com/fortis/go-steam-totp" "github.com/pquerna/otp/totp" "os" + "strings" "time" ) @@ -27,9 +29,19 @@ func CopyArgument(targetLocation string, field int, executableName string) { if field != 5 { // TODO Update field after removed from notes (breaking sshyp entry compatibility) copySubject = decryptedEntry[field] } else { // TOTP mode + var secret string // stores secret for TOTP generation + var forSteam bool // indicates whether to generate TOTP in Steam format + + if strings.HasPrefix(decryptedEntry[5], "steam@") { + secret = decryptedEntry[5][6:] + forSteam = true + } else { + secret = decryptedEntry[5] + } + for { // keep field copied to clipboard, refresh on 30-second intervals currentTime := time.Now() - copyField(genTOTP(decryptedEntry[5], currentTime), "") + copyField(genTOTP(secret, currentTime, forSteam), "") // sleep until next 30-second interval time.Sleep(time.Duration(30-(currentTime.Second()%30)) * time.Second) } @@ -56,12 +68,21 @@ func ClipClearArgument() { } } -// genTOTP generates a TOTP token from a secret -func genTOTP(secret string, time time.Time) string { - totpToken, err := totp.GenerateCode(secret, time) +// genTOTP generates a TOTP token from a secret (supports standard and Steam TOTP) +func genTOTP(secret string, time time.Time, forSteam bool) string { + var totpToken string + var err error + + if forSteam { + totpToken, err = steamtotp.GenerateAuthCode(secret, time) + } else { + totpToken, err = totp.GenerateCode(secret, time) + } + if err != nil { fmt.Println(AnsiError + "Error generating TOTP code" + AnsiReset) os.Exit(1) } + return totpToken }