diff --git a/WORKSPACE b/WORKSPACE index 63ef13cd..99097313 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -57,8 +57,8 @@ http_archive( ], ) -load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository") +load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") load("//:repositories.bzl", "go_repositories") go_rules_dependencies() diff --git a/go.mod b/go.mod index 3c2a8106..73da520e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( bazel.build/protobuf v0.0.0-00010101000000-000000000000 cirello.io/dynamolock v1.4.0 github.com/ProtonMail/go-crypto v1.0.0 - github.com/ProtonMail/gopenpgp/v2 v2.4.7 + github.com/ProtonMail/gopenpgp/v2 v2.7.5 github.com/authzed/authzed-go v0.3.0 github.com/authzed/grpcutil v0.0.0-20240123194739-2ea1e3d2d98b github.com/aws/aws-sdk-go v1.54.19 @@ -65,7 +65,7 @@ require ( cloud.google.com/go/storage v1.43.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f // indirect + github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index c3d194b4..ccc7f914 100644 --- a/go.sum +++ b/go.sum @@ -57,13 +57,13 @@ github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f h1:CGq7OieOz3wyQJ1fO8S0eO9TCW1JyvLrf8fhzz1i8ko= -github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= -github.com/ProtonMail/gopenpgp/v2 v2.4.7 h1:V3xeelvXgJiZXZuPtSSE+uYbtPw4RmbmyPqXDAESPhg= -github.com/ProtonMail/gopenpgp/v2 v2.4.7/go.mod h1:ZW1KxHNG6q5LMgFKf9Ap/d2eVYeyGf5+fAUEAjJWtmo= +github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= +github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= +github.com/ProtonMail/gopenpgp/v2 v2.7.5 h1:STOY3vgES59gNgoOt2w0nyHBjKViB/qSg7NjbQWPJkA= +github.com/ProtonMail/gopenpgp/v2 v2.7.5/go.mod h1:IhkNEDaxec6NyzSI0PlxapinnwPVIESk8/76da3Ct3g= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= @@ -552,7 +552,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= @@ -562,7 +561,6 @@ golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= @@ -587,12 +585,10 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -775,7 +771,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= diff --git a/repositories.bzl b/repositories.bzl index 699c6ead..afee6074 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -171,9 +171,9 @@ def go_repositories(): ) go_repository( name = "com_github_cloudflare_circl", + importpath = "github.com/cloudflare/circl", patch_args = ["-p1"], patches = ["//patches:circl.patch"], - importpath = "github.com/cloudflare/circl", sum = "h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=", version = "v1.3.9", ) @@ -1078,14 +1078,14 @@ def go_repositories(): go_repository( name = "com_github_protonmail_go_mime", importpath = "github.com/ProtonMail/go-mime", - sum = "h1:CGq7OieOz3wyQJ1fO8S0eO9TCW1JyvLrf8fhzz1i8ko=", - version = "v0.0.0-20220302105931-303f85f7fe0f", + sum = "h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k=", + version = "v0.0.0-20230322103455-7d82a3887f2f", ) go_repository( name = "com_github_protonmail_gopenpgp_v2", importpath = "github.com/ProtonMail/gopenpgp/v2", - sum = "h1:V3xeelvXgJiZXZuPtSSE+uYbtPw4RmbmyPqXDAESPhg=", - version = "v2.4.7", + sum = "h1:STOY3vgES59gNgoOt2w0nyHBjKViB/qSg7NjbQWPJkA=", + version = "v2.7.5", ) go_repository( name = "com_github_rivo_uniseg", @@ -2285,8 +2285,8 @@ def go_repositories(): go_repository( name = "org_golang_x_mobile", importpath = "golang.org/x/mobile", - sum = "h1:OVJ6QQUBAesB8CZijKDSsXX7xYVtUhrkY0gwMfbi4p4=", - version = "v0.0.0-20200801112145-973feb4309de", + sum = "h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=", + version = "v0.0.0-20190719004257-d2bd2a29d028", ) go_repository( name = "org_golang_x_mod", diff --git a/vendor/github.com/ProtonMail/go-mime/BUILD.bazel b/vendor/github.com/ProtonMail/go-mime/BUILD.bazel index 96df1c97..cc3a1a71 100644 --- a/vendor/github.com/ProtonMail/go-mime/BUILD.bazel +++ b/vendor/github.com/ProtonMail/go-mime/BUILD.bazel @@ -11,7 +11,6 @@ go_library( importpath = "github.com/ProtonMail/go-mime", visibility = ["//visibility:public"], deps = [ - "//vendor/github.com/sirupsen/logrus", "//vendor/golang.org/x/text/encoding", "//vendor/golang.org/x/text/encoding/htmlindex", "//vendor/golang.org/x/text/transform", diff --git a/vendor/github.com/ProtonMail/go-mime/README.md b/vendor/github.com/ProtonMail/go-mime/README.md index a78b7476..efee623a 100644 --- a/vendor/github.com/ProtonMail/go-mime/README.md +++ b/vendor/github.com/ProtonMail/go-mime/README.md @@ -1,6 +1,25 @@ # Go Mime Wrapper Library +Provides a parser for MIME messages + ## Download/Install Run `go get -u github.com/ProtonMail/go-mime`, or manually `git clone` the repository into `$GOPATH/src/github.com/ProtonMail/go-mime`. + + +## Usage + +The library can be used to extract the body and attachments from a MIME message + +Example: +```go +printAccepter := gomime.NewMIMEPrinter() +bodyCollector := gomime.NewBodyCollector(printAccepter) +attachmentsCollector := gomime.NewAttachmentsCollector(bodyCollector) +mimeVisitor := gomime.NewMimeVisitor(attachmentsCollector) +err := gomime.VisitAll(bytes.NewReader(mmBodyData), h, mimeVisitor) +attachments := attachmentsCollector.GetAttachments(), +attachmentsHeaders := attachmentsCollector.GetAttHeaders() +bodyContent, bodyMimeType := bodyCollector.GetBody() +``` diff --git a/vendor/github.com/ProtonMail/go-mime/encoding.go b/vendor/github.com/ProtonMail/go-mime/encoding.go index cf237e6a..fced2149 100644 --- a/vendor/github.com/ProtonMail/go-mime/encoding.go +++ b/vendor/github.com/ProtonMail/go-mime/encoding.go @@ -1,7 +1,6 @@ package gomime import ( - "bytes" "fmt" "io" "mime" @@ -11,9 +10,9 @@ import ( "unicode/utf8" "encoding/base64" + "golang.org/x/text/encoding" "golang.org/x/text/encoding/htmlindex" - "golang.org/x/text/transform" ) var wordDec = &mime.WordDecoder{ @@ -189,21 +188,13 @@ func DecodeCharset(original []byte, mediaType string, contentTypeParams map[stri } err = fmt.Errorf("non-utf8 content without charset specification") } - if err != nil { return original, err } - - utf8 := make([]byte, len(original)) - nDst, nSrc, err := decoder.Transform(utf8, original, false) - for err == transform.ErrShortDst { - utf8 = make([]byte, (nDst/nSrc+1)*len(original)) - nDst, nSrc, err = decoder.Transform(utf8, original, false) - } + utf8, err := decoder.Bytes(original) if err != nil { return original, err } - utf8 = bytes.Trim(utf8, "\x00") return utf8, nil } diff --git a/vendor/github.com/ProtonMail/go-mime/parser.go b/vendor/github.com/ProtonMail/go-mime/parser.go index 4bbc0d73..e36cd879 100644 --- a/vendor/github.com/ProtonMail/go-mime/parser.go +++ b/vendor/github.com/ProtonMail/go-mime/parser.go @@ -5,6 +5,7 @@ import ( "bytes" "io" "io/ioutil" + "log" "mime" "mime/multipart" "net/http" @@ -12,8 +13,6 @@ import ( "net/textproto" "regexp" "strings" - - log "github.com/sirupsen/logrus" ) // VisitAcceptor decidest what to do with part which is processed @@ -181,7 +180,7 @@ func GetMultipartParts(r io.Reader, params map[string]string) (parts []io.Reader headers = []textproto.MIMEHeader{} var p *multipart.Part for { - p, err = mr.NextPart() + p, err = mr.NextRawPart() if err == io.EOF { err = nil break @@ -275,7 +274,7 @@ func checkHeaders(headers []textproto.MIMEHeader) bool { func decodePart(partReader io.Reader, header textproto.MIMEHeader) (decodedPart io.Reader) { decodedPart = DecodeContentEncoding(partReader, header.Get("Content-Transfer-Encoding")) if decodedPart == nil { - log.Warnf("Unsupported Content-Transfer-Encoding '%v'", header.Get("Content-Transfer-Encoding")) + log.Printf("Unsupported Content-Transfer-Encoding '%v'", header.Get("Content-Transfer-Encoding")) decodedPart = partReader } return @@ -376,7 +375,7 @@ func (ptc *PlainTextCollector) Accept(partReader io.Reader, header textproto.MIM if buffer, err := ioutil.ReadAll(decodedPart); err == nil { buffer, err = DecodeCharset(buffer, mediaType, params) if err != nil { - log.Warnln("Decode charset error:", err) + log.Println("Decode charset error:", err) err = nil // Don't fail parsing on decoding errors, use original } ptc.plainTextContents.Write(buffer) @@ -431,7 +430,7 @@ func (bc *BodyCollector) Accept(partReader io.Reader, header textproto.MIMEHeade if buffer, err := ioutil.ReadAll(decodedPart); err == nil { buffer, err = DecodeCharset(buffer, mediaType, params) if err != nil { - log.Warnln("Decode charset error:", err) + log.Println("Decode charset error:", err) err = nil // Don't fail parsing on decoding errors, use original } if mediaType == "text/html" { @@ -500,7 +499,7 @@ func (ac *AttachmentsCollector) Accept(partReader io.Reader, header textproto.MI if buffer, err := ioutil.ReadAll(decodedPart); err == nil { buffer, err = DecodeCharset(buffer, mediaType, params) if err != nil { - log.Warnln("Decode charset error:", err) + log.Println("Decode charset error:", err) err = nil // Don't fail parsing on decoding errors, use original } headerBuf := new(bytes.Buffer) diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/BUILD.bazel b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/BUILD.bazel index 93e6a86c..093d54b4 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/BUILD.bazel +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "armor.go", "cipher.go", + "context.go", "version.go", ], importmap = "peridot.resf.org/vendor/github.com/ProtonMail/gopenpgp/v2/constants", diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/armor.go b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/armor.go index 2c755774..0d2c1925 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/armor.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/armor.go @@ -3,7 +3,7 @@ package constants // Constants for armored data. const ( - ArmorHeaderVersion = "GopenPGP 2.4.7" + ArmorHeaderVersion = "GopenPGP 2.7.5" ArmorHeaderComment = "https://gopenpgp.org" PGPMessageHeader = "PGP MESSAGE" PGPSignatureHeader = "PGP SIGNATURE" diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/cipher.go b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/cipher.go index 970960ce..ab8c72ee 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/cipher.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/cipher.go @@ -15,6 +15,7 @@ const ( SIGNATURE_NOT_SIGNED int = 1 SIGNATURE_NO_VERIFIER int = 2 SIGNATURE_FAILED int = 3 + SIGNATURE_BAD_CONTEXT int = 4 ) const DefaultCompression = 2 // ZLIB diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/context.go b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/context.go new file mode 100644 index 00000000..ca001526 --- /dev/null +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/context.go @@ -0,0 +1,3 @@ +package constants + +const SignatureContextName = "context@proton.ch" diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/version.go b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/version.go index 29df3e3d..cca8c39c 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/constants/version.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/constants/version.go @@ -1,3 +1,3 @@ package constants -const Version = "2.4.7" +const Version = "2.7.5" diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/BUILD.bazel b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/BUILD.bazel index e8b536a2..25ca3191 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/BUILD.bazel +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "message_getters.go", "mime.go", "password.go", + "sanitize_string.go", "sessionkey.go", "sessionkey_streaming.go", "signature.go", @@ -34,6 +35,8 @@ go_library( "@com_github_protonmail_go_crypto//openpgp", "@com_github_protonmail_go_crypto//openpgp/clearsign", "@com_github_protonmail_go_crypto//openpgp/ecdh", + "@com_github_protonmail_go_crypto//openpgp/ecdsa", + "@com_github_protonmail_go_crypto//openpgp/eddsa", "@com_github_protonmail_go_crypto//openpgp/elgamal", "@com_github_protonmail_go_crypto//openpgp/errors", "@com_github_protonmail_go_crypto//openpgp/packet", diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/attachment_manual.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/attachment_manual.go index 6e33c1f1..39a2957a 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/attachment_manual.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/attachment_manual.go @@ -75,7 +75,7 @@ func (keyRing *KeyRing) NewManualAttachmentProcessor( estimatedSize int, filename string, dataBuffer []byte, ) (*ManualAttachmentProcessor, error) { if len(dataBuffer) == 0 { - return nil, errors.New("gopenpgp: can't give a nil or empty buffer to process the attachement") + return nil, errors.New("gopenpgp: can't give a nil or empty buffer to process the attachment") } // forces the gc to be called often @@ -148,7 +148,7 @@ func (keyRing *KeyRing) NewManualAttachmentProcessor( return attachmentProc, nil } -// readAll works a bit like io.ReadAll +// readAll works a bit like ioutil.ReadAll // but we can choose the buffer to write to // and we don't grow the slice in case of overflow. func readAll(buffer []byte, reader io.Reader) (int, error) { diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/key_clear.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/key_clear.go index 0f2e8952..c628f363 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/key_clear.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/key_clear.go @@ -2,13 +2,13 @@ package crypto import ( "crypto/dsa" //nolint:staticcheck - "crypto/ecdsa" - "crypto/ed25519" "crypto/rsa" "errors" "math/big" "github.com/ProtonMail/go-crypto/openpgp/ecdh" + "github.com/ProtonMail/go-crypto/openpgp/ecdsa" + "github.com/ProtonMail/go-crypto/openpgp/eddsa" "github.com/ProtonMail/go-crypto/openpgp/elgamal" ) @@ -57,7 +57,7 @@ func clearPrivateKey(privateKey interface{}) error { return clearElGamalPrivateKey(priv) case *ecdsa.PrivateKey: return clearECDSAPrivateKey(priv) - case *ed25519.PrivateKey: + case *eddsa.PrivateKey: return clearEdDSAPrivateKey(priv) case *ecdh.PrivateKey: return clearECDHPrivateKey(priv) @@ -115,8 +115,8 @@ func clearECDSAPrivateKey(priv *ecdsa.PrivateKey) error { return nil } -func clearEdDSAPrivateKey(priv *ed25519.PrivateKey) error { - clearMem(*priv) +func clearEdDSAPrivateKey(priv *eddsa.PrivateKey) error { + clearMem(priv.D) return nil } diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_message.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_message.go index 4c2c9cd4..f0fc16e0 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_message.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_message.go @@ -2,7 +2,6 @@ package crypto import ( "bytes" - "crypto" "io" "io/ioutil" "time" @@ -18,13 +17,16 @@ import ( // * message : The plaintext input as a PlainMessage. // * privateKey : (optional) an unlocked private keyring to include signature in the message. func (keyRing *KeyRing) Encrypt(message *PlainMessage, privateKey *KeyRing) (*PGPMessage, error) { - config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()} - encrypted, err := asymmetricEncrypt(message, keyRing, privateKey, config) - if err != nil { - return nil, err - } + return asymmetricEncrypt(message, keyRing, privateKey, false, nil) +} - return NewPGPMessage(encrypted), nil +// EncryptWithContext encrypts a PlainMessage, outputs a PGPMessage. +// If an unlocked private key is also provided it will also sign the message. +// * message : The plaintext input as a PlainMessage. +// * privateKey : (optional) an unlocked private keyring to include signature in the message. +// * signingContext : (optional) the context for the signature. +func (keyRing *KeyRing) EncryptWithContext(message *PlainMessage, privateKey *KeyRing, signingContext *SigningContext) (*PGPMessage, error) { + return asymmetricEncrypt(message, keyRing, privateKey, false, signingContext) } // EncryptWithCompression encrypts with compression support a PlainMessage to PGPMessage using public/private keys. @@ -32,60 +34,92 @@ func (keyRing *KeyRing) Encrypt(message *PlainMessage, privateKey *KeyRing) (*PG // * privateKey : (optional) an unlocked private keyring to include signature in the message. // * output : The encrypted data as PGPMessage. func (keyRing *KeyRing) EncryptWithCompression(message *PlainMessage, privateKey *KeyRing) (*PGPMessage, error) { - config := &packet.Config{ - DefaultCipher: packet.CipherAES256, - Time: getTimeGenerator(), - DefaultCompressionAlgo: constants.DefaultCompression, - CompressionConfig: &packet.CompressionConfig{Level: constants.DefaultCompressionLevel}, - } + return asymmetricEncrypt(message, keyRing, privateKey, true, nil) +} - encrypted, err := asymmetricEncrypt(message, keyRing, privateKey, config) - if err != nil { - return nil, err - } - - return NewPGPMessage(encrypted), nil +// EncryptWithContextAndCompression encrypts with compression support a PlainMessage to PGPMessage using public/private keys. +// * message : The plain data as a PlainMessage. +// * privateKey : (optional) an unlocked private keyring to include signature in the message. +// * signingContext : (optional) the context for the signature. +// * output : The encrypted data as PGPMessage. +func (keyRing *KeyRing) EncryptWithContextAndCompression(message *PlainMessage, privateKey *KeyRing, signingContext *SigningContext) (*PGPMessage, error) { + return asymmetricEncrypt(message, keyRing, privateKey, true, signingContext) } // Decrypt decrypts encrypted string using pgp keys, returning a PlainMessage // * message : The encrypted input as a PGPMessage // * verifyKey : Public key for signature verification (optional) // * verifyTime : Time at verification (necessary only if verifyKey is not nil) +// * verificationContext : (optional) the context for the signature verification. // // When verifyKey is not provided, then verifyTime should be zero, and // signature verification will be ignored. func (keyRing *KeyRing) Decrypt( message *PGPMessage, verifyKey *KeyRing, verifyTime int64, ) (*PlainMessage, error) { - return asymmetricDecrypt(message.NewReader(), keyRing, verifyKey, verifyTime) + return asymmetricDecrypt(message.NewReader(), keyRing, verifyKey, verifyTime, nil) +} + +// DecryptWithContext decrypts encrypted string using pgp keys, returning a PlainMessage +// * message : The encrypted input as a PGPMessage +// * verifyKey : Public key for signature verification (optional) +// * verifyTime : Time at verification (necessary only if verifyKey is not nil) +// * verificationContext : (optional) the context for the signature verification. +// +// When verifyKey is not provided, then verifyTime should be zero, and +// signature verification will be ignored. +func (keyRing *KeyRing) DecryptWithContext( + message *PGPMessage, + verifyKey *KeyRing, + verifyTime int64, + verificationContext *VerificationContext, +) (*PlainMessage, error) { + return asymmetricDecrypt(message.NewReader(), keyRing, verifyKey, verifyTime, verificationContext) } // SignDetached generates and returns a PGPSignature for a given PlainMessage. func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, error) { - signEntity, err := keyRing.getSigningEntity() - if err != nil { - return nil, err - } + return keyRing.SignDetachedWithContext(message, nil) +} - config := &packet.Config{DefaultHash: crypto.SHA512, Time: getTimeGenerator()} - var outBuf bytes.Buffer - // sign bin - if err := openpgp.DetachSign(&outBuf, signEntity, message.NewReader(), config); err != nil { - return nil, errors.Wrap(err, "gopenpgp: error in signing") - } - - return NewPGPSignature(outBuf.Bytes()), nil +// SignDetachedWithContext generates and returns a PGPSignature for a given PlainMessage. +// If a context is provided, it is added to the signature as notation data +// with the name set in `constants.SignatureContextName`. +func (keyRing *KeyRing) SignDetachedWithContext(message *PlainMessage, context *SigningContext) (*PGPSignature, error) { + return signMessageDetached( + keyRing, + message.NewReader(), + message.IsBinary(), + context, + ) } // VerifyDetached verifies a PlainMessage with a detached PGPSignature // and returns a SignatureVerificationError if fails. func (keyRing *KeyRing) VerifyDetached(message *PlainMessage, signature *PGPSignature, verifyTime int64) error { - return verifySignature( + _, err := verifySignature( keyRing.entities, message.NewReader(), signature.GetBinary(), verifyTime, + nil, ) + return err +} + +// VerifyDetachedWithContext verifies a PlainMessage with a detached PGPSignature +// and returns a SignatureVerificationError if fails. +// If a context is provided, it verifies that the signature is valid in the given context, using +// the signature notation with name the name set in `constants.SignatureContextName`. +func (keyRing *KeyRing) VerifyDetachedWithContext(message *PlainMessage, signature *PGPSignature, verifyTime int64, verificationContext *VerificationContext) error { + _, err := verifySignature( + keyRing.entities, + message.NewReader(), + signature.GetBinary(), + verifyTime, + verificationContext, + ) + return err } // SignDetachedEncrypted generates and returns a PGPMessage @@ -122,38 +156,41 @@ func (keyRing *KeyRing) VerifyDetachedEncrypted(message *PlainMessage, encrypted // returns the creation time of the signature if it succeeds // and returns a SignatureVerificationError if fails. func (keyRing *KeyRing) GetVerifiedSignatureTimestamp(message *PlainMessage, signature *PGPSignature, verifyTime int64) (int64, error) { - packets := packet.NewReader(bytes.NewReader(signature.Data)) - var err error - var p packet.Packet - for { - p, err = packets.Next() - if errors.Is(err, io.EOF) { - break - } - if err != nil { - continue - } - sigPacket, ok := p.(*packet.Signature) - if !ok { - continue - } - var outBuf bytes.Buffer - err = sigPacket.Serialize(&outBuf) - if err != nil { - continue - } - err = verifySignature( - keyRing.entities, - message.NewReader(), - outBuf.Bytes(), - verifyTime, - ) - if err != nil { - continue - } - return sigPacket.CreationTime.Unix(), nil + sigPacket, err := verifySignature( + keyRing.entities, + message.NewReader(), + signature.GetBinary(), + verifyTime, + nil, + ) + if err != nil { + return 0, err } - return 0, errors.Wrap(err, "gopenpgp: can't verify any signature packets") + return sigPacket.CreationTime.Unix(), nil +} + +// GetVerifiedSignatureTimestampWithContext verifies a PlainMessage with a detached PGPSignature +// returns the creation time of the signature if it succeeds +// and returns a SignatureVerificationError if fails. +// If a context is provided, it verifies that the signature is valid in the given context, using +// the signature notation with name the name set in `constants.SignatureContextName`. +func (keyRing *KeyRing) GetVerifiedSignatureTimestampWithContext( + message *PlainMessage, + signature *PGPSignature, + verifyTime int64, + verificationContext *VerificationContext, +) (int64, error) { + sigPacket, err := verifySignature( + keyRing.entities, + message.NewReader(), + signature.GetBinary(), + verifyTime, + verificationContext, + ) + if err != nil { + return 0, err + } + return sigPacket.CreationTime.Unix(), nil } // ------ INTERNAL FUNCTIONS ------- @@ -162,8 +199,9 @@ func (keyRing *KeyRing) GetVerifiedSignatureTimestamp(message *PlainMessage, sig func asymmetricEncrypt( plainMessage *PlainMessage, publicKey, privateKey *KeyRing, - config *packet.Config, -) ([]byte, error) { + compress bool, + signingContext *SigningContext, +) (*PGPMessage, error) { var outBuf bytes.Buffer var encryptWriter io.WriteCloser var err error @@ -174,7 +212,7 @@ func asymmetricEncrypt( ModTime: plainMessage.getFormattedTime(), } - encryptWriter, err = asymmetricEncryptStream(hints, &outBuf, &outBuf, publicKey, privateKey, config) + encryptWriter, err = asymmetricEncryptStream(hints, &outBuf, &outBuf, publicKey, privateKey, compress, signingContext) if err != nil { return nil, err } @@ -189,7 +227,7 @@ func asymmetricEncrypt( return nil, errors.Wrap(err, "gopenpgp: error in closing message") } - return outBuf.Bytes(), nil + return &PGPMessage{outBuf.Bytes()}, nil } // Core for encryption+signature (all) functions. @@ -198,10 +236,24 @@ func asymmetricEncryptStream( keyPacketWriter io.Writer, dataPacketWriter io.Writer, publicKey, privateKey *KeyRing, - config *packet.Config, + compress bool, + signingContext *SigningContext, ) (encryptWriter io.WriteCloser, err error) { - var signEntity *openpgp.Entity + config := &packet.Config{ + DefaultCipher: packet.CipherAES256, + Time: getTimeGenerator(), + } + if compress { + config.DefaultCompressionAlgo = constants.DefaultCompression + config.CompressionConfig = &packet.CompressionConfig{Level: constants.DefaultCompressionLevel} + } + + if signingContext != nil { + config.SignatureNotations = append(config.SignatureNotations, signingContext.getNotation()) + } + + var signEntity *openpgp.Entity if privateKey != nil && len(privateKey.entities) > 0 { var err error signEntity, err = privateKey.getSigningEntity() @@ -223,13 +275,18 @@ func asymmetricEncryptStream( // Core for decryption+verification (non streaming) functions. func asymmetricDecrypt( - encryptedIO io.Reader, privateKey *KeyRing, verifyKey *KeyRing, verifyTime int64, + encryptedIO io.Reader, + privateKey *KeyRing, + verifyKey *KeyRing, + verifyTime int64, + verificationContext *VerificationContext, ) (message *PlainMessage, err error) { messageDetails, err := asymmetricDecryptStream( encryptedIO, privateKey, verifyKey, verifyTime, + verificationContext, ) if err != nil { return nil, err @@ -242,7 +299,7 @@ func asymmetricDecrypt( if verifyKey != nil { processSignatureExpiration(messageDetails, verifyTime) - err = verifyDetailsSignature(messageDetails, verifyKey) + err = verifyDetailsSignature(messageDetails, verifyKey, verificationContext) } return &PlainMessage{ @@ -259,6 +316,7 @@ func asymmetricDecryptStream( privateKey *KeyRing, verifyKey *KeyRing, verifyTime int64, + verificationContext *VerificationContext, ) (messageDetails *openpgp.MessageDetails, err error) { privKeyEntries := privateKey.entities var additionalEntries openpgp.EntityList @@ -285,6 +343,10 @@ func asymmetricDecryptStream( }, } + if verificationContext != nil { + config.KnownNotations = map[string]bool{constants.SignatureContextName: true} + } + messageDetails, err = openpgp.ReadMessage(encryptedIO, privKeyEntries, nil, config) if err != nil { return nil, errors.Wrap(err, "gopenpgp: error in reading message") diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_session.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_session.go index ca2a94f9..638c1f78 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_session.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_session.go @@ -55,7 +55,11 @@ Loop: } if !hasPacket { - return nil, errors.Wrap(err, "gopenpgp: couldn't find a session key packet") + if err != nil { + return nil, errors.Wrap(err, "gopenpgp: couldn't find a session key packet") + } else { + return nil, errors.New("gopenpgp: couldn't find a session key packet") + } } if decryptErr != nil { diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_streaming.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_streaming.go index 215212a7..6d99402d 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_streaming.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/keyring_streaming.go @@ -2,12 +2,10 @@ package crypto import ( "bytes" - "crypto" "io" "time" "github.com/ProtonMail/go-crypto/openpgp" - "github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/pkg/errors" ) @@ -42,8 +40,89 @@ func (keyRing *KeyRing) EncryptStream( plainMessageMetadata *PlainMessageMetadata, signKeyRing *KeyRing, ) (plainMessageWriter WriteCloser, err error) { - config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()} + return encryptStream( + keyRing, + pgpMessageWriter, + pgpMessageWriter, + plainMessageMetadata, + signKeyRing, + false, + nil, + ) +} +// EncryptStreamWithContext is used to encrypt data as a Writer. +// It takes a writer for the encrypted data and returns a WriteCloser for the plaintext data +// If signKeyRing is not nil, it is used to do an embedded signature. +// * signingContext : (optional) a context for the embedded signature. +func (keyRing *KeyRing) EncryptStreamWithContext( + pgpMessageWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + signingContext *SigningContext, +) (plainMessageWriter WriteCloser, err error) { + return encryptStream( + keyRing, + pgpMessageWriter, + pgpMessageWriter, + plainMessageMetadata, + signKeyRing, + false, + signingContext, + ) +} + +// EncryptStreamWithCompression is used to encrypt data as a Writer. +// The plaintext data is compressed before being encrypted. +// It takes a writer for the encrypted data and returns a WriteCloser for the plaintext data +// If signKeyRing is not nil, it is used to do an embedded signature. +func (keyRing *KeyRing) EncryptStreamWithCompression( + pgpMessageWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, +) (plainMessageWriter WriteCloser, err error) { + return encryptStream( + keyRing, + pgpMessageWriter, + pgpMessageWriter, + plainMessageMetadata, + signKeyRing, + true, + nil, + ) +} + +// EncryptStreamWithContextAndCompression is used to encrypt data as a Writer. +// The plaintext data is compressed before being encrypted. +// It takes a writer for the encrypted data and returns a WriteCloser for the plaintext data +// If signKeyRing is not nil, it is used to do an embedded signature. +// * signingContext : (optional) a context for the embedded signature. +func (keyRing *KeyRing) EncryptStreamWithContextAndCompression( + pgpMessageWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + signingContext *SigningContext, +) (plainMessageWriter WriteCloser, err error) { + return encryptStream( + keyRing, + pgpMessageWriter, + pgpMessageWriter, + plainMessageMetadata, + signKeyRing, + true, + signingContext, + ) +} + +func encryptStream( + encryptionKeyRing *KeyRing, + keyPacketWriter Writer, + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + compress bool, + signingContext *SigningContext, +) (plainMessageWriter WriteCloser, err error) { if plainMessageMetadata == nil { // Use sensible default metadata plainMessageMetadata = &PlainMessageMetadata{ @@ -59,7 +138,7 @@ func (keyRing *KeyRing) EncryptStream( ModTime: time.Unix(plainMessageMetadata.ModTime, 0), } - plainMessageWriter, err = asymmetricEncryptStream(hints, pgpMessageWriter, pgpMessageWriter, keyRing, signKeyRing, config) + plainMessageWriter, err = asymmetricEncryptStream(hints, keyPacketWriter, dataPacketWriter, encryptionKeyRing, signKeyRing, compress, signingContext) if err != nil { return nil, err } @@ -107,28 +186,102 @@ func (keyRing *KeyRing) EncryptSplitStream( plainMessageMetadata *PlainMessageMetadata, signKeyRing *KeyRing, ) (*EncryptSplitResult, error) { - config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: getTimeGenerator()} + return encryptSplitStream( + keyRing, + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + false, + nil, + ) +} - if plainMessageMetadata == nil { - // Use sensible default metadata - plainMessageMetadata = &PlainMessageMetadata{ - IsBinary: true, - Filename: "", - ModTime: GetUnixTime(), - } - } +// EncryptSplitStreamWithContext is used to encrypt data as a stream. +// It takes a writer for the Symmetrically Encrypted Data Packet +// (https://datatracker.ietf.org/doc/html/rfc4880#section-5.7) +// and returns a writer for the plaintext data and the key packet. +// If signKeyRing is not nil, it is used to do an embedded signature. +// * signingContext : (optional) a context for the embedded signature. +func (keyRing *KeyRing) EncryptSplitStreamWithContext( + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + signingContext *SigningContext, +) (*EncryptSplitResult, error) { + return encryptSplitStream( + keyRing, + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + false, + signingContext, + ) +} - hints := &openpgp.FileHints{ - FileName: plainMessageMetadata.Filename, - IsBinary: plainMessageMetadata.IsBinary, - ModTime: time.Unix(plainMessageMetadata.ModTime, 0), - } +// EncryptSplitStreamWithCompression is used to encrypt data as a stream. +// It takes a writer for the Symmetrically Encrypted Data Packet +// (https://datatracker.ietf.org/doc/html/rfc4880#section-5.7) +// and returns a writer for the plaintext data and the key packet. +// If signKeyRing is not nil, it is used to do an embedded signature. +func (keyRing *KeyRing) EncryptSplitStreamWithCompression( + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, +) (*EncryptSplitResult, error) { + return encryptSplitStream( + keyRing, + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + true, + nil, + ) +} +// EncryptSplitStreamWithContextAndCompression is used to encrypt data as a stream. +// It takes a writer for the Symmetrically Encrypted Data Packet +// (https://datatracker.ietf.org/doc/html/rfc4880#section-5.7) +// and returns a writer for the plaintext data and the key packet. +// If signKeyRing is not nil, it is used to do an embedded signature. +// * signingContext : (optional) a context for the embedded signature. +func (keyRing *KeyRing) EncryptSplitStreamWithContextAndCompression( + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + signingContext *SigningContext, +) (*EncryptSplitResult, error) { + return encryptSplitStream( + keyRing, + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + true, + signingContext, + ) +} + +func encryptSplitStream( + encryptionKeyRing *KeyRing, + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + compress bool, + signingContext *SigningContext, +) (*EncryptSplitResult, error) { var keyPacketBuf bytes.Buffer - plainMessageWriter, err := asymmetricEncryptStream(hints, &keyPacketBuf, dataPacketWriter, keyRing, signKeyRing, config) + plainMessageWriter, err := encryptStream( + encryptionKeyRing, + &keyPacketBuf, + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + compress, + signingContext, + ) if err != nil { return nil, err } + return &EncryptSplitResult{ keyPacketBuf: &keyPacketBuf, plainMessageWriter: plainMessageWriter, @@ -138,10 +291,11 @@ func (keyRing *KeyRing) EncryptSplitStream( // PlainMessageReader is used to wrap the data of the decrypted plain message. // It can be used to read the decrypted data and verify the embedded signature. type PlainMessageReader struct { - details *openpgp.MessageDetails - verifyKeyRing *KeyRing - verifyTime int64 - readAll bool + details *openpgp.MessageDetails + verifyKeyRing *KeyRing + verifyTime int64 + readAll bool + verificationContext *VerificationContext } // GetMetadata returns the metadata of the decrypted message. @@ -173,7 +327,7 @@ func (msg *PlainMessageReader) VerifySignature() (err error) { } if msg.verifyKeyRing != nil { processSignatureExpiration(msg.details, msg.verifyTime) - err = verifyDetailsSignature(msg.details, msg.verifyKeyRing) + err = verifyDetailsSignature(msg.details, msg.verifyKeyRing, msg.verificationContext) } else { err = errors.New("gopenpgp: no verify keyring was provided before decryption") } @@ -190,11 +344,49 @@ func (keyRing *KeyRing) DecryptStream( verifyKeyRing *KeyRing, verifyTime int64, ) (plainMessage *PlainMessageReader, err error) { - messageDetails, err := asymmetricDecryptStream( - message, + return decryptStream( keyRing, + message, verifyKeyRing, verifyTime, + nil, + ) +} + +// DecryptStreamWithContext is used to decrypt a pgp message as a Reader. +// It takes a reader for the message data +// and returns a PlainMessageReader for the plaintext data. +// If verifyKeyRing is not nil, PlainMessageReader.VerifySignature() will +// verify the embedded signature with the given key ring and verification time. +// * verificationContext (optional): context for the signature verification. +func (keyRing *KeyRing) DecryptStreamWithContext( + message Reader, + verifyKeyRing *KeyRing, + verifyTime int64, + verificationContext *VerificationContext, +) (plainMessage *PlainMessageReader, err error) { + return decryptStream( + keyRing, + message, + verifyKeyRing, + verifyTime, + verificationContext, + ) +} + +func decryptStream( + decryptionKeyRing *KeyRing, + message Reader, + verifyKeyRing *KeyRing, + verifyTime int64, + verificationContext *VerificationContext, +) (plainMessage *PlainMessageReader, err error) { + messageDetails, err := asymmetricDecryptStream( + message, + decryptionKeyRing, + verifyKeyRing, + verifyTime, + verificationContext, ) if err != nil { return nil, err @@ -205,6 +397,7 @@ func (keyRing *KeyRing) DecryptStream( verifyKeyRing, verifyTime, false, + verificationContext, }, err } @@ -229,21 +422,45 @@ func (keyRing *KeyRing) DecryptSplitStream( ) } +// DecryptSplitStreamWithContext is used to decrypt a split pgp message as a Reader. +// It takes a key packet and a reader for the data packet +// and returns a PlainMessageReader for the plaintext data. +// If verifyKeyRing is not nil, PlainMessageReader.VerifySignature() will +// verify the embedded signature with the given key ring and verification time. +// * verificationContext (optional): context for the signature verification. +func (keyRing *KeyRing) DecryptSplitStreamWithContext( + keypacket []byte, + dataPacketReader Reader, + verifyKeyRing *KeyRing, verifyTime int64, + verificationContext *VerificationContext, +) (plainMessage *PlainMessageReader, err error) { + messageReader := io.MultiReader( + bytes.NewReader(keypacket), + dataPacketReader, + ) + return keyRing.DecryptStreamWithContext( + messageReader, + verifyKeyRing, + verifyTime, + verificationContext, + ) +} + // SignDetachedStream generates and returns a PGPSignature for a given message Reader. func (keyRing *KeyRing) SignDetachedStream(message Reader) (*PGPSignature, error) { - signEntity, err := keyRing.getSigningEntity() - if err != nil { - return nil, err - } + return keyRing.SignDetachedStreamWithContext(message, nil) +} - config := &packet.Config{DefaultHash: crypto.SHA512, Time: getTimeGenerator()} - var outBuf bytes.Buffer - // sign bin - if err := openpgp.DetachSign(&outBuf, signEntity, message, config); err != nil { - return nil, errors.Wrap(err, "gopenpgp: error in signing") - } - - return NewPGPSignature(outBuf.Bytes()), nil +// SignDetachedStreamWithContext generates and returns a PGPSignature for a given message Reader. +// If a context is provided, it is added to the signature as notation data +// with the name set in `constants.SignatureContextName`. +func (keyRing *KeyRing) SignDetachedStreamWithContext(message Reader, context *SigningContext) (*PGPSignature, error) { + return signMessageDetached( + keyRing, + message, + true, + context, + ) } // VerifyDetachedStream verifies a message reader with a detached PGPSignature @@ -253,12 +470,34 @@ func (keyRing *KeyRing) VerifyDetachedStream( signature *PGPSignature, verifyTime int64, ) error { - return verifySignature( + _, err := verifySignature( keyRing.entities, message, signature.GetBinary(), verifyTime, + nil, ) + return err +} + +// VerifyDetachedStreamWithContext verifies a message reader with a detached PGPSignature +// and returns a SignatureVerificationError if fails. +// If a context is provided, it verifies that the signature is valid in the given context, using +// the signature notations. +func (keyRing *KeyRing) VerifyDetachedStreamWithContext( + message Reader, + signature *PGPSignature, + verifyTime int64, + verificationContext *VerificationContext, +) error { + _, err := verifySignature( + keyRing.entities, + message, + signature.GetBinary(), + verifyTime, + verificationContext, + ) + return err } // SignDetachedEncryptedStream generates and returns a PGPMessage diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/message.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/message.go index ccdb5d33..284098fe 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/message.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/message.go @@ -3,6 +3,7 @@ package crypto import ( "bytes" "encoding/base64" + "encoding/json" goerrors "errors" "io" "io/ioutil" @@ -92,7 +93,7 @@ func NewPlainMessageFromFile(data []byte, filename string, time uint32) *PlainMe // This allows seamless conversion to clear text signed messages (see RFC 4880 5.2.1 and 7.1). func NewPlainMessageFromString(text string) *PlainMessage { return &PlainMessage{ - Data: []byte(internal.CanonicalizeAndTrim(text)), + Data: []byte(internal.Canonicalize(text)), TextType: true, Filename: "", Time: uint32(GetUnixTime()), @@ -202,7 +203,7 @@ func (msg *PlainMessage) GetBinary() []byte { // GetString returns the content of the message as a string. func (msg *PlainMessage) GetString() string { - return strings.ReplaceAll(string(msg.Data), "\r\n", "\n") + return sanitizeString(strings.ReplaceAll(string(msg.Data), "\r\n", "\n")) } // GetBase64 returns the base-64 encoded binary content of the message as a @@ -287,6 +288,21 @@ func (msg *PGPMessage) GetHexEncryptionKeyIDs() ([]string, bool) { return getHexKeyIDs(msg.GetEncryptionKeyIDs()) } +// GetHexEncryptionKeyIDsJson returns the key IDs of the keys to which the session key is encrypted as a JSON array. +// If an error occurs it returns nil. +// Helper function for go-mobile clients. +func (msg *PGPMessage) GetHexEncryptionKeyIDsJson() []byte { + hexIds, ok := msg.GetHexEncryptionKeyIDs() + if !ok { + return nil + } + hexIdsJson, err := json.Marshal(hexIds) + if err != nil { + return nil + } + return hexIdsJson +} + // GetSignatureKeyIDs Returns the key IDs of the keys to which the (readable) signature packets are encrypted to. func (msg *PGPMessage) GetSignatureKeyIDs() ([]uint64, bool) { return getSignatureKeyIDs(msg.Data) @@ -297,6 +313,20 @@ func (msg *PGPMessage) GetHexSignatureKeyIDs() ([]string, bool) { return getHexKeyIDs(msg.GetSignatureKeyIDs()) } +// GetHexSignatureKeyIDsJson returns the key IDs of the keys to which the (readable) signature packets +// are encrypted to as a JSON array. Helper function for go-mobile clients. +func (msg *PGPMessage) GetHexSignatureKeyIDsJson() []byte { + sigHexSigIds, ok := msg.GetHexSignatureKeyIDs() + if !ok { + return nil + } + sigHexKeyIdsJSON, err := json.Marshal(sigHexSigIds) + if err != nil { + return nil + } + return sigHexKeyIdsJSON +} + // GetBinaryDataPacket returns the unarmored binary datapacket as a []byte. func (msg *PGPSplitMessage) GetBinaryDataPacket() []byte { return msg.DataPacket @@ -324,6 +354,27 @@ func (msg *PGPSplitMessage) GetPGPMessage() *PGPMessage { return NewPGPMessage(append(msg.KeyPacket, msg.DataPacket...)) } +// GetNumberOfKeyPackets returns the number of keys packets in this message. +func (msg *PGPSplitMessage) GetNumberOfKeyPackets() (int, error) { + bytesReader := bytes.NewReader(msg.KeyPacket) + packets := packet.NewReader(bytesReader) + var keyPacketCount int + for { + p, err := packets.Next() + if goerrors.Is(err, io.EOF) { + break + } + if err != nil { + return 0, err + } + switch p.(type) { + case *packet.SymmetricKeyEncrypted, *packet.EncryptedKey: + keyPacketCount += 1 + } + } + return keyPacketCount, nil +} + // SplitMessage splits the message into key and data packet(s). // Parameters are for backwards compatibility and are unused. func (msg *PGPMessage) SplitMessage() (*PGPSplitMessage, error) { diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/mime.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/mime.go index 4d55cd00..d756dfcc 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/mime.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/mime.go @@ -49,7 +49,8 @@ func (keyRing *KeyRing) DecryptMIMEMessage( callbacks.OnVerified(constants.SIGNATURE_OK) } bodyContent, bodyMimeType := body.GetBody() - callbacks.OnBody(bodyContent, bodyMimeType) + bodyContentSanitized := sanitizeString(bodyContent) + callbacks.OnBody(bodyContentSanitized, bodyMimeType) for i := 0; i < len(attachments); i++ { callbacks.OnAttachment(attachmentHeaders[i], []byte(attachments[i])) } diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sanitize_string.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sanitize_string.go new file mode 100644 index 00000000..854e11f3 --- /dev/null +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sanitize_string.go @@ -0,0 +1,7 @@ +package crypto + +import "strings" + +func sanitizeString(input string) string { + return strings.ToValidUTF8(input, "\ufffd") +} diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey.go index 481e505b..a523fce8 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey.go @@ -138,17 +138,7 @@ func newSessionKeyFromEncrypted(ek *packet.EncryptedKey) (*SessionKey, error) { // * message : The plain data as a PlainMessage. // * output : The encrypted data as PGPMessage. func (sk *SessionKey) Encrypt(message *PlainMessage) ([]byte, error) { - dc, err := sk.GetCipherFunc() - if err != nil { - return nil, errors.Wrap(err, "gopenpgp: unable to encrypt with session key") - } - - config := &packet.Config{ - Time: getTimeGenerator(), - DefaultCipher: dc, - } - - return encryptWithSessionKey(message, sk, nil, config) + return encryptWithSessionKey(message, sk, nil, false, nil) } // EncryptAndSign encrypts a PlainMessage to PGPMessage with a SessionKey and signs it with a Private key. @@ -156,59 +146,50 @@ func (sk *SessionKey) Encrypt(message *PlainMessage) ([]byte, error) { // * signKeyRing: The KeyRing to sign the message // * output : The encrypted data as PGPMessage. func (sk *SessionKey) EncryptAndSign(message *PlainMessage, signKeyRing *KeyRing) ([]byte, error) { - dc, err := sk.GetCipherFunc() - if err != nil { - return nil, errors.Wrap(err, "gopenpgp: unable to encrypt with session key") - } + return encryptWithSessionKey(message, sk, signKeyRing, false, nil) +} - config := &packet.Config{ - Time: getTimeGenerator(), - DefaultCipher: dc, - } - - signEntity, err := signKeyRing.getSigningEntity() - if err != nil { - return nil, errors.Wrap(err, "gopenpgp: unable to sign") - } - - return encryptWithSessionKey(message, sk, signEntity, config) +// EncryptAndSignWithContext encrypts a PlainMessage to PGPMessage with a SessionKey and signs it with a Private key. +// * message : The plain data as a PlainMessage. +// * signKeyRing: The KeyRing to sign the message +// * output : The encrypted data as PGPMessage. +// * signingContext : (optional) the context for the signature. +func (sk *SessionKey) EncryptAndSignWithContext(message *PlainMessage, signKeyRing *KeyRing, signingContext *SigningContext) ([]byte, error) { + return encryptWithSessionKey(message, sk, signKeyRing, false, signingContext) } // EncryptWithCompression encrypts with compression support a PlainMessage to PGPMessage with a SessionKey. // * message : The plain data as a PlainMessage. // * output : The encrypted data as PGPMessage. func (sk *SessionKey) EncryptWithCompression(message *PlainMessage) ([]byte, error) { - dc, err := sk.GetCipherFunc() - if err != nil { - return nil, errors.Wrap(err, "gopenpgp: unable to encrypt with session key") - } - - config := &packet.Config{ - Time: getTimeGenerator(), - DefaultCipher: dc, - DefaultCompressionAlgo: constants.DefaultCompression, - CompressionConfig: &packet.CompressionConfig{Level: constants.DefaultCompressionLevel}, - } - - return encryptWithSessionKey(message, sk, nil, config) + return encryptWithSessionKey(message, sk, nil, true, nil) } -func encryptWithSessionKey(message *PlainMessage, sk *SessionKey, signEntity *openpgp.Entity, config *packet.Config) ([]byte, error) { +func encryptWithSessionKey( + message *PlainMessage, + sk *SessionKey, + signKeyRing *KeyRing, + compress bool, + signingContext *SigningContext, +) ([]byte, error) { var encBuf = new(bytes.Buffer) encryptWriter, signWriter, err := encryptStreamWithSessionKey( - message.IsBinary(), - message.Filename, - message.Time, + NewPlainMessageMetadata( + message.IsBinary(), + message.Filename, + int64(message.Time), + ), encBuf, sk, - signEntity, - config, + signKeyRing, + compress, + signingContext, ) if err != nil { return nil, err } - if signEntity != nil { + if signKeyRing != nil { _, err = signWriter.Write(message.GetBinary()) if err != nil { return nil, errors.Wrap(err, "gopenpgp: error in writing signed message") @@ -231,6 +212,61 @@ func encryptWithSessionKey(message *PlainMessage, sk *SessionKey, signEntity *op } func encryptStreamWithSessionKey( + plainMessageMetadata *PlainMessageMetadata, + dataPacketWriter io.Writer, + sk *SessionKey, + signKeyRing *KeyRing, + compress bool, + signingContext *SigningContext, +) (encryptWriter, signWriter io.WriteCloser, err error) { + dc, err := sk.GetCipherFunc() + if err != nil { + return nil, nil, errors.Wrap(err, "gopenpgp: unable to encrypt with session key") + } + + config := &packet.Config{ + Time: getTimeGenerator(), + DefaultCipher: dc, + } + + var signEntity *openpgp.Entity + if signKeyRing != nil { + signEntity, err = signKeyRing.getSigningEntity() + if err != nil { + return nil, nil, errors.Wrap(err, "gopenpgp: unable to sign") + } + } + + if compress { + config.DefaultCompressionAlgo = constants.DefaultCompression + config.CompressionConfig = &packet.CompressionConfig{Level: constants.DefaultCompressionLevel} + } + + if signingContext != nil { + config.SignatureNotations = append(config.SignatureNotations, signingContext.getNotation()) + } + + if plainMessageMetadata == nil { + // Use sensible default metadata + plainMessageMetadata = &PlainMessageMetadata{ + IsBinary: true, + Filename: "", + ModTime: GetUnixTime(), + } + } + + return encryptStreamWithSessionKeyAndConfig( + plainMessageMetadata.IsBinary, + plainMessageMetadata.Filename, + uint32(plainMessageMetadata.ModTime), + dataPacketWriter, + sk, + signEntity, + config, + ) +} + +func encryptStreamWithSessionKeyAndConfig( isBinary bool, filename string, modTime uint32, @@ -239,7 +275,15 @@ func encryptStreamWithSessionKey( signEntity *openpgp.Entity, config *packet.Config, ) (encryptWriter, signWriter io.WriteCloser, err error) { - encryptWriter, err = packet.SerializeSymmetricallyEncrypted(dataPacketWriter, config.Cipher(), sk.Key, config) + encryptWriter, err = packet.SerializeSymmetricallyEncrypted( + dataPacketWriter, + config.Cipher(), + config.AEAD() != nil, + packet.CipherSuite{Cipher: config.Cipher(), Mode: config.AEAD().Mode()}, + sk.Key, + config, + ) + if err != nil { return nil, nil, errors.Wrap(err, "gopenpgp: unable to encrypt") } @@ -289,9 +333,41 @@ func (sk *SessionKey) Decrypt(dataPacket []byte) (*PlainMessage, error) { // * verifyTime: when should the signature be valid, as timestamp. If 0 time verification is disabled. // * output: PlainMessage. func (sk *SessionKey) DecryptAndVerify(dataPacket []byte, verifyKeyRing *KeyRing, verifyTime int64) (*PlainMessage, error) { + return decryptWithSessionKeyAndContext( + sk, + dataPacket, + verifyKeyRing, + verifyTime, + nil, + ) +} + +// DecryptAndVerifyWithContext decrypts pgp data packets using directly a session key and verifies embedded signatures. +// * encrypted: PGPMessage. +// * verifyKeyRing: KeyRing with verification public keys +// * verifyTime: when should the signature be valid, as timestamp. If 0 time verification is disabled. +// * output: PlainMessage. +// * verificationContext (optional): context for the signature verification. +func (sk *SessionKey) DecryptAndVerifyWithContext(dataPacket []byte, verifyKeyRing *KeyRing, verifyTime int64, verificationContext *VerificationContext) (*PlainMessage, error) { + return decryptWithSessionKeyAndContext( + sk, + dataPacket, + verifyKeyRing, + verifyTime, + verificationContext, + ) +} + +func decryptWithSessionKeyAndContext( + sk *SessionKey, + dataPacket []byte, + verifyKeyRing *KeyRing, + verifyTime int64, + verificationContext *VerificationContext, +) (*PlainMessage, error) { var messageReader = bytes.NewReader(dataPacket) - md, err := decryptStreamWithSessionKey(sk, messageReader, verifyKeyRing) + md, err := decryptStreamWithSessionKey(sk, messageReader, verifyKeyRing, verificationContext) if err != nil { return nil, err } @@ -303,7 +379,7 @@ func (sk *SessionKey) DecryptAndVerify(dataPacket []byte, verifyKeyRing *KeyRing if verifyKeyRing != nil { processSignatureExpiration(md, verifyTime) - err = verifyDetailsSignature(md, verifyKeyRing) + err = verifyDetailsSignature(md, verifyKeyRing, verificationContext) } return &PlainMessage{ @@ -314,7 +390,12 @@ func (sk *SessionKey) DecryptAndVerify(dataPacket []byte, verifyKeyRing *KeyRing }, err } -func decryptStreamWithSessionKey(sk *SessionKey, messageReader io.Reader, verifyKeyRing *KeyRing) (*openpgp.MessageDetails, error) { +func decryptStreamWithSessionKey( + sk *SessionKey, + messageReader io.Reader, + verifyKeyRing *KeyRing, + verificationContext *VerificationContext, +) (*openpgp.MessageDetails, error) { var decrypted io.ReadCloser var keyring openpgp.EntityList @@ -327,17 +408,24 @@ func decryptStreamWithSessionKey(sk *SessionKey, messageReader io.Reader, verify // Decrypt data packet switch p := p.(type) { - case *packet.SymmetricallyEncrypted: + case *packet.SymmetricallyEncrypted, *packet.AEADEncrypted: + if symPacket, ok := p.(*packet.SymmetricallyEncrypted); ok { + if !symPacket.IntegrityProtected { + return nil, errors.New("gopenpgp: message is not authenticated") + } + } dc, err := sk.GetCipherFunc() if err != nil { return nil, errors.Wrap(err, "gopenpgp: unable to decrypt with session key") } - - decrypted, err = p.Decrypt(dc, sk.Key) + encryptedDataPacket, isDataPacket := p.(packet.EncryptedDataPacket) + if !isDataPacket { + return nil, errors.Wrap(err, "gopenpgp: unknown data packet") + } + decrypted, err = encryptedDataPacket.Decrypt(dc, sk.Key) if err != nil { return nil, errors.Wrap(err, "gopenpgp: unable to decrypt symmetric packet") } - default: return nil, errors.New("gopenpgp: invalid packet type") } @@ -346,6 +434,10 @@ func decryptStreamWithSessionKey(sk *SessionKey, messageReader io.Reader, verify Time: getTimeGenerator(), } + if verificationContext != nil { + config.KnownNotations = map[string]bool{constants.SignatureContextName: true} + } + // Push decrypted packet as literal packet and use openpgp's reader if verifyKeyRing != nil { keyring = verifyKeyRing.entities diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey_streaming.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey_streaming.go index 02e80ab4..200ca639 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey_streaming.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/sessionkey_streaming.go @@ -1,8 +1,6 @@ package crypto import ( - "github.com/ProtonMail/go-crypto/openpgp" - "github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/pkg/errors" ) @@ -30,40 +28,87 @@ func (sk *SessionKey) EncryptStream( plainMessageMetadata *PlainMessageMetadata, signKeyRing *KeyRing, ) (plainMessageWriter WriteCloser, err error) { - dc, err := sk.GetCipherFunc() - if err != nil { - return nil, errors.Wrap(err, "gopenpgp: unable to encrypt with session key") - } + return sk.encryptStream( + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + false, + nil, + ) +} - config := &packet.Config{ - Time: getTimeGenerator(), - DefaultCipher: dc, - } - var signEntity *openpgp.Entity - if signKeyRing != nil { - signEntity, err = signKeyRing.getSigningEntity() - if err != nil { - return nil, errors.Wrap(err, "gopenpgp: unable to sign") - } - } +// EncryptStreamWithContext is used to encrypt data as a Writer. +// It takes a writer for the encrypted data packet and returns a writer for the plaintext data. +// If signKeyRing is not nil, it is used to do an embedded signature. +// * signingContext : (optional) the context for the signature. +func (sk *SessionKey) EncryptStreamWithContext( + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + signingContext *SigningContext, +) (plainMessageWriter WriteCloser, err error) { + return sk.encryptStream( + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + false, + signingContext, + ) +} - if plainMessageMetadata == nil { - // Use sensible default metadata - plainMessageMetadata = &PlainMessageMetadata{ - IsBinary: true, - Filename: "", - ModTime: GetUnixTime(), - } - } +// EncryptStreamWithCompression is used to encrypt data as a Writer. +// The plaintext data is compressed before being encrypted. +// It takes a writer for the encrypted data packet and returns a writer for the plaintext data. +// If signKeyRing is not nil, it is used to do an embedded signature. +// * signingContext : (optional) the context for the signature. +func (sk *SessionKey) EncryptStreamWithCompression( + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, +) (plainMessageWriter WriteCloser, err error) { + return sk.encryptStream( + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + true, + nil, + ) +} +// EncryptStreamWithContextAndCompression is used to encrypt data as a Writer. +// The plaintext data is compressed before being encrypted. +// It takes a writer for the encrypted data packet and returns a writer for the plaintext data. +// If signKeyRing is not nil, it is used to do an embedded signature. +// * signingContext : (optional) the context for the signature. +func (sk *SessionKey) EncryptStreamWithContextAndCompression( + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + signingContext *SigningContext, +) (plainMessageWriter WriteCloser, err error) { + return sk.encryptStream( + dataPacketWriter, + plainMessageMetadata, + signKeyRing, + true, + signingContext, + ) +} + +func (sk *SessionKey) encryptStream( + dataPacketWriter Writer, + plainMessageMetadata *PlainMessageMetadata, + signKeyRing *KeyRing, + compress bool, + signingContext *SigningContext, +) (plainMessageWriter WriteCloser, err error) { encryptWriter, signWriter, err := encryptStreamWithSessionKey( - plainMessageMetadata.IsBinary, - plainMessageMetadata.Filename, - uint32(plainMessageMetadata.ModTime), + plainMessageMetadata, dataPacketWriter, sk, - signEntity, - config, + signKeyRing, + compress, + signingContext, ) if err != nil { @@ -87,10 +132,48 @@ func (sk *SessionKey) DecryptStream( verifyKeyRing *KeyRing, verifyTime int64, ) (plainMessage *PlainMessageReader, err error) { - messageDetails, err := decryptStreamWithSessionKey( + return decryptStreamWithSessionKeyAndContext( sk, dataPacketReader, verifyKeyRing, + verifyTime, + nil, + ) +} + +// DecryptStreamWithContext is used to decrypt a data packet as a Reader. +// It takes a reader for the data packet +// and returns a PlainMessageReader for the plaintext data. +// If verifyKeyRing is not nil, PlainMessageReader.VerifySignature() will +// verify the embedded signature with the given key ring and verification time. +// * verificationContext (optional): context for the signature verification. +func (sk *SessionKey) DecryptStreamWithContext( + dataPacketReader Reader, + verifyKeyRing *KeyRing, + verifyTime int64, + verificationContext *VerificationContext, +) (plainMessage *PlainMessageReader, err error) { + return decryptStreamWithSessionKeyAndContext( + sk, + dataPacketReader, + verifyKeyRing, + verifyTime, + verificationContext, + ) +} + +func decryptStreamWithSessionKeyAndContext( + sessionKey *SessionKey, + dataPacketReader Reader, + verifyKeyRing *KeyRing, + verifyTime int64, + verificationContext *VerificationContext, +) (plainMessage *PlainMessageReader, err error) { + messageDetails, err := decryptStreamWithSessionKey( + sessionKey, + dataPacketReader, + verifyKeyRing, + verificationContext, ) if err != nil { return nil, errors.Wrap(err, "gopenpgp: error in reading message") @@ -101,5 +184,6 @@ func (sk *SessionKey) DecryptStream( verifyKeyRing, verifyTime, false, + verificationContext, }, err } diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature.go index 67c1d7c2..f5c58ab3 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature.go @@ -3,7 +3,6 @@ package crypto import ( "bytes" "crypto" - "errors" "fmt" "io" "math" @@ -12,6 +11,7 @@ import ( "github.com/ProtonMail/go-crypto/openpgp" pgpErrors "github.com/ProtonMail/go-crypto/openpgp/errors" "github.com/ProtonMail/go-crypto/openpgp/packet" + "github.com/pkg/errors" "github.com/ProtonMail/gopenpgp/v2/constants" "github.com/ProtonMail/gopenpgp/v2/internal" @@ -29,23 +29,41 @@ var allowedHashes = []crypto.Hash{ type SignatureVerificationError struct { Status int Message string + Cause error } // Error is the base method for all errors. func (e SignatureVerificationError) Error() string { + if e.Cause != nil { + return fmt.Sprintf("Signature Verification Error: %v caused by %v", e.Message, e.Cause) + } return fmt.Sprintf("Signature Verification Error: %v", e.Message) } +// Unwrap returns the cause of failure. +func (e SignatureVerificationError) Unwrap() error { + return e.Cause +} + // ------------------ // Internal functions // ------------------ // newSignatureFailed creates a new SignatureVerificationError, type // SignatureFailed. -func newSignatureFailed() SignatureVerificationError { +func newSignatureBadContext(cause error) SignatureVerificationError { + return SignatureVerificationError{ + Status: constants.SIGNATURE_BAD_CONTEXT, + Message: "Invalid signature context", + Cause: cause, + } +} + +func newSignatureFailed(cause error) SignatureVerificationError { return SignatureVerificationError{ Status: constants.SIGNATURE_FAILED, Message: "Invalid signature", + Cause: cause, } } @@ -98,7 +116,7 @@ func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) { } // verifyDetailsSignature verifies signature from message details. -func verifyDetailsSignature(md *openpgp.MessageDetails, verifierKey *KeyRing) error { +func verifyDetailsSignature(md *openpgp.MessageDetails, verifierKey *KeyRing, verificationContext *VerificationContext) error { if !md.IsSigned { return newSignatureNotSigned() } @@ -108,18 +126,113 @@ func verifyDetailsSignature(md *openpgp.MessageDetails, verifierKey *KeyRing) er return newSignatureNoVerifier() } if md.SignatureError != nil { - return newSignatureFailed() + return newSignatureFailed(md.SignatureError) } if md.Signature == nil || md.Signature.Hash < allowedHashes[0] || md.Signature.Hash > allowedHashes[len(allowedHashes)-1] { return newSignatureInsecure() } + if verificationContext != nil { + err := verificationContext.verifyContext(md.Signature) + if err != nil { + return newSignatureBadContext(err) + } + } + + return nil +} + +// SigningContext gives the context that will be +// included in the signature's notation data. +type SigningContext struct { + Value string + IsCritical bool +} + +// NewSigningContext creates a new signing context. +// The value is set to the notation data. +// isCritical controls whether the notation is flagged as a critical packet. +func NewSigningContext(value string, isCritical bool) *SigningContext { + return &SigningContext{Value: value, IsCritical: isCritical} +} + +func (context *SigningContext) getNotation() *packet.Notation { + return &packet.Notation{ + Name: constants.SignatureContextName, + Value: []byte(context.Value), + IsCritical: context.IsCritical, + IsHumanReadable: true, + } +} + +// VerificationContext gives the context that will be +// used to verify the signature. +type VerificationContext struct { + Value string + IsRequired bool + RequiredAfter int64 +} + +// NewVerificationContext creates a new verification context. +// The value is checked against the signature's notation data. +// If isRequired is false, the signature is allowed to have no context set. +// If requiredAfter is != 0, the signature is allowed to have no context set if it +// was created before the unix time set in requiredAfter. +func NewVerificationContext(value string, isRequired bool, requiredAfter int64) *VerificationContext { + return &VerificationContext{ + Value: value, + IsRequired: isRequired, + RequiredAfter: requiredAfter, + } +} + +func (context *VerificationContext) isRequiredAtTime(signatureTime time.Time) bool { + return context.IsRequired && + (context.RequiredAfter == 0 || signatureTime.After(time.Unix(context.RequiredAfter, 0))) +} + +func findContext(notations []*packet.Notation) (string, error) { + context := "" + for _, notation := range notations { + if notation.Name == constants.SignatureContextName { + if context != "" { + return "", errors.New("gopenpgp: signature has multiple context notations") + } + if !notation.IsHumanReadable { + return "", errors.New("gopenpgp: context notation was not set as human-readable") + } + context = string(notation.Value) + } + } + return context, nil +} + +func (context *VerificationContext) verifyContext(sig *packet.Signature) error { + signatureContext, err := findContext(sig.Notations) + if err != nil { + return err + } + if signatureContext != context.Value { + contextRequired := context.isRequiredAtTime(sig.CreationTime) + if contextRequired { + return errors.New("gopenpgp: signature did not have the required context") + } else if signatureContext != "" { + return errors.New("gopenpgp: signature had a wrong context") + } + } + return nil } // verifySignature verifies if a signature is valid with the entity list. -func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signature []byte, verifyTime int64) error { +func verifySignature( + pubKeyEntries openpgp.EntityList, + origText io.Reader, + signature []byte, + verifyTime int64, + verificationContext *VerificationContext, +) (*packet.Signature, error) { config := &packet.Config{} if verifyTime == 0 { config.Time = func() time.Time { @@ -130,32 +243,90 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signa return time.Unix(verifyTime+internal.CreationTimeOffset, 0) } } + + if verificationContext != nil { + config.KnownNotations = map[string]bool{constants.SignatureContextName: true} + } signatureReader := bytes.NewReader(signature) - signer, err := openpgp.CheckDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config) + sig, signer, err := openpgp.VerifyDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config) - if errors.Is(err, pgpErrors.ErrSignatureExpired) && signer != nil && verifyTime > 0 { - // if verifyTime = 0: time check disabled, everything is okay - // Maybe the creation time offset pushed it over the edge - // Retry with the actual verification time - config.Time = func() time.Time { - return time.Unix(verifyTime, 0) - } + if sig != nil && signer != nil && (errors.Is(err, pgpErrors.ErrSignatureExpired) || errors.Is(err, pgpErrors.ErrKeyExpired)) { //nolint:nestif + if verifyTime == 0 { // Expiration check disabled + err = nil + } else { + // Maybe the creation time offset pushed it over the edge + // Retry with the actual verification time + config.Time = func() time.Time { + return time.Unix(verifyTime, 0) + } - _, err = signatureReader.Seek(0, io.SeekStart) - if err != nil { - return newSignatureFailed() - } + seeker, ok := origText.(io.ReadSeeker) + if !ok { + return nil, errors.Wrap(err, "gopenpgp: message reader do not support seeking, cannot retry signature verification") + } - signer, err = openpgp.CheckDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config) - if err != nil { - return newSignatureFailed() + _, err = seeker.Seek(0, io.SeekStart) + if err != nil { + return nil, newSignatureFailed(errors.Wrap(err, "gopenpgp: could not rewind the data reader.")) + } + + _, err = signatureReader.Seek(0, io.SeekStart) + if err != nil { + return nil, newSignatureFailed(err) + } + + sig, signer, err = openpgp.VerifyDetachedSignatureAndHash(pubKeyEntries, seeker, signatureReader, allowedHashes, config) } } - if signer == nil { - return newSignatureFailed() + if err != nil { + return nil, newSignatureFailed(err) } - return nil + if sig == nil || signer == nil { + return nil, newSignatureFailed(errors.New("gopenpgp: no signer or valid signature")) + } + + if verificationContext != nil { + err := verificationContext.verifyContext(sig) + if err != nil { + return nil, newSignatureBadContext(err) + } + } + + return sig, nil +} + +func signMessageDetached( + signKeyRing *KeyRing, + messageReader io.Reader, + isBinary bool, + context *SigningContext, +) (*PGPSignature, error) { + config := &packet.Config{ + DefaultHash: crypto.SHA512, + Time: getTimeGenerator(), + } + + signEntity, err := signKeyRing.getSigningEntity() + if err != nil { + return nil, err + } + + if context != nil { + config.SignatureNotations = append(config.SignatureNotations, context.getNotation()) + } + + var outBuf bytes.Buffer + if isBinary { + err = openpgp.DetachSign(&outBuf, signEntity, messageReader, config) + } else { + err = openpgp.DetachSignText(&outBuf, signEntity, messageReader, config) + } + if err != nil { + return nil, errors.Wrap(err, "gopenpgp: error in signing") + } + + return NewPGPSignature(outBuf.Bytes()), nil } diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature_collector.go b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature_collector.go index b5aefa62..fb769a91 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature_collector.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/crypto/signature_collector.go @@ -99,7 +99,7 @@ func (sc *SignatureCollector) Accept( } sc.signature = string(buffer) str, _ := ioutil.ReadAll(rawBody) - canonicalizedBody := internal.CanonicalizeAndTrim(string(str)) + canonicalizedBody := internal.Canonicalize(internal.TrimEachLine(string(str))) rawBody = bytes.NewReader([]byte(canonicalizedBody)) if sc.keyring != nil { _, err = openpgp.CheckArmoredDetachedSignature(sc.keyring, rawBody, bytes.NewReader(buffer), sc.config) @@ -110,7 +110,7 @@ func (sc *SignatureCollector) Accept( case errors.Is(err, pgpErrors.ErrUnknownIssuer): sc.verified = newSignatureNoVerifier() default: - sc.verified = newSignatureFailed() + sc.verified = newSignatureFailed(err) } } else { sc.verified = newSignatureNoVerifier() diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/BUILD.bazel b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/BUILD.bazel index e5b0719a..3a558f88 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/BUILD.bazel +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/BUILD.bazel @@ -4,8 +4,10 @@ go_library( name = "helper", srcs = [ "cleartext.go", + "decrypt_check.go", "helper.go", "key.go", + "message.go", "mobile.go", "mobile_stream.go", "sign_detached.go", @@ -15,6 +17,8 @@ go_library( visibility = ["//visibility:public"], deps = [ "//vendor/github.com/ProtonMail/gopenpgp/v2/crypto", + "//vendor/github.com/ProtonMail/gopenpgp/v2/internal", "//vendor/github.com/pkg/errors", + "@com_github_protonmail_go_crypto//openpgp/packet", ], ) diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/cleartext.go b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/cleartext.go index c3187391..d5517b16 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/cleartext.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/cleartext.go @@ -2,6 +2,7 @@ package helper import ( "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/ProtonMail/gopenpgp/v2/internal" "github.com/pkg/errors" ) @@ -48,7 +49,7 @@ func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) // SignCleartextMessage signs text given a private keyring, canonicalizes and // trims the newlines, and returns the PGP-compliant special armoring. func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error) { - message := crypto.NewPlainMessageFromString(text) + message := crypto.NewPlainMessageFromString(internal.TrimEachLine(text)) signature, err := keyRing.SignDetached(message) if err != nil { @@ -67,7 +68,7 @@ func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime return "", errors.Wrap(err, "gopengpp: unable to unarmor cleartext message") } - message := crypto.NewPlainMessageFromString(clearTextMessage.GetString()) + message := crypto.NewPlainMessageFromString(internal.TrimEachLine(clearTextMessage.GetString())) signature := crypto.NewPGPSignature(clearTextMessage.GetBinarySignature()) err = keyRing.VerifyDetached(message, signature, verifyTime) if err != nil { diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/decrypt_check.go b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/decrypt_check.go new file mode 100644 index 00000000..eeff1089 --- /dev/null +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/decrypt_check.go @@ -0,0 +1,86 @@ +package helper + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "io" + + "github.com/ProtonMail/go-crypto/openpgp/packet" + "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/pkg/errors" +) + +const AES_BLOCK_SIZE = 16 + +func supported(cipher packet.CipherFunction) bool { + switch cipher { + case packet.CipherAES128, packet.CipherAES192, packet.CipherAES256: + return true + case packet.CipherCAST5, packet.Cipher3DES: + return false + } + return false +} + +func blockSize(cipher packet.CipherFunction) int { + switch cipher { + case packet.CipherAES128, packet.CipherAES192, packet.CipherAES256: + return AES_BLOCK_SIZE + case packet.CipherCAST5, packet.Cipher3DES: + return 0 + } + return 0 +} + +func blockCipher(cipher packet.CipherFunction, key []byte) (cipher.Block, error) { + switch cipher { + case packet.CipherAES128, packet.CipherAES192, packet.CipherAES256: + return aes.NewCipher(key) + case packet.CipherCAST5, packet.Cipher3DES: + return nil, errors.New("gopenpgp: cipher not supported for quick check") + } + return nil, errors.New("gopenpgp: unknown cipher") +} + +// QuickCheckDecryptReader checks with high probability if the provided session key +// can decrypt a data packet given its 24 byte long prefix. +// The method reads up to but not exactly 24 bytes from the prefixReader. +// NOTE: Only works for SEIPDv1 packets with AES. +func QuickCheckDecryptReader(sessionKey *crypto.SessionKey, prefixReader crypto.Reader) (bool, error) { + algo, err := sessionKey.GetCipherFunc() + if err != nil { + return false, errors.New("gopenpgp: cipher algorithm not found") + } + if !supported(algo) { + return false, errors.New("gopenpgp: cipher not supported for quick check") + } + packetParser := packet.NewReader(prefixReader) + _, err = packetParser.Next() + if err != nil { + return false, errors.New("gopenpgp: failed to parse packet prefix") + } + + blockSize := blockSize(algo) + encryptedData := make([]byte, blockSize+2) + _, err = io.ReadFull(prefixReader, encryptedData) + if err != nil { + return false, errors.New("gopenpgp: prefix is too short to check") + } + + blockCipher, err := blockCipher(algo, sessionKey.Key) + if err != nil { + return false, errors.New("gopenpgp: failed to initialize the cipher") + } + _ = packet.NewOCFBDecrypter(blockCipher, encryptedData, packet.OCFBNoResync) + return encryptedData[blockSize-2] == encryptedData[blockSize] && + encryptedData[blockSize-1] == encryptedData[blockSize+1], nil +} + +// QuickCheckDecrypt checks with high probability if the provided session key +// can decrypt the encrypted data packet given its 24 byte long prefix. +// The method only considers the first 24 bytes of the prefix slice (prefix[:24]). +// NOTE: Only works for SEIPDv1 packets with AES. +func QuickCheckDecrypt(sessionKey *crypto.SessionKey, prefix []byte) (bool, error) { + return QuickCheckDecryptReader(sessionKey, bytes.NewReader(prefix)) +} diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/message.go b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/message.go new file mode 100644 index 00000000..b4e58ff0 --- /dev/null +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/message.go @@ -0,0 +1,22 @@ +package helper + +import "github.com/ProtonMail/gopenpgp/v2/crypto" + +// EncryptPGPMessageToAdditionalKey decrypts the session key of the input PGPSplitMessage with a private key in keyRing +// and encrypts it towards the additionalKeys by adding the additional key packets to the input PGPSplitMessage. +// If successful, new key packets are added to message. +// * messageToModify : The encrypted pgp message that should be modified +// * keyRing : The private keys to decrypt the session key in the messageToModify. +// * additionalKey : The public keys the message should be additionally encrypted to. +func EncryptPGPMessageToAdditionalKey(messageToModify *crypto.PGPSplitMessage, keyRing *crypto.KeyRing, additionalKey *crypto.KeyRing) error { + sessionKey, err := keyRing.DecryptSessionKey(messageToModify.KeyPacket) + if err != nil { + return err + } + additionalKeyPacket, err := additionalKey.EncryptSessionKey(sessionKey) + if err != nil { + return err + } + messageToModify.KeyPacket = append(messageToModify.KeyPacket, additionalKeyPacket...) + return nil +} diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/mobile.go b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/mobile.go index d4cd9ada..a08d81d9 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/helper/mobile.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/helper/mobile.go @@ -26,6 +26,20 @@ func DecryptExplicitVerify( return newExplicitVerifyMessage(message, err) } +// DecryptExplicitVerifyWithContext decrypts a PGP message given a private keyring +// and a public keyring to verify the embedded signature. Returns the plain +// data and an error on signature verification failure. +// The caller can provide a context that will be used to verify the signature. +func DecryptExplicitVerifyWithContext( + pgpMessage *crypto.PGPMessage, + privateKeyRing, publicKeyRing *crypto.KeyRing, + verifyTime int64, + verificationContext *crypto.VerificationContext, +) (*ExplicitVerifyMessage, error) { + message, err := privateKeyRing.DecryptWithContext(pgpMessage, publicKeyRing, verifyTime, verificationContext) + return newExplicitVerifyMessage(message, err) +} + // DecryptSessionKeyExplicitVerify decrypts a PGP data packet given a session key // and a public keyring to verify the embedded signature. Returns the plain data and // an error on signature verification failure. @@ -39,6 +53,21 @@ func DecryptSessionKeyExplicitVerify( return newExplicitVerifyMessage(message, err) } +// DecryptSessionKeyExplicitVerifyWithContext decrypts a PGP data packet given a session key +// and a public keyring to verify the embedded signature. Returns the plain data and +// an error on signature verification failure. +// The caller can provide a context that will be used to verify the signature. +func DecryptSessionKeyExplicitVerifyWithContext( + dataPacket []byte, + sessionKey *crypto.SessionKey, + publicKeyRing *crypto.KeyRing, + verifyTime int64, + verificationContext *crypto.VerificationContext, +) (*ExplicitVerifyMessage, error) { + message, err := sessionKey.DecryptAndVerifyWithContext(dataPacket, publicKeyRing, verifyTime, verificationContext) + return newExplicitVerifyMessage(message, err) +} + func newExplicitVerifyMessage(message *crypto.PlainMessage, err error) (*ExplicitVerifyMessage, error) { var explicitVerify *ExplicitVerifyMessage if err != nil { diff --git a/vendor/github.com/ProtonMail/gopenpgp/v2/internal/common.go b/vendor/github.com/ProtonMail/gopenpgp/v2/internal/common.go index 9704cd01..534b33d2 100644 --- a/vendor/github.com/ProtonMail/gopenpgp/v2/internal/common.go +++ b/vendor/github.com/ProtonMail/gopenpgp/v2/internal/common.go @@ -7,14 +7,18 @@ import ( "github.com/ProtonMail/gopenpgp/v2/constants" ) -func CanonicalizeAndTrim(text string) string { +func Canonicalize(text string) string { + return strings.ReplaceAll(strings.ReplaceAll(text, "\r\n", "\n"), "\n", "\r\n") +} + +func TrimEachLine(text string) string { lines := strings.Split(text, "\n") for i := range lines { lines[i] = strings.TrimRight(lines[i], " \t\r") } - return strings.Join(lines, "\r\n") + return strings.Join(lines, "\n") } // CreationTimeOffset stores the amount of seconds that a signature may be diff --git a/vendor/modules.txt b/vendor/modules.txt index e9279281..b6d2ccab 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -76,10 +76,10 @@ github.com/ProtonMail/go-crypto/openpgp/internal/ecc github.com/ProtonMail/go-crypto/openpgp/internal/encoding github.com/ProtonMail/go-crypto/openpgp/packet github.com/ProtonMail/go-crypto/openpgp/s2k -# github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f +# github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f ## explicit; go 1.12 github.com/ProtonMail/go-mime -# github.com/ProtonMail/gopenpgp/v2 v2.4.7 +# github.com/ProtonMail/gopenpgp/v2 v2.7.5 ## explicit; go 1.15 github.com/ProtonMail/gopenpgp/v2/armor github.com/ProtonMail/gopenpgp/v2/constants