From d2f03751b6edb8063555cebfd5432c4bd4baaa55 Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Fri, 3 Dec 2021 17:17:36 +0100 Subject: [PATCH] feat: Add PGP encryption support --- cmd/stbak/cmd/archive.go | 31 +++++++++++++++++++++++++++++++ cmd/stbak/cmd/recovery_index.go | 2 ++ cmd/stbak/cmd/root.go | 5 ++++- go.mod | 1 + go.sum | 3 +++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/cmd/stbak/cmd/archive.go b/cmd/stbak/cmd/archive.go index 835222f..570ca04 100644 --- a/cmd/stbak/cmd/archive.go +++ b/cmd/stbak/cmd/archive.go @@ -17,6 +17,7 @@ import ( "strconv" "filippo.io/age" + "github.com/ProtonMail/go-crypto/openpgp" "github.com/andybalholm/brotli" "github.com/dsnet/compress/bzip2" "github.com/klauspost/compress/zstd" @@ -471,6 +472,8 @@ func addSuffix(name string, compressionFormat string, encryptionFormat string) ( switch encryptionFormat { case encryptionFormatAgeKey: name += encryptionFormatAgeSuffix + case encryptionFormatPGPKey: + name += encryptionFormatPGPSuffix case compressionFormatNoneKey: default: return "", errUnsupportedEncryptionFormat @@ -492,6 +495,13 @@ func encrypt( } return age.Encrypt(dst, recipient) + case encryptionFormatPGPKey: + recipient, err := openpgp.ReadKeyRing(bytes.NewBuffer(pubkey)) + if err != nil { + return nil, err + } + + return openpgp.Encrypt(dst, recipient, nil, nil, nil) case encryptionFormatNoneKey: return noop.AddClose(dst), nil default: @@ -525,6 +535,27 @@ func encryptString( return "", err } + return base64.StdEncoding.EncodeToString(out.Bytes()), nil + case encryptionFormatPGPKey: + recipient, err := openpgp.ReadKeyRing(bytes.NewBuffer(pubkey)) + if err != nil { + return "", err + } + + out := &bytes.Buffer{} + w, err := openpgp.Encrypt(out, recipient, nil, nil, nil) + if err != nil { + return "", err + } + + if _, err := io.WriteString(w, src); err != nil { + return "", err + } + + if err := w.Close(); err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(out.Bytes()), nil case encryptionFormatNoneKey: return src, nil diff --git a/cmd/stbak/cmd/recovery_index.go b/cmd/stbak/cmd/recovery_index.go index 1cc336e..5caea2e 100644 --- a/cmd/stbak/cmd/recovery_index.go +++ b/cmd/stbak/cmd/recovery_index.go @@ -416,6 +416,8 @@ func removeSuffix(name string, compressionFormat string, encryptionFormat string switch encryptionFormat { case encryptionFormatAgeKey: name = strings.TrimSuffix(name, encryptionFormatAgeSuffix) + case encryptionFormatPGPKey: + name = strings.TrimSuffix(name, encryptionFormatPGPSuffix) case encryptionFormatNoneKey: default: return "", errUnsupportedEncryptionFormat diff --git a/cmd/stbak/cmd/root.go b/cmd/stbak/cmd/root.go index 80a6fad..097775e 100644 --- a/cmd/stbak/cmd/root.go +++ b/cmd/stbak/cmd/root.go @@ -44,6 +44,9 @@ const ( encryptionFormatAgeKey = "age" encryptionFormatAgeSuffix = ".age" + + encryptionFormatPGPKey = "pgp" + encryptionFormatPGPSuffix = ".pgp" ) var ( @@ -52,7 +55,7 @@ var ( errUnknownCompressionFormat = errors.New("unknown compression format") errUnsupportedCompressionFormat = errors.New("unsupported compression format") - knownEncryptionFormats = []string{encryptionFormatNoneKey, encryptionFormatAgeKey} + knownEncryptionFormats = []string{encryptionFormatNoneKey, encryptionFormatAgeKey, encryptionFormatPGPKey} errUnknownEncryptionFormat = errors.New("unknown encryption format") errUnsupportedEncryptionFormat = errors.New("unsupported encryption format") diff --git a/go.mod b/go.mod index 3e713cc..b90aba3 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( ) require ( + github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/gofrs/uuid v3.2.0+incompatible // indirect github.com/hashicorp/hcl v1.0.0 // indirect diff --git a/go.sum b/go.sum index f145ba1..e48cffd 100644 --- a/go.sum +++ b/go.sum @@ -54,6 +54,8 @@ github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy86 github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3 h1:XcF0cTDJeiuZ5NU8w7WUDge0HRwwNRmxj/GGk6KSA6g= +github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -462,6 +464,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=