Skip to content

crypto/x509: Certificate no longer encodable using encoding/gob in Go1.22 #65633

Description

@VictorLowther

Go version

go 1.22.0 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/victor/.cache/go-build'
GOENV='/home/victor/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/victor/go/pkg/mod'
GONOPROXY='gitlab.com/rackn'
GONOSUMDB='gitlab.com/rackn'
GOOS='linux'
GOPATH='/home/victor/go'
GOPRIVATE='gitlab.com/rackn'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.0'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2733416375=/tmp/go-build -gno-record-gcc-switches'

What did you do?

A project of mine directly embeds the *x509.Certificate struct in a larger struct, which is encoded and decoded using encoding/gob. The struct added fields that use a new x509.OID structure, which contains a single non-exported field.

Test program is here on the Go playground. Running it under Go 1.22 displays the error, and running it under Go 1.21 does not.

What did you see happen?

go run main.go
2024/02/09 08:42:03 Failed to gob encode enpty x.509 cert: gob: type x509.OID has no exported fields

What did you expect to see?

go run main.go
2024/02/09 08:41:47 Encoded empty x.509 cert

Adding MarshalBinary and UnmarshalBinary methods to *x509.OID allows encoding to succeed. Patch against 1.22.0:

diff --git a/src/crypto/x509/oid.go b/src/crypto/x509/oid.go
index 5359af624b..0e2b872539 100644
--- a/src/crypto/x509/oid.go
+++ b/src/crypto/x509/oid.go
@@ -24,6 +24,15 @@ type OID struct {
        der []byte
 }

+func (o *OID) MarshalBinary() ([]byte, error) {
+       return append([]byte{}, o.der...), nil
+}
+
+func (o *OID) UnmarshalBinary(b []byte) error {
+       o.der = append(o.der[:0], b...)
+       return nil
+}
+
 func newOIDFromDER(der []byte) (OID, bool) {
        if len(der) == 0 || der[len(der)-1]&0x80 != 0 {
                return OID{}, false

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions