From a535a832c2667e8f022fffe6f1612dfe833b1b69 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Thu, 21 Mar 2024 22:34:54 +0100 Subject: [PATCH] Add TOTP Export Support --- go.mod | 2 ++ go.sum | 5 +++++ keepass/export.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/go.mod b/go.mod index 0600b61..ae57b5e 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/aead/argon2 v0.0.0-20180111183520-a87724528b07 // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/console v1.0.4 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect @@ -40,6 +41,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pquerna/otp v1.4.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect diff --git a/go.sum b/go.sum index 9b98bb8..2a7ebc3 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,8 @@ github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPp github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= +github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -234,6 +236,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= +github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= @@ -290,6 +294,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/keepass/export.go b/keepass/export.go index 38f422b..54f23a4 100644 --- a/keepass/export.go +++ b/keepass/export.go @@ -2,12 +2,15 @@ package keepass import ( "context" + "encoding/json" "fmt" "os" "github.com/passbolt/go-passbolt-cli/util" "github.com/passbolt/go-passbolt/api" "github.com/passbolt/go-passbolt/helper" + "github.com/pquerna/otp" + "github.com/pquerna/otp/totp" "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/tobischo/gokeepasslib/v3" @@ -103,6 +106,57 @@ func KeepassExport(cmd *cobra.Command, args []string) error { gokeepasslib.ValueData{Key: "Password", Value: gokeepasslib.V{Content: pass, Protected: w.NewBoolWrapper(true)}}, gokeepasslib.ValueData{Key: "Notes", Value: gokeepasslib.V{Content: desc}}, ) + + if resource.ResourceType.Slug == "password-description-totp" || resource.ResourceType.Slug == "totp" { + var totpData api.SecretDataTOTP + + rawSecretData, err := client.DecryptMessage(resource.Secrets[0].Data) + if err != nil { + return fmt.Errorf("Decrypting Secret Data: %w", err) + } + + if resource.ResourceType.Slug == "password-description-totp" { + var secretData api.SecretDataTypePasswordDescriptionTOTP + err = json.Unmarshal([]byte(rawSecretData), &secretData) + if err != nil { + return fmt.Errorf("Parsing Decrypted Secret Data: %w", err) + } + totpData = secretData.TOTP + } else { + var secretData api.SecretDataTOTP + err = json.Unmarshal([]byte(rawSecretData), &secretData) + if err != nil { + return fmt.Errorf("Parsing Decrypted Secret Data: %w", err) + } + totpData = secretData + } + + var alg otp.Algorithm + + switch totpData.Algorithm { + case "SHA1": + alg = otp.AlgorithmSHA1 + case "SHA256": + alg = otp.AlgorithmSHA256 + default: + return fmt.Errorf("Unsuported TOTP Algorithm: %v ", totpData.Algorithm) + } + + totpKey, err := totp.Generate(totp.GenerateOpts{ + Issuer: resource.URI, + AccountName: resource.Username, + Secret: []byte(totpData.SecretKey), + Algorithm: alg, + Period: uint(totpData.Period), + Digits: otp.Digits(totpData.Digits), + }) + if err != nil { + return fmt.Errorf("Generating TOTP Key: %w", err) + } + + entry.Values = append(entry.Values, gokeepasslib.ValueData{Key: "otp", Value: gokeepasslib.V{Content: totpKey.URL(), Protected: w.NewBoolWrapper(true)}}) + } + rootGroup.Entries = append(rootGroup.Entries, entry) progressbar.Increment() }